"""Output target 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.output_target import OutputTarget
from wled_controller.storage.wled_output_target import WledOutputTarget
from wled_controller.storage.key_colors_output_target import (
    KeyColorsSettings,
    KeyColorsOutputTarget,
)
from wled_controller.storage.ha_light_output_target import (
    HALightMapping,
    HALightOutputTarget,
)
from wled_controller.utils import get_logger

logger = get_logger(__name__)

DEFAULT_STATE_CHECK_INTERVAL = 30  # seconds


class OutputTargetStore(BaseSqliteStore[OutputTarget]):
    """Persistent storage for output targets."""

    _table_name = "output_targets"
    _entity_name = "Output target"

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

    # Backward-compatible aliases
    get_all_targets = BaseSqliteStore.get_all
    get_target = BaseSqliteStore.get
    delete_target = BaseSqliteStore.delete

    def create_target(
        self,
        name: str,
        target_type: str,
        device_id: str = "",
        color_strip_source_id: str = "",
        brightness_value_source_id: str = "",
        fps: int = 30,
        keepalive_interval: float = 1.0,
        state_check_interval: int = DEFAULT_STATE_CHECK_INTERVAL,
        min_brightness_threshold: int = 0,
        adaptive_fps: bool = False,
        protocol: str = "ddp",
        key_colors_settings: Optional[KeyColorsSettings] = None,
        description: Optional[str] = None,
        picture_source_id: str = "",
        tags: Optional[List[str]] = None,
        ha_source_id: str = "",
        ha_light_mappings: Optional[List[HALightMapping]] = None,
        update_rate: float = 2.0,
        transition: float = 0.5,
        color_tolerance: int = 5,
    ) -> OutputTarget:
        """Create a new output target.

        Raises:
            ValueError: If validation fails
        """
        if target_type not in ("led", "key_colors", "ha_light"):
            raise ValueError(f"Invalid target type: {target_type}")

        # Check for duplicate name
        for target in self._items.values():
            if target.name == name:
                raise ValueError(f"Output target with name '{name}' already exists")

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

        if target_type == "led":
            target: OutputTarget = WledOutputTarget(
                id=target_id,
                name=name,
                target_type="led",
                device_id=device_id,
                color_strip_source_id=color_strip_source_id,
                brightness_value_source_id=brightness_value_source_id,
                fps=fps,
                keepalive_interval=keepalive_interval,
                state_check_interval=state_check_interval,
                min_brightness_threshold=min_brightness_threshold,
                adaptive_fps=adaptive_fps,
                protocol=protocol,
                description=description,
                created_at=now,
                updated_at=now,
            )
        elif target_type == "key_colors":
            target = KeyColorsOutputTarget(
                id=target_id,
                name=name,
                target_type="key_colors",
                picture_source_id=picture_source_id,
                settings=key_colors_settings or KeyColorsSettings(),
                description=description,
                created_at=now,
                updated_at=now,
            )
        elif target_type == "ha_light":
            target = HALightOutputTarget(
                id=target_id,
                name=name,
                target_type="ha_light",
                ha_source_id=ha_source_id,
                color_strip_source_id=color_strip_source_id,
                light_mappings=ha_light_mappings or [],
                update_rate=update_rate,
                transition=transition,
                min_brightness_threshold=min_brightness_threshold,
                color_tolerance=color_tolerance,
                description=description,
                created_at=now,
                updated_at=now,
            )
        else:
            raise ValueError(f"Unknown target type: {target_type}")

        target.tags = tags or []
        self._items[target_id] = target
        self._save_item(target_id, target)

        logger.info(f"Created output target: {name} ({target_id}, type={target_type})")
        return target

    def update_target(
        self,
        target_id: str,
        name: Optional[str] = None,
        device_id: Optional[str] = None,
        color_strip_source_id: Optional[str] = None,
        brightness_value_source_id: Optional[str] = None,
        fps: Optional[int] = None,
        keepalive_interval: Optional[float] = None,
        state_check_interval: Optional[int] = None,
        min_brightness_threshold: Optional[int] = None,
        adaptive_fps: Optional[bool] = None,
        protocol: Optional[str] = None,
        key_colors_settings: Optional[KeyColorsSettings] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> OutputTarget:
        """Update an output target.

        Raises:
            ValueError: If target not found or validation fails
        """
        if target_id not in self._items:
            raise ValueError(f"Output target not found: {target_id}")

        target = self._items[target_id]

        if name is not None:
            # Check for duplicate name (exclude self)
            for other in self._items.values():
                if other.id != target_id and other.name == name:
                    raise ValueError(f"Output target with name '{name}' already exists")

        target.update_fields(
            name=name,
            device_id=device_id,
            color_strip_source_id=color_strip_source_id,
            brightness_value_source_id=brightness_value_source_id,
            fps=fps,
            keepalive_interval=keepalive_interval,
            state_check_interval=state_check_interval,
            min_brightness_threshold=min_brightness_threshold,
            adaptive_fps=adaptive_fps,
            protocol=protocol,
            key_colors_settings=key_colors_settings,
            description=description,
            tags=tags,
        )

        target.updated_at = datetime.now(timezone.utc)
        self._save_item(target_id, target)

        logger.info(f"Updated output target: {target_id}")
        return target

    def get_targets_for_device(self, device_id: str) -> List[OutputTarget]:
        """Get all targets that reference a specific device."""
        return [
            t
            for t in self._items.values()
            if isinstance(t, WledOutputTarget) and t.device_id == device_id
        ]

    def get_targets_referencing_source(self, source_id: str) -> List[str]:
        """Return names of KC targets that reference a picture source."""
        return [
            target.name
            for target in self._items.values()
            if isinstance(target, KeyColorsOutputTarget) and target.picture_source_id == source_id
        ]

    def get_targets_referencing_css(self, css_id: str) -> List[str]:
        """Return names of targets that reference a color strip source."""
        result = []
        for target in self._items.values():
            if isinstance(target, WledOutputTarget) and target.color_strip_source_id == css_id:
                result.append(target.name)
            elif isinstance(target, HALightOutputTarget) and target.color_strip_source_id == css_id:
                result.append(target.name)
        return result

    def count(self) -> int:
        """Get number of targets."""
        return len(self._items)
