from __future__ import annotations

import asyncio
import logging
from typing import Any

import httpx

from app.cache import cache_get, cache_set
from app.config import CACHE_TTL_GEOCODE, DWD_WMS_URL
from app.http_client import get_client

logger = logging.getLogger(__name__)

WFS_URL = f"{DWD_WMS_URL.rsplit('/wms', 1)[0]}/ows"
# Landkreise reicht fuer warnapp_landkreise/json/warnings.json
WFS_LAYERS = ("dwd:Warngebiete_Kreise",)


async def _wfs_intersects(layer: str, lat: float, lon: float) -> list[dict[str, Any]]:
    params = {
        "service": "WFS",
        "version": "2.0.0",
        "request": "GetFeature",
        "typeName": layer,
        "outputFormat": "application/json",
        "count": 5,
        "CQL_FILTER": f"INTERSECTS(SHAPE,POINT({lat} {lon}))",
    }
    client = get_client()
    response = await client.get(WFS_URL, params=params, timeout=8.0)
    response.raise_for_status()
    payload = response.json()
    results = []
    for feature in payload.get("features", []):
        props = feature.get("properties") or {}
        cell_id = props.get("WARNCELLID")
        if cell_id is None:
            continue
        results.append(
            {
                "warncell_id": str(cell_id),
                "name": props.get("NAME"),
                "short_name": props.get("KURZNAME"),
                "layer": layer.split(":")[-1],
                "state": props.get("BL"),
            }
        )
    return results


def _related_cell_ids(cell_id: str) -> set[str]:
    ids = {cell_id}
    if len(cell_id) >= 9:
        core = cell_id[1:]
        ids.add(f"1{core}")
        ids.add(f"9{core}")
        if cell_id.startswith("9"):
            ids.add(f"1{cell_id[1:]}")
        elif cell_id.startswith("1"):
            ids.add(f"9{cell_id[1:]}")
    return ids


async def resolve_warncells(lat: float, lon: float) -> dict[str, Any]:
    cache_key = f"warncell:{lat:.4f}:{lon:.4f}"
    cached = await cache_get(cache_key)
    if cached:
        return cached

    layer_results = await asyncio.gather(
        *[_wfs_intersects(layer, lat, lon) for layer in WFS_LAYERS],
        return_exceptions=True,
    )
    areas: list[dict[str, Any]] = []
    for layer, result in zip(WFS_LAYERS, layer_results):
        if isinstance(result, Exception):
            logger.warning("WFS warncell lookup failed for %s: %s", layer, result)
            continue
        areas.extend(result)

    cell_ids: set[str] = set()
    for area in areas:
        cell_ids.update(_related_cell_ids(area["warncell_id"]))

    payload = {
        "lat": lat,
        "lon": lon,
        "areas": areas,
        "cell_ids": sorted(cell_ids),
    }
    await cache_set(cache_key, payload, CACHE_TTL_GEOCODE)
    return payload
