"""Weather system with procedural transitions."""

from __future__ import annotations

import enum
import random
from dataclasses import dataclass


class WeatherCondition(enum.Enum):
    clear = "clear"
    cloudy = "cloudy"
    rain = "rain"
    storm = "storm"
    snow = "snow"
    fog = "fog"


@dataclass
class WeatherState:
    condition: WeatherCondition
    intensity: float  # 0.0 to 1.0


def get_weather_description(state: WeatherState) -> str:
    """Return atmospheric text for the current weather."""
    condition = state.condition
    intensity = state.intensity

    if condition == WeatherCondition.clear:
        return "the sky is clear"

    elif condition == WeatherCondition.cloudy:
        if intensity < 0.4:
            return "thin clouds drift overhead"
        elif intensity < 0.7:
            return "clouds fill the sky"
        else:
            return "heavy clouds loom darkly"

    elif condition == WeatherCondition.rain:
        if intensity < 0.3:
            return "a light drizzle falls"
        elif intensity < 0.6:
            return "rain patters steadily"
        else:
            return "rain hammers down relentlessly"

    elif condition == WeatherCondition.storm:
        if intensity < 0.5:
            return "thunder rumbles in the distance"
        else:
            return "lightning splits the sky as the storm rages"

    elif condition == WeatherCondition.snow:
        if intensity < 0.3:
            return "light snow drifts down"
        elif intensity < 0.6:
            return "snow falls steadily"
        else:
            return "heavy snow blankets everything"

    elif condition == WeatherCondition.fog:
        if intensity < 0.4:
            return "thin mist hangs in the air"
        elif intensity < 0.7:
            return "fog obscures the distance"
        else:
            return "thick fog shrouds everything"

    return ""


# Climate profiles: transition weights for each condition
# Format: {from_condition: {to_condition: weight, ...}, ...}
CLIMATE_PROFILES = {
    "temperate": {
        WeatherCondition.clear: {
            "clear": 50,
            "cloudy": 40,
            "fog": 10,
        },
        WeatherCondition.cloudy: {
            "clear": 30,
            "cloudy": 35,
            "rain": 20,
            "snow": 10,
            "fog": 5,
        },
        WeatherCondition.rain: {
            "cloudy": 35,
            "rain": 30,
            "storm": 15,
            "snow": 10,
            "fog": 10,
        },
        WeatherCondition.storm: {
            "rain": 60,
            "cloudy": 40,
        },
        WeatherCondition.snow: {
            "snow": 40,
            "cloudy": 35,
            "fog": 25,
        },
        WeatherCondition.fog: {
            "fog": 30,
            "cloudy": 40,
            "clear": 30,
        },
    },
    "arid": {
        WeatherCondition.clear: {
            "clear": 90,
            "cloudy": 10,
        },
        WeatherCondition.cloudy: {
            "clear": 70,
            "cloudy": 20,
            "rain": 5,
            "fog": 5,
        },
        WeatherCondition.rain: {
            "cloudy": 60,
            "rain": 20,
            "clear": 20,
        },
        WeatherCondition.storm: {
            "rain": 50,
            "cloudy": 50,
        },
        WeatherCondition.snow: {
            "cloudy": 100,
        },
        WeatherCondition.fog: {
            "clear": 60,
            "fog": 20,
            "cloudy": 20,
        },
    },
    "arctic": {
        WeatherCondition.clear: {
            "cloudy": 50,
            "fog": 30,
            "clear": 20,
        },
        WeatherCondition.cloudy: {
            "snow": 40,
            "cloudy": 35,
            "fog": 25,
        },
        WeatherCondition.rain: {
            "snow": 40,
            "cloudy": 40,
            "fog": 20,
        },
        WeatherCondition.storm: {
            "snow": 60,
            "cloudy": 40,
        },
        WeatherCondition.snow: {
            "snow": 50,
            "cloudy": 30,
            "fog": 20,
        },
        WeatherCondition.fog: {
            "fog": 40,
            "cloudy": 40,
            "snow": 20,
        },
    },
}


def advance_weather(
    current: WeatherState,
    season: str = "summer",
    rng: random.Random | None = None,
    climate: str = "temperate",
) -> WeatherState:
    """Advance weather by one step (one game hour)."""
    if rng is None:
        rng = random.Random()

    # Get climate profile
    profile = CLIMATE_PROFILES.get(climate, CLIMATE_PROFILES["temperate"])

    # Get transition weights for current condition
    transitions = profile.get(current.condition, {})

    # Filter out snow if not winter/autumn
    if season not in ("winter", "autumn"):
        transitions = {k: v for k, v in transitions.items() if k != "snow"}

    # If no valid transitions, stay in current condition
    if not transitions:
        return WeatherState(
            condition=current.condition, intensity=rng.uniform(0.0, 1.0)
        )

    # Weighted random choice
    conditions = list(transitions.keys())
    weights = list(transitions.values())

    # Convert string keys to WeatherCondition enums
    resolved_conditions = []
    for cond in conditions:
        if isinstance(cond, str):
            resolved_conditions.append(WeatherCondition[cond])
        else:
            resolved_conditions.append(cond)

    new_condition = rng.choices(resolved_conditions, weights=weights, k=1)[0]

    # Generate appropriate intensity for the new condition
    if new_condition == WeatherCondition.clear:
        new_intensity = 0.5  # Clear has no meaningful intensity variation
    elif new_condition == WeatherCondition.storm:
        new_intensity = rng.uniform(0.5, 1.0)  # Storms are always intense
    else:
        new_intensity = rng.uniform(0.0, 1.0)

    return WeatherState(condition=new_condition, intensity=new_intensity)


# Global weather state
_current_weather: WeatherState | None = None


def init_weather(
    condition: WeatherCondition = WeatherCondition.clear, intensity: float = 0.5
) -> None:
    """Initialize the global weather state.

    Args:
        condition: Initial weather condition
        intensity: Initial intensity (0.0 to 1.0)
    """
    global _current_weather
    _current_weather = WeatherState(condition=condition, intensity=intensity)


def get_current_weather() -> WeatherState:
    """Get the current global weather state.

    Returns:
        Current weather state (defaults to clear if not initialized)
    """
    if _current_weather is None:
        return WeatherState(condition=WeatherCondition.clear, intensity=0.5)
    return _current_weather


def tick_weather(season: str = "summer", climate: str = "temperate") -> None:
    """Advance weather by one step. Called once per game hour.

    Args:
        season: Current season
        climate: Climate profile to use
    """
    global _current_weather
    current = get_current_weather()
    _current_weather = advance_weather(current, season=season, climate=climate)


def get_weather_ambience(condition: WeatherCondition) -> list[str]:
    """Return ambient messages appropriate for the weather."""
    if condition == WeatherCondition.rain:
        return [
            "rain patters on the ground around you.",
            "water drips from above.",
            "you hear the steady rhythm of rainfall.",
        ]
    elif condition == WeatherCondition.storm:
        return [
            "thunder cracks overhead.",
            "lightning flashes in the distance.",
            "the wind howls fiercely.",
        ]
    elif condition == WeatherCondition.snow:
        return [
            "snowflakes drift silently down.",
            "the world is muffled under falling snow.",
        ]
    elif condition == WeatherCondition.fog:
        return [
            "mist swirls around your feet.",
            "shapes loom and fade in the fog.",
        ]
    else:
        # clear or cloudy: no extra ambience
        return []
