# services/external/app/schemas/weather.py
"""Weather data schemas"""

from pydantic import BaseModel, Field, field_validator
from datetime import datetime
from typing import Optional, List
from uuid import UUID

class WeatherDataBase(BaseModel):
    """Base weather data schema"""
    location_id: str = Field(..., max_length=100, description="Weather monitoring location ID")
    date: datetime = Field(..., description="Date and time of weather measurement")
    temperature: Optional[float] = Field(None, ge=-50, le=60, description="Temperature in Celsius")
    precipitation: Optional[float] = Field(None, ge=0, description="Precipitation in mm")
    humidity: Optional[float] = Field(None, ge=0, le=100, description="Humidity percentage")
    wind_speed: Optional[float] = Field(None, ge=0, le=200, description="Wind speed in km/h")
    pressure: Optional[float] = Field(None, ge=800, le=1200, description="Atmospheric pressure in hPa")
    description: Optional[str] = Field(None, max_length=200, description="Weather description")
    source: str = Field("aemet", max_length=50, description="Data source")
    raw_data: Optional[str] = Field(None, description="Raw data from source")

class WeatherDataCreate(WeatherDataBase):
    """Schema for creating weather data"""
    pass

class WeatherDataUpdate(BaseModel):
    """Schema for updating weather data"""
    temperature: Optional[float] = Field(None, ge=-50, le=60)
    precipitation: Optional[float] = Field(None, ge=0)
    humidity: Optional[float] = Field(None, ge=0, le=100)
    wind_speed: Optional[float] = Field(None, ge=0, le=200)
    pressure: Optional[float] = Field(None, ge=800, le=1200)
    description: Optional[str] = Field(None, max_length=200)
    raw_data: Optional[str] = None

class WeatherDataResponse(WeatherDataBase):
    """Schema for weather data responses"""
    id: str = Field(..., description="Unique identifier")
    created_at: datetime = Field(..., description="Creation timestamp")
    updated_at: datetime = Field(..., description="Last update timestamp")

    @field_validator('id', mode='before')
    @classmethod
    def convert_uuid_to_string(cls, v):
        if isinstance(v, UUID):
            return str(v)
        return v

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

class WeatherForecastBase(BaseModel):
    """Base weather forecast schema"""
    location_id: str = Field(..., max_length=100, description="Location ID")
    forecast_date: datetime = Field(..., description="Date for forecast")
    temperature: Optional[float] = Field(None, ge=-50, le=60, description="Forecasted temperature")
    precipitation: Optional[float] = Field(None, ge=0, description="Forecasted precipitation")
    humidity: Optional[float] = Field(None, ge=0, le=100, description="Forecasted humidity")
    wind_speed: Optional[float] = Field(None, ge=0, le=200, description="Forecasted wind speed")
    description: Optional[str] = Field(None, max_length=200, description="Forecast description")
    source: str = Field("aemet", max_length=50, description="Data source")
    raw_data: Optional[str] = Field(None, description="Raw forecast data")

class WeatherForecastCreate(WeatherForecastBase):
    """Schema for creating weather forecasts"""
    pass

class WeatherForecastResponse(WeatherForecastBase):
    """Schema for weather forecast responses"""
    id: str = Field(..., description="Unique identifier")
    generated_at: datetime = Field(..., description="When forecast was generated")
    created_at: datetime = Field(..., description="Creation timestamp")
    updated_at: datetime = Field(..., description="Last update timestamp")

    @field_validator('id', mode='before')
    @classmethod
    def convert_uuid_to_string(cls, v):
        if isinstance(v, UUID):
            return str(v)
        return v

    class Config:
        from_attributes = True
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }

class WeatherDataList(BaseModel):
    """Schema for paginated weather data responses"""
    data: List[WeatherDataResponse]
    total: int = Field(..., description="Total number of records")
    page: int = Field(..., description="Current page number")
    per_page: int = Field(..., description="Records per page")
    has_next: bool = Field(..., description="Whether there are more pages")
    has_prev: bool = Field(..., description="Whether there are previous pages")

class WeatherForecastList(BaseModel):
    """Schema for paginated weather forecast responses"""
    forecasts: List[WeatherForecastResponse]
    total: int = Field(..., description="Total number of forecasts")
    page: int = Field(..., description="Current page number")
    per_page: int = Field(..., description="Forecasts per page")

class WeatherAnalytics(BaseModel):
    """Schema for weather analytics"""
    location_id: str
    period_start: datetime
    period_end: datetime
    avg_temperature: Optional[float] = None
    min_temperature: Optional[float] = None
    max_temperature: Optional[float] = None
    total_precipitation: Optional[float] = None
    avg_humidity: Optional[float] = None
    avg_wind_speed: Optional[float] = None
    avg_pressure: Optional[float] = None
    weather_conditions: dict = Field(default_factory=dict)
    rainy_days: int = 0
    sunny_days: int = 0

class LocationRequest(BaseModel):
    latitude: float
    longitude: float
    address: Optional[str] = None

class DateRangeRequest(BaseModel):
    start_date: datetime
    end_date: datetime
    
class HistoricalWeatherRequest(BaseModel):
    latitude: float
    longitude: float
    start_date: datetime
    end_date: datetime
    
class WeatherForecastRequest(BaseModel):
    latitude: float
    longitude: float
    days: int

class HourlyForecastRequest(BaseModel):
    latitude: float
    longitude: float
    hours: int = Field(default=48, ge=1, le=48, description="Number of hours to forecast (1-48)")

class HourlyForecastResponse(BaseModel):
    forecast_datetime: datetime
    generated_at: datetime
    temperature: Optional[float]
    precipitation: Optional[float]
    humidity: Optional[float]
    wind_speed: Optional[float]
    description: Optional[str]
    source: str
    hour: int

class WeatherForecastAPIResponse(BaseModel):
    """Simplified schema for API weather forecast responses (without database fields)"""
    forecast_date: datetime = Field(..., description="Date for forecast")
    generated_at: datetime = Field(..., description="When forecast was generated")
    temperature: Optional[float] = Field(None, ge=-50, le=60, description="Forecasted temperature")
    precipitation: Optional[float] = Field(None, ge=0, description="Forecasted precipitation")
    humidity: Optional[float] = Field(None, ge=0, le=100, description="Forecasted humidity")
    wind_speed: Optional[float] = Field(None, ge=0, le=200, description="Forecasted wind speed")
    description: Optional[str] = Field(None, max_length=200, description="Forecast description")
    source: str = Field("aemet", max_length=50, description="Data source")

    class Config:
        json_encoders = {
            datetime: lambda v: v.isoformat()
        }