from __future__ import annotations

import os
from pathlib import Path
from typing import Any

from .cache import read_json, write_json, envelope
from .data_gouv import DataGouvClient
from .scope import current_scope, refresh_scope
from .sources import sources_catalog


class OpenDataBroker:
    def __init__(self, base_dir: Path):
        self.base_dir = base_dir
        self.cache_dir = base_dir / os.getenv("AULA_CACHE_DIR", "data/cache")

    def sources(self) -> list[dict[str, Any]]:
        return sources_catalog()

    def scope(self) -> dict[str, Any]:
        return current_scope(self.base_dir)

    def refresh_geo_scope(self) -> dict[str, Any]:
        return refresh_scope(self.base_dir)

    def refresh_conso_enaf_metadata(self) -> dict[str, Any]:
        slug = os.getenv(
            "CONSO_ENAF_DATASET_SLUG",
            "consommation-despaces-naturels-agricoles-et-forestiers-du-1er-janvier-2009-au-1er-janvier-2024",
        )
        client = DataGouvClient()
        payload = client.dataset(slug)
        slim = client.slim_dataset(payload)
        result = envelope("data_gouv_conso_enaf", slim, metadata={"slug": slug, "base_url": client.base_url})
        write_json(self.cache_dir / "conso_enaf_metadata.json", result)
        return result

    def cached(self, name: str) -> dict[str, Any]:
        return read_json(self.cache_dir / name, default=envelope(name, None, status="missing_cache"))

    def context(self, territoire: str | None = None) -> dict[str, Any]:
        """Return a stable normalized object for the front-end.

        Real indicator values are filled when refresh scripts have written cache
        files. The front-end can already consume this contract without knowing
        whether the source came from PostGIS, API Geo, data.gouv, INSEE, SDES or
        Georisques.
        """
        return {
            "territoire": territoire,
            "scope": self.scope(),
            "sources": self.sources(),
            "sociodemo": {
                "status": "prepared_not_loaded",
                "source": "INSEE API Melodi / donnees locales",
                "indicators_ready": [
                    "population", "population_0_14", "population_15_29", "population_30_59",
                    "population_60_plus", "menages", "naissances", "projection_omphale_si_disponible",
                ],
                "cache": self.cached("insee_context.json"),
            },
            "consumption": {
                "status": "metadata_ready" if self.cached("conso_enaf_metadata.json").get("status") == "ok" else "prepared_not_loaded",
                "source": "CONSOENAF 2009-2024 / data.gouv",
                "indicators_ready": [
                    "conso_enaf_totale_ha", "conso_enaf_annuelle_ha", "conso_enaf_recent_ha",
                    "part_habitat", "rythme_moyen", "trajectoire_zan",
                ],
                "metadata": self.cached("conso_enaf_metadata.json"),
            },
            "construction": {
                "status": "prepared_not_loaded",
                "source": "SDES Sitadel / Dido",
                "indicators_ready": [
                    "logements_autorises", "logements_commences", "locaux_autorises_m2",
                    "permis_amenager", "rythme_recent_construction",
                ],
                "cache": self.cached("sitadel_context.json"),
            },
            "risks": {
                "status": "prepared_not_loaded",
                "source": "Georisques",
                "indicators_ready": ["risques_par_commune", "ppri_metadata", "pprn_pprt_metadata"],
                "note": "Les croisements batiments historiques x perimetres de risque doivent rester dans PostGIS.",
                "cache": self.cached("georisques_context.json"),
            },
        }
