"""
Async HTTP-Clients für Climate TRACE, NOAA und Open-Meteo Climate APIs.
"""

import httpx
from src.config import (
    CLIMATE_TRACE_BASE_URL,
    NOAA_BASE_URL,
    NOAA_TOKEN,
    OPEN_METEO_CLIMATE_URL,
    HTTP_TIMEOUT,
)


# ─── Climate TRACE API ───────────────────────────────────────────────

async def get_country_emissions(country_code: str, year: int | None = None) -> dict:
    """
    CO2-Emissionen eines Landes via Climate TRACE abrufen.
    country_code: ISO 3166-1 alpha-3 (z.B. "DEU", "USA", "CHN")
    """
    url = f"{CLIMATE_TRACE_BASE_URL}/country/emissions"
    params: dict = {
        "countries": country_code.upper(),
        "gas": "co2",
    }
    if year:
        params["since"] = year
        params["to"] = year

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        return resp.json()


async def get_sector_emissions(
    country_code: str, sector: str, year: int | None = None
) -> dict:
    """
    Emissionen nach Sektor abrufen.
    Sektoren: power, transportation, manufacturing, agriculture, buildings,
              fossil-fuel-operations, mineral-extraction, waste, forestry-and-land-use
    """
    url = f"{CLIMATE_TRACE_BASE_URL}/country/emissions"
    params: dict = {
        "countries": country_code.upper(),
        "sector": sector.lower(),
        "gas": "co2",
    }
    if year:
        params["since"] = year
        params["to"] = year

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        return resp.json()


# ─── Open-Meteo Climate API ──────────────────────────────────────────

async def get_climate_projection(
    lat: float,
    lon: float,
    scenario: str = "rcp45",
    start_year: int = 2025,
    end_year: int = 2050,
) -> dict:
    """
    Klimaprojektionen für einen Standort via Open-Meteo Climate API.
    Szenarien: rcp26, rcp45, rcp85 (CMIP5) oder ssp126, ssp245, ssp370, ssp585 (CMIP6)
    """
    # Mapping: Kurzform auf Open-Meteo Modellgruppen
    model_mapping = {
        "rcp26": ("CMIP5", ["MRI_CGCM3"]),
        "rcp45": ("CMIP5", ["MRI_CGCM3"]),
        "rcp85": ("CMIP5", ["MRI_CGCM3"]),
        "ssp126": ("CMIP6", ["MRI_AGCM3_2_S"]),
        "ssp245": ("CMIP6", ["MRI_AGCM3_2_S"]),
        "ssp370": ("CMIP6", ["MRI_AGCM3_2_S"]),
        "ssp585": ("CMIP6", ["MRI_AGCM3_2_S"]),
    }

    scenario_lower = scenario.lower()
    if scenario_lower not in model_mapping:
        raise ValueError(
            f"Unbekanntes Szenario: {scenario}. "
            f"Erlaubt: {', '.join(model_mapping.keys())}"
        )

    params = {
        "latitude": lat,
        "longitude": lon,
        "start_date": f"{start_year}-01-01",
        "end_date": f"{end_year}-12-31",
        "models": ",".join(model_mapping[scenario_lower][1]),
        "daily": "temperature_2m_max,temperature_2m_min,precipitation_sum",
    }

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(OPEN_METEO_CLIMATE_URL, params=params)
        resp.raise_for_status()
        return resp.json()


# ─── NOAA CDO API ────────────────────────────────────────────────────

async def get_noaa_climate_data(
    dataset_id: str = "GHCND",
    location_id: str = "FIPS:GM",
    start_date: str = "2020-01-01",
    end_date: str = "2020-12-31",
    data_types: str = "TAVG,PRCP",
    limit: int = 100,
) -> dict:
    """
    NOAA Climate Data Online abrufen.
    Braucht NOAA_TOKEN in der Umgebung.
    """
    if not NOAA_TOKEN:
        return {
            "error": "NOAA_TOKEN nicht gesetzt. "
            "Registrierung: https://www.ncdc.noaa.gov/cdo-web/token"
        }

    url = f"{NOAA_BASE_URL}/data"
    params = {
        "datasetid": dataset_id,
        "locationid": location_id,
        "startdate": start_date,
        "enddate": end_date,
        "datatypeid": data_types,
        "limit": limit,
        "units": "metric",
    }
    headers = {"token": NOAA_TOKEN}

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(url, params=params, headers=headers)
        resp.raise_for_status()
        return resp.json()


# ─── Hilfsfunktionen ─────────────────────────────────────────────────

async def get_multiple_country_emissions(
    country_codes: list[str], year: int | None = None
) -> dict:
    """
    Emissionen mehrerer Länder parallel abrufen.
    """
    # Climate TRACE unterstützt kommaseparierte Länder
    codes = ",".join(c.upper() for c in country_codes)
    url = f"{CLIMATE_TRACE_BASE_URL}/country/emissions"
    params: dict = {
        "countries": codes,
        "gas": "co2",
    }
    if year:
        params["since"] = year
        params["to"] = year

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        return resp.json()


async def get_emission_history(
    country_code: str, start_year: int, end_year: int
) -> dict:
    """
    Historische Emissionsdaten eines Landes über einen Zeitraum.
    """
    url = f"{CLIMATE_TRACE_BASE_URL}/country/emissions"
    params = {
        "countries": country_code.upper(),
        "gas": "co2",
        "since": start_year,
        "to": end_year,
    }

    async with httpx.AsyncClient(timeout=HTTP_TIMEOUT) as client:
        resp = await client.get(url, params=params)
        resp.raise_for_status()
        return resp.json()
