"""Weather source storage using SQLite."""

import uuid
from datetime import datetime, timezone
from typing import List, Optional

from wled_controller.storage.base_sqlite_store import BaseSqliteStore
from wled_controller.storage.database import Database
from wled_controller.storage.weather_source import WeatherSource
from wled_controller.utils import get_logger

logger = get_logger(__name__)


class WeatherSourceStore(BaseSqliteStore[WeatherSource]):
    """Persistent storage for weather sources."""

    _table_name = "weather_sources"
    _entity_name = "Weather source"

    def __init__(self, db: Database):
        super().__init__(db, WeatherSource.from_dict)

    # Backward-compatible aliases
    get_all_sources = BaseSqliteStore.get_all
    get_source = BaseSqliteStore.get
    delete_source = BaseSqliteStore.delete

    def create_source(
        self,
        name: str,
        provider: str = "open_meteo",
        provider_config: Optional[dict] = None,
        latitude: float = 50.0,
        longitude: float = 0.0,
        update_interval: int = 600,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> WeatherSource:
        from wled_controller.core.weather.weather_provider import PROVIDER_REGISTRY

        if provider not in PROVIDER_REGISTRY:
            raise ValueError(f"Unknown weather provider: {provider}")
        if not (60 <= update_interval <= 3600):
            raise ValueError("update_interval must be between 60 and 3600 seconds")
        if not (-90.0 <= latitude <= 90.0):
            raise ValueError("latitude must be between -90 and 90")
        if not (-180.0 <= longitude <= 180.0):
            raise ValueError("longitude must be between -180 and 180")

        self._check_name_unique(name)

        sid = f"ws_{uuid.uuid4().hex[:8]}"
        now = datetime.now(timezone.utc)

        source = WeatherSource(
            id=sid,
            name=name,
            created_at=now,
            updated_at=now,
            provider=provider,
            provider_config=provider_config or {},
            latitude=latitude,
            longitude=longitude,
            update_interval=update_interval,
            description=description,
            tags=tags or [],
        )

        self._items[sid] = source
        self._save_item(sid, source)
        logger.info(f"Created weather source: {name} ({sid})")
        return source

    def update_source(
        self,
        source_id: str,
        name: Optional[str] = None,
        provider: Optional[str] = None,
        provider_config: Optional[dict] = None,
        latitude: Optional[float] = None,
        longitude: Optional[float] = None,
        update_interval: Optional[int] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> WeatherSource:
        existing = self.get(source_id)

        if name is not None and name != existing.name:
            self._check_name_unique(name)

        if provider is not None:
            from wled_controller.core.weather.weather_provider import PROVIDER_REGISTRY
            if provider not in PROVIDER_REGISTRY:
                raise ValueError(f"Unknown weather provider: {provider}")

        if update_interval is not None and not (60 <= update_interval <= 3600):
            raise ValueError("update_interval must be between 60 and 3600 seconds")
        if latitude is not None and not (-90.0 <= latitude <= 90.0):
            raise ValueError("latitude must be between -90 and 90")
        if longitude is not None and not (-180.0 <= longitude <= 180.0):
            raise ValueError("longitude must be between -180 and 180")

        updated = WeatherSource(
            id=existing.id,
            name=name if name is not None else existing.name,
            created_at=existing.created_at,
            updated_at=datetime.now(timezone.utc),
            provider=provider if provider is not None else existing.provider,
            provider_config=provider_config if provider_config is not None else existing.provider_config,
            latitude=latitude if latitude is not None else existing.latitude,
            longitude=longitude if longitude is not None else existing.longitude,
            update_interval=update_interval if update_interval is not None else existing.update_interval,
            description=description if description is not None else existing.description,
            tags=tags if tags is not None else existing.tags,
        )

        self._items[source_id] = updated
        self._save_item(source_id, updated)
        logger.info(f"Updated weather source: {updated.name} ({source_id})")
        return updated
