"""Fetch hourly precipitation for the six sites named in rule.py.

Open-Meteo's historical archive (ERA5 reanalysis), no API key. Writes one
JSON file per (site, chunk) into ~/data/rain-before-seven/ and never
re-downloads a file that is already there, so this is safe to re-run.

    python research/rain-before-seven/fetch.py

The raw data is not in git (it is ~30 MB); it is re-downloadable from the URLs
printed below, which are the whole provenance.
"""
import json
import os
import sys
import time
import urllib.parse
import urllib.request

SITES = {
    "london": (51.5072, -0.1276),
    "manchester": (53.4808, -2.2426),
    "edinburgh": (55.9533, -3.1883),
    "cardiff": (51.4816, -3.1791),
    "belfast": (54.5973, -5.9301),
    "plymouth": (50.3755, -4.1427),
}

# rule.py fixes the period at 2000-01-01..2025-12-31; chunked so no single
# request is enormous, and so a failure costs one chunk rather than a site.
CHUNKS = [
    ("2000-01-01", "2006-12-31"),
    ("2007-01-01", "2013-12-31"),
    ("2014-01-01", "2020-12-31"),
    ("2021-01-01", "2025-12-31"),
]

OUT = os.path.expanduser("~/data/rain-before-seven")
BASE = "https://archive-api.open-meteo.com/v1/archive"


def url_for(lat, lon, start, end):
    q = urllib.parse.urlencode({
        "latitude": lat,
        "longitude": lon,
        "start_date": start,
        "end_date": end,
        "hourly": "precipitation",
        "timezone": "Europe/London",
    })
    return f"{BASE}?{q}"


def main():
    os.makedirs(OUT, exist_ok=True)
    for site, (lat, lon) in SITES.items():
        for start, end in CHUNKS:
            path = os.path.join(OUT, f"{site}_{start[:4]}.json")
            if os.path.exists(path) and os.path.getsize(path) > 1000:
                print(f"have  {os.path.basename(path)}")
                continue
            u = url_for(lat, lon, start, end)
            print(f"fetch {os.path.basename(path)}  {u}")
            for attempt in range(4):
                try:
                    with urllib.request.urlopen(u, timeout=180) as r:
                        body = r.read()
                    d = json.loads(body)
                    if "hourly" not in d:
                        raise ValueError(f"no hourly block: {body[:200]!r}")
                    with open(path, "wb") as f:
                        f.write(body)
                    print(f"      {len(d['hourly']['time'])} hours")
                    break
                except Exception as e:  # noqa: BLE001 - report and retry
                    print(f"      attempt {attempt + 1} failed: {e}")
                    time.sleep(10 * (attempt + 1))
            else:
                print(f"GAVE UP on {path}")
                return 1
            time.sleep(2)
    return 0


if __name__ == "__main__":
    sys.exit(main())
