from __future__ import annotations
import urllib.request
import json
from datetime import datetime, timedelta
from fastapi import APIRouter, Query
from typing import Optional

router = APIRouter(tags=["weather"])

WMO_CODES = {
    0: {"desc": "Clear Sky", "icon": "☀️", "bg": "from-amber-400 to-orange-500"},
    1: {"desc": "Mainly Clear", "icon": "🌤️", "bg": "from-amber-400 to-yellow-400"},
    2: {"desc": "Partly Cloudy", "icon": "⛅", "bg": "from-blue-400 to-gray-400"},
    3: {"desc": "Overcast", "icon": "☁️", "bg": "from-gray-400 to-gray-500"},
    45: {"desc": "Fog", "icon": "🌫️", "bg": "from-gray-400 to-gray-500"},
    48: {"desc": "Rime Fog", "icon": "🌫️", "bg": "from-gray-400 to-gray-500"},
    51: {"desc": "Light Drizzle", "icon": "🌦️", "bg": "from-blue-300 to-gray-400"},
    53: {"desc": "Moderate Drizzle", "icon": "🌦️", "bg": "from-blue-400 to-gray-400"},
    55: {"desc": "Dense Drizzle", "icon": "🌧️", "bg": "from-blue-500 to-gray-500"},
    61: {"desc": "Slight Rain", "icon": "🌧️", "bg": "from-blue-400 to-gray-500"},
    63: {"desc": "Moderate Rain", "icon": "🌧️", "bg": "from-blue-500 to-gray-500"},
    65: {"desc": "Heavy Rain", "icon": "🌧️", "bg": "from-blue-600 to-gray-600"},
    71: {"desc": "Slight Snow", "icon": "❄️", "bg": "from-blue-200 to-white"},
    73: {"desc": "Moderate Snow", "icon": "❄️", "bg": "from-blue-300 to-white"},
    75: {"desc": "Heavy Snow", "icon": "❄️", "bg": "from-blue-400 to-white"},
    80: {"desc": "Slight Showers", "icon": "🌦️", "bg": "from-blue-400 to-gray-400"},
    81: {"desc": "Moderate Showers", "icon": "🌧️", "bg": "from-blue-500 to-gray-500"},
    82: {"desc": "Violent Showers", "icon": "⛈️", "bg": "from-blue-700 to-gray-600"},
    95: {"desc": "Thunderstorm", "icon": "⛈️", "bg": "from-purple-600 to-gray-700"},
    96: {"desc": "Thunderstorm + Hail", "icon": "⛈️", "bg": "from-purple-700 to-gray-700"},
    99: {"desc": "Thunderstorm + Heavy Hail", "icon": "⛈️", "bg": "from-purple-800 to-gray-800"},
}

BD_CITIES = {
    "dhaka": {"lat": 23.8103, "lon": 90.4125},
    "chittagong": {"lat": 22.3569, "lon": 91.7832},
    "sylhet": {"lat": 24.8949, "lon": 91.8687},
    "rajshahi": {"lat": 24.3636, "lon": 88.6241},
    "khulna": {"lat": 22.8456, "lon": 89.5403},
    "barishal": {"lat": 22.7010, "lon": 90.3535},
    "rangpur": {"lat": 25.7439, "lon": 89.2752},
    "mymensingh": {"lat": 24.7471, "lon": 90.4203},
    "coxsbazar": {"lat": 21.4272, "lon": 92.0058},
    "comilla": {"lat": 23.4611, "lon": 91.1721},
}


def _fetch_weather(city: str = "dhaka") -> dict:
    coords = BD_CITIES.get(city.lower(), BD_CITIES["dhaka"])
    url = (
        f"https://api.open-meteo.com/v1/forecast?"
        f"latitude={coords['lat']}&longitude={coords['lon']}"
        f"&current=temperature_2m,relative_humidity_2m,apparent_temperature,"
        f"precipitation,weather_code,wind_speed_10m,wind_direction_10m"
        f"&daily=weather_code,temperature_2m_max,temperature_2m_min,"
        f"precipitation_sum,precipitation_probability_max,"
        f"wind_speed_10m_max,uv_index_max"
        f"&timezone=Asia/Dhaka&forecast_days=7"
    )
    req = urllib.request.Request(url, headers={"User-Agent": "NurseryOps/1.0"})
    with urllib.request.urlopen(req, timeout=10) as resp:
        return json.loads(resp.read().decode())


def _format_forecast(raw: dict) -> dict:
    current = raw.get("current", {})
    daily = raw.get("daily", {})
    code = current.get("weather_code", 0)
    wmo = WMO_CODES.get(code, WMO_CODES[0])

    today = []
    daily_dates = daily.get("time", [])
    for i in range(min(7, len(daily_dates))):
        d_code = daily["weather_code"][i] if i < len(daily["weather_code"]) else 0
        d_wmo = WMO_CODES.get(d_code, WMO_CODES[0])
        today.append({
            "date": daily_dates[i],
            "day": datetime.strptime(daily_dates[i], "%Y-%m-%d").strftime("%a"),
            "weather_code": d_code,
            "description": d_wmo["desc"],
            "icon": d_wmo["icon"],
            "max": daily["temperature_2m_max"][i] if i < len(daily["temperature_2m_max"]) else None,
            "min": daily["temperature_2m_min"][i] if i < len(daily["temperature_2m_min"]) else None,
            "precipitation": daily["precipitation_sum"][i] if i < len(daily["precipitation_sum"]) else 0,
            "precip_probability": daily["precipitation_probability_max"][i] if i < len(daily.get("precipitation_probability_max", [])) else None,
            "wind_max": daily["wind_speed_10m_max"][i] if i < len(daily.get("wind_speed_10m_max", [])) else None,
            "uv_index": daily["uv_index_max"][i] if i < len(daily.get("uv_index_max", [])) else None,
        })

    return {
        "current": {
            "temperature": current.get("temperature_2m"),
            "feels_like": current.get("apparent_temperature"),
            "humidity": current.get("relative_humidity_2m"),
            "precipitation": current.get("precipitation"),
            "wind_speed": current.get("wind_speed_10m"),
            "wind_direction": current.get("wind_direction_10m"),
            "weather_code": code,
            "description": wmo["desc"],
            "icon": wmo["icon"],
            "bg": wmo["bg"],
        },
        "forecast": today,
    }


@router.get("/weather")
def get_weather(city: str = Query("dhaka", description="Bangladesh city name")):
    try:
        raw = _fetch_weather(city)
        data = _format_forecast(raw)
        data["city"] = city.title()
        data["fetched_at"] = datetime.now().isoformat()
        return data
    except Exception as e:
        return {
            "error": str(e),
            "city": city.title(),
            "current": {
                "temperature": None,
                "description": "Unavailable",
                "icon": "❓",
                "bg": "from-gray-400 to-gray-500",
                "humidity": None,
                "wind_speed": None,
            },
            "forecast": [],
        }
