#!/usr/bin/env python3
from __future__ import annotations

import gzip
import json
import time
import urllib.parse
import urllib.request
from datetime import datetime, timedelta, timezone
from pathlib import Path

ROOT = Path(__file__).resolve().parent


def dt(value: str) -> datetime:
    parsed = datetime.fromisoformat(value.replace("Z", "+00:00"))
    if parsed.tzinfo is None:
        parsed = parsed.replace(tzinfo=timezone.utc)
    return parsed.astimezone(timezone.utc)


def fetch(pair: str, start: datetime, end: datetime) -> list[dict]:
    rows = []
    cursor, end_ms = int(start.timestamp() * 1000), int(end.timestamp() * 1000)
    symbol = pair.split(":")[0].replace("/", "")
    while cursor < end_ms:
        query = urllib.parse.urlencode({"symbol": symbol, "interval": "5m", "startTime": cursor, "endTime": end_ms, "limit": 1500})
        with urllib.request.urlopen("https://fapi.binance.com/fapi/v1/klines?" + query, timeout=30) as response:
            batch = json.loads(response.read())
        if not batch:
            break
        rows.extend({"time": datetime.fromtimestamp(k[0] / 1000, tz=timezone.utc).isoformat(),
                     "open": float(k[1]), "high": float(k[2]), "low": float(k[3]),
                     "close": float(k[4]), "volume": float(k[5])} for k in batch)
        next_cursor = int(batch[-1][0]) + 300_000
        if next_cursor <= cursor:
            break
        cursor = next_cursor
        time.sleep(0.08)
    return rows


def main():
    evidence = json.loads((ROOT / "evidence.json").read_text())
    pairs = sorted({t["pair"] for t in evidence["trades"]}
                   | {x["pair"] for x in evidence["cancelled_entries"]}
                   | {x["pair"] for x in evidence["block_clusters"]})
    start = dt(evidence["window"]["start"]) - timedelta(hours=12)
    end = dt(evidence["window"]["end"]) + timedelta(hours=24)
    result = {}
    for pair in pairs:
        result[pair] = fetch(pair, start, end)
        print(pair, len(result[pair]))
    with gzip.open(ROOT / "binance-usdtm-5m.json.gz", "wt") as handle:
        json.dump(result, handle, separators=(",", ":"))


if __name__ == "__main__":
    main()
