# weather.py
#
# author: deng
# date: 20251127

from typing import Optional

import requests


class WeatherFetcher:
    """Fetch weather data for hiking locations."""

    def __init__(self, api_url: str = 'https://api.open-meteo.com/v1/forecast', request_timeout: int = 8, forecast_days: int = 7) -> None:
        """Initialize weather fetcher."""
        self.api_url = api_url
        self.request_timeout = request_timeout
        self.forecast_days = max(forecast_days, 1)

    def convert_wind_degrees_to_flow_direction(self, degrees: Optional[float]) -> str:
        """Convert wind direction from degrees to flow direction emoji.

        Args:
            degrees: Wind direction in degrees (0-360)

        Returns:
            str: Flow direction as emoji arrow (pointing where wind is blowing to)
        """
        if degrees is None:
            return 'N/A'
        directions = ['⬇️', '↙️', '⬅️', '↖️', '⬆️', '↗️', '➡️', '↘️']
        index = round(degrees / 45) % 8
        return directions[index]

    def get_wind_speed_indicator(self, wind_speed: Optional[float]) -> str:
        """Get wind speed level indicator based on speed.

        Args:
            wind_speed: Wind speed in km/h

        Returns:
            str: Emoji indicator (🟢/🟡/🟠/🔴)
        """
        if wind_speed is None:
            return ''

        if wind_speed < 20:
            return '🟢'  # Safe
        elif wind_speed < 40:
            return '🟡'  # Caution
        elif wind_speed < 60:
            return '🟠'  # Alert
        else:
            return '🔴'  # Dangerous

    def get_uv_index_indicator(self, uv_index: Optional[float]) -> str:
        """Get UV index level indicator based on index.

        Args:
            uv_index: UV index

        Returns:
            str: Emoji indicator (🟢/🟡/🟠/🔴/🟣)
        """
        if uv_index is None:
            return ''

        if uv_index <= 2:
            return '🟢'  # Safe
        elif uv_index <= 5:
            return '🟡'  # Caution
        elif uv_index <= 7:
            return '🟠'  # Alert
        elif uv_index <= 10:
            return '🔴'  # Dangerous
        else:
            return '🟣'  # Extreme

    def get_weather(self, latitude: float, longitude: float) -> Optional[dict]:
        """Fetch weather data for given coordinates.

        Args:
            latitude: Latitude of the location
            longitude: Longitude of the location

        Returns:
            dict: Weather data with temperature, humidity, precipitation, etc.
                  Returns None if request fails.
        """
        try:
            params = {
                'latitude': latitude,
                'longitude': longitude,
                'current': ('relative_humidity_2m,apparent_temperature,precipitation_probability,precipitation,wind_speed_10m,wind_direction_10m',),
                'daily': (
                    'temperature_2m_max,temperature_2m_min,apparent_temperature_max,apparent_temperature_min,'
                    'relative_humidity_2m_mean,precipitation_sum,precipitation_probability_max,sunrise,sunset,'
                    'wind_speed_10m_max,wind_direction_10m_dominant,uv_index_max'
                ),
                'timezone': 'auto',
                'forecast_days': self.forecast_days,
            }

            response = requests.get(self.api_url, params=params, timeout=self.request_timeout)
            response.raise_for_status()

            data = response.json()

            # Parse weather data
            current = data.get('current', {})
            daily = data.get('daily', {})

            weather_info = {
                'current_humidity': current.get('relative_humidity_2m'),
                'current_apparent_temperature': current.get('apparent_temperature'),
                'current_precipitation_probability': current.get('precipitation_probability'),
                'current_precipitation': current.get('precipitation'),
                'current_wind_speed': current.get('wind_speed_10m'),
                'current_wind_direction': current.get('wind_direction_10m'),
                'daily_temp_max': daily.get('temperature_2m_max', []),
                'daily_temp_min': daily.get('temperature_2m_min', []),
                'daily_apparent_temp_max': daily.get('apparent_temperature_max', []),
                'daily_apparent_temp_min': daily.get('apparent_temperature_min', []),
                'daily_mean_relative_humidity': daily.get('relative_humidity_2m_mean', []),
                'daily_precipitation_sum': daily.get('precipitation_sum', []),
                'daily_precipitation_prob': daily.get('precipitation_probability_max', []),
                'daily_wind_speed_max': daily.get('wind_speed_10m_max', []),
                'daily_wind_direction_dominant': daily.get('wind_direction_10m_dominant', []),
                'daily_sunrise': daily.get('sunrise', []),
                'daily_sunset': daily.get('sunset', []),
                'daily_uv_index_max': daily.get('uv_index_max', []),
                'daily_time': daily.get('time', []),
            }

            return weather_info

        except requests.exceptions.RequestException as e:
            print(f'天氣資料獲取失敗: {str(e)}')
            return None
        except Exception as e:
            print(f'天氣資料處理失敗: {str(e)}')
            return None
