"""GISCO NUTS-2 boundary GeoJSON extractor.

Downloads NUTS-2 boundary polygons from Eurostat GISCO. The file is stored
uncompressed because DuckDB's ST_Read cannot read gzipped files.

NUTS classification revises approximately every 7 years (current: 2021).
The partition path is fixed to the revision year, not the run date, making
the source version explicit. Cursor tracking still uses year_month to avoid
re-downloading on every monthly run.

Landing: {LANDING_DIR}/gisco/2024/01/nuts2_boundaries.geojson  (~5 MB, uncompressed)
"""

import sqlite3
from pathlib import Path

import niquests

from ._shared import HTTP_TIMEOUT_SECONDS, run_extractor, setup_logging
from .utils import skip_if_current

logger = setup_logging("padelnomics.extract.gisco")

EXTRACTOR_NAME = "gisco"

# NUTS 2021 revision, 20M scale (1:20,000,000), WGS84 (EPSG:4326), LEVL_2 only.
# 20M resolution gives simplified polygons that are fast for point-in-polygon
# matching without sacrificing accuracy at the NUTS-2 boundary level.
GISCO_URL = (
    "https://gisco-services.ec.europa.eu/distribution/v2/nuts/geojson/"
    "NUTS_RG_20M_2021_4326_LEVL_2.geojson"
)

# Fixed partition: NUTS boundaries are a static reference file, not time-series data.
# The 2024/01 partition reflects when this NUTS 2021 dataset was first ingested.
DEST_REL = Path("gisco/2024/01/nuts2_boundaries.geojson")

_GISCO_TIMEOUT_SECONDS = HTTP_TIMEOUT_SECONDS * 4  # ~5 MB; generous for slow upstreams


def extract(
    landing_dir: Path,
    year_month: str,
    conn: sqlite3.Connection,
    session: niquests.Session,
) -> dict:
    """Download NUTS-2 GeoJSON. Skips if already run this month or file exists."""
    skip = skip_if_current(conn, EXTRACTOR_NAME, year_month)
    if skip:
        logger.info("already ran for %s — skipping", year_month)
        return skip

    dest = landing_dir / DEST_REL
    if dest.exists():
        logger.info("file already exists (skipping download): %s", dest)
        return {
            "files_written": 0,
            "files_skipped": 1,
            "bytes_written": 0,
            "cursor_value": year_month,
        }

    dest.parent.mkdir(parents=True, exist_ok=True)
    logger.info("GET %s", GISCO_URL)
    resp = session.get(GISCO_URL, timeout=_GISCO_TIMEOUT_SECONDS)
    resp.raise_for_status()

    content = resp.content
    assert len(content) > 100_000, (
        f"GeoJSON too small ({len(content)} bytes) — download may have failed"
    )
    assert b'"FeatureCollection"' in content, "Response does not look like GeoJSON"

    # Write uncompressed — ST_Read requires a plain file, not .gz
    tmp = dest.with_suffix(".geojson.tmp")
    tmp.write_bytes(content)
    tmp.rename(dest)

    size_mb = len(content) / 1_000_000
    logger.info("written %s (%.1f MB)", dest, size_mb)

    return {
        "files_written": 1,
        "files_skipped": 0,
        "bytes_written": len(content),
        "cursor_value": year_month,
    }


def main() -> None:
    run_extractor(EXTRACTOR_NAME, extract)


if __name__ == "__main__":
    main()
