#!/usr/bin/env python3
"""Extract taxonomy data from NASA Worldview's wv.json config.

Fetches the ~51MB wv.json from Worldview and distills it into a compact
taxonomy.json (~182 KB) that maps layers to science disciplines, hazard
categories, measurements, layergroups, and search tags.

Usage:
    uv run python scripts/extract_taxonomy.py
"""

import json
import subprocess
import sys
from pathlib import Path

WV_JSON_URL = "https://worldview.earthdata.nasa.gov/config/wv.json"
OUTPUT = Path(__file__).resolve().parent.parent / "src" / "mcgibs" / "data" / "taxonomy.json"

USER_AGENT = "mcgibs-taxonomy-extractor/1.0 (ryan@supported.systems)"


def fetch_wv_json() -> dict:
    """Download wv.json from Worldview using curl (handles brotli/gzip)."""
    print(f"Fetching {WV_JSON_URL} ...", file=sys.stderr)
    result = subprocess.run(
        ["curl", "-sS", "--compressed", "-L", "-A", USER_AGENT, WV_JSON_URL],
        capture_output=True,
        timeout=120,
    )
    if result.returncode != 0:
        raise RuntimeError(f"curl failed: {result.stderr.decode()}")
    data = json.loads(result.stdout)
    print(f"  Downloaded {len(result.stdout) / 1_000_000:.1f} MB", file=sys.stderr)

    for required_key in ("categories", "measurements", "layers"):
        if required_key not in data:
            raise RuntimeError(
                f"wv.json missing expected key '{required_key}' -- "
                f"schema may have changed. Got top-level keys: {sorted(data.keys())}"
            )
    return data


def extract_taxonomy(wv: dict) -> dict:
    """Distill wv.json into a compact taxonomy structure."""
    taxonomy: dict = {
        "disciplines": {},
        "hazards": {},
        "measurements": {},
        "layers": {},
    }

    # --- Categories (disciplines + hazards) ---
    # wv.json nests categories under group keys:
    #   categories["science disciplines"]["Atmosphere"] = {title, measurements}
    #   categories["hazards and disasters"]["Fires"] = {title, measurements}
    categories = wv.get("categories", {})

    for group_key, group_data in categories.items():
        if not isinstance(group_data, dict):
            continue

        is_hazard = "hazard" in group_key.lower() or "disaster" in group_key.lower()
        target = taxonomy["hazards"] if is_hazard else taxonomy["disciplines"]

        for cat_key, cat_data in group_data.items():
            if not isinstance(cat_data, dict):
                continue

            measurements_in_cat = cat_data.get("measurements", [])
            if not measurements_in_cat:
                continue

            title = cat_data.get("title", cat_key)
            # Skip "All" meta-categories
            if title.lower() == "all":
                continue

            target[title] = measurements_in_cat

    # --- Measurements ---
    raw_measurements = wv.get("measurements", {})
    for meas_key, meas_data in raw_measurements.items():
        if not isinstance(meas_data, dict):
            continue

        sources = meas_data.get("sources", {})
        source_map = {}
        for source_name, source_info in sources.items():
            if isinstance(source_info, dict):
                settings = source_info.get("settings", [])
                # settings is a list of layer IDs
                if isinstance(settings, list):
                    source_map[source_name] = settings

        if source_map:
            taxonomy["measurements"][meas_key] = {
                "id": meas_data.get("id", meas_key.lower().replace(" ", "-")),
                "subtitle": meas_data.get("subtitle", ""),
                "sources": source_map,
            }

    # --- Per-layer data (layergroup + tags) ---
    raw_layers = wv.get("layers", {})
    for layer_id, layer_data in raw_layers.items():
        if not isinstance(layer_data, dict):
            continue

        entry = {}
        layergroup = layer_data.get("layergroup")
        if layergroup:
            entry["g"] = layergroup

        tags = layer_data.get("tags")
        if tags:
            entry["t"] = tags

        if entry:
            taxonomy["layers"][layer_id] = entry

    return taxonomy


def main():
    wv = fetch_wv_json()
    taxonomy = extract_taxonomy(wv)

    if not taxonomy["disciplines"] or not taxonomy["measurements"]:
        raise RuntimeError(
            "Extracted taxonomy is empty -- wv.json structure may have changed"
        )

    # Summary
    print(f"  Disciplines: {len(taxonomy['disciplines'])}", file=sys.stderr)
    print(f"  Hazards: {len(taxonomy['hazards'])}", file=sys.stderr)
    print(f"  Measurements: {len(taxonomy['measurements'])}", file=sys.stderr)
    print(f"  Layers with tags/group: {len(taxonomy['layers'])}", file=sys.stderr)

    OUTPUT.parent.mkdir(parents=True, exist_ok=True)
    out = json.dumps(taxonomy, indent=1, sort_keys=True)
    OUTPUT.write_text(out + "\n")

    size_kb = len(out.encode()) / 1024
    print(f"Wrote {OUTPUT} ({size_kb:.0f} KB)", file=sys.stderr)


if __name__ == "__main__":
    main()
