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

Eight held-out UK and Irish sites (the population the seal is scored on) and
three Pacific Northwest sites (S3, descriptive, never part of the verdict).

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

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

The raw data is not in git (~50 MB); it is re-downloadable from the URLs
printed below, which are the whole provenance.

CLOCK. rule.py fixes Europe/London for the eight (Europe/Dublin is the same
clock). It does not name a clock for the three PNW sites, because they are
descriptive; the pipeline is "the same", and the thing being measured is a
*local* morning, so they are fetched on America/Los_Angeles, which is the
civil clock of all three including Vancouver BC. That choice is recorded here
rather than made silently in the analysis.
"""
import json
import os
import sys
import time
import urllib.parse
import urllib.request

SITES = {
    "aberdeen":  (57.1497, -2.0943, "Europe/London"),
    "inverness": (57.4778, -4.2247, "Europe/London"),
    "carlisle":  (54.8925, -2.9329, "Europe/London"),
    "hull":      (53.7676, -0.3274, "Europe/London"),
    "norwich":   (52.6309,  1.2974, "Europe/London"),
    "swansea":   (51.6214, -3.9436, "Europe/London"),
    "dublin":    (53.3498, -6.2603, "Europe/London"),
    "galway":    (53.2707, -9.0568, "Europe/London"),
    "seattle":   (47.6062, -122.3321, "America/Los_Angeles"),
    "portland":  (45.5152, -122.6784, "America/Los_Angeles"),
    "vancouver": (49.2827, -123.1207, "America/Los_Angeles"),
}

# 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-replication")
BASE = "https://archive-api.open-meteo.com/v1/archive"


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


def main():
    os.makedirs(OUT, exist_ok=True)
    for site, (lat, lon, tz) 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)}", flush=True)
                continue
            u = url_for(lat, lon, tz, start, end)
            print(f"fetch {os.path.basename(path)}  {u}", flush=True)
            for attempt in range(5):
                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", flush=True)
                    break
                except Exception as e:  # noqa: BLE001 - report and retry
                    print(f"      attempt {attempt + 1} failed: {e}", flush=True)
                    time.sleep(10 * (attempt + 1))
            else:
                print(f"GAVE UP on {path}", flush=True)
                return 1
            time.sleep(2)
    print("fetch complete", flush=True)
    return 0


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