"""Weather via Open-Meteo API — free, no API key required."""

import httpx

GEOCODE_URL = "https://geocoding-api.open-meteo.com/v1/search"
WEATHER_URL = "https://api.open-meteo.com/v1/forecast"

# WMO weather interpretation codes → human-readable conditions
WMO_CODES = {
    0: "Clear sky", 1: "Mainly clear", 2: "Partly cloudy", 3: "Overcast",
    45: "Foggy", 48: "Depositing rime fog",
    51: "Light drizzle", 53: "Moderate drizzle", 55: "Dense drizzle",
    61: "Slight rain", 63: "Moderate rain", 65: "Heavy rain",
    71: "Slight snow", 73: "Moderate snow", 75: "Heavy snow",
    77: "Snow grains", 80: "Slight rain showers", 81: "Moderate rain showers",
    82: "Violent rain showers", 85: "Slight snow showers", 86: "Heavy snow showers",
    95: "Thunderstorm", 96: "Thunderstorm with slight hail",
    99: "Thunderstorm with heavy hail",
}


async def _geocode(client: httpx.AsyncClient, location: str) -> tuple[float, float, str]:
    """Resolve city name to coordinates. Returns (lat, lon, display_name)."""
    # Check if already coordinates
    if "," in location:
        parts = location.split(",", 1)
        try:
            lat, lon = float(parts[0].strip()), float(parts[1].strip())
            return lat, lon, f"{lat}, {lon}"
        except ValueError:
            pass

    resp = await client.get(GEOCODE_URL, params={"name": location, "count": 1, "language": "en"})
    resp.raise_for_status()
    data = resp.json()

    results = data.get("results")
    if not results:
        raise ValueError(f"Location not found: '{location}'. Try a different city name or use coordinates (lat,lon).")

    r = results[0]
    name_parts = [r.get("name", "")]
    if r.get("admin1"):
        name_parts.append(r["admin1"])
    if r.get("country"):
        name_parts.append(r["country"])
    display = ", ".join(name_parts)

    return r["latitude"], r["longitude"], display


async def handler(params: dict) -> dict:
    """Get current weather and optional forecast for a location."""
    location = params["location"]
    forecast_days = min(max(int(params.get("forecast_days") or 0), 0), 7)

    async with httpx.AsyncClient(timeout=15) as client:
        lat, lon, display_name = await _geocode(client, location)

        weather_params = {
            "latitude": lat,
            "longitude": lon,
            "current": "temperature_2m,relative_humidity_2m,weather_code,wind_speed_10m,apparent_temperature",
            "timezone": "auto",
        }
        if forecast_days > 0:
            weather_params["daily"] = "weather_code,temperature_2m_max,temperature_2m_min,precipitation_sum"
            weather_params["forecast_days"] = forecast_days

        resp = await client.get(WEATHER_URL, params=weather_params)
        resp.raise_for_status()
        data = resp.json()

    # Parse current conditions
    current = data.get("current", {})
    code = current.get("weather_code", 0)
    result = {
        "location": display_name,
        "current": {
            "temperature_c": current.get("temperature_2m"),
            "feels_like_c": current.get("apparent_temperature"),
            "humidity_pct": current.get("relative_humidity_2m"),
            "wind_speed_kmh": current.get("wind_speed_10m"),
            "condition": WMO_CODES.get(code, f"Unknown ({code})"),
        },
    }

    # Parse daily forecast if requested
    if forecast_days > 0:
        daily = data.get("daily", {})
        dates = daily.get("time", [])
        forecast = []
        codes = daily.get("weather_code") or []
        highs = daily.get("temperature_2m_max") or []
        lows = daily.get("temperature_2m_min") or []
        precip = daily.get("precipitation_sum") or []
        for i, date in enumerate(dates):
            day_code = codes[i] if i < len(codes) else 0
            forecast.append({
                "date": date,
                "high_c": highs[i] if i < len(highs) else None,
                "low_c": lows[i] if i < len(lows) else None,
                "precipitation_mm": precip[i] if i < len(precip) else None,
                "condition": WMO_CODES.get(day_code, f"Unknown ({day_code})"),
            })
        result["forecast"] = forecast

    return result
