from __future__ import annotations

import asyncio
import logging
from typing import Any

from app.cache import cache_get, cache_set
from app.config import CACHE_TTL_DASHBOARD, CACHE_TTL_OBSERVATIONS, CACHE_TTL_WARNINGS
from app.services.dwd_radar import fetch_radar_index
from app.services.warnings import fetch_warnings_for_location
from app.services.weather import get_forecast, get_observations

logger = logging.getLogger(__name__)


async def get_radar_summary() -> dict[str, Any]:
    redis_key = "radar:summary"
    cached = await cache_get(redis_key)
    if cached:
        return {**cached, "cached": True}

    index = await fetch_radar_index(limit=12)
    payload = {
        "source": index["source"],
        "product": index["product"],
        "count": index["count"],
        "cached": False,
    }
    await cache_set(redis_key, payload, 120)
    return payload


async def build_dashboard(lat: float, lon: float, local_only: bool = True) -> dict[str, Any]:
    redis_key = f"dashboard:{round(lat, 4)}:{round(lon, 4)}:{int(local_only)}"
    cached = await cache_get(redis_key)
    if cached:
        return {**cached, "bundle_cached": True}

    results = await asyncio.gather(
        get_forecast(lat, lon),
        get_observations(lat, lon),
        fetch_warnings_for_location(lat, lon, local_only=local_only),
        get_radar_summary(),
        return_exceptions=True,
    )

    payload: dict[str, Any] = {
        "lat": lat,
        "lon": lon,
        "bundle_cached": False,
        "errors": {},
    }

    names = ("forecast", "observations", "warnings", "radar")
    for name, result in zip(names, results):
        if isinstance(result, Exception):
            logger.warning("dashboard %s failed: %s", name, result)
            payload["errors"][name] = str(result)
            payload[name] = None
        else:
            payload[name] = result

    ttl = min(CACHE_TTL_DASHBOARD, CACHE_TTL_OBSERVATIONS, CACHE_TTL_WARNINGS)
    if not payload["errors"]:
        await cache_set(redis_key, payload, ttl)

    return payload
