"""Audio template storage using SQLite."""

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

from wled_controller.core.audio.factory import AudioEngineRegistry
from wled_controller.storage.audio_template import AudioCaptureTemplate
from wled_controller.storage.base_sqlite_store import BaseSqliteStore
from wled_controller.storage.database import Database
from wled_controller.utils import get_logger

logger = get_logger(__name__)


class AudioTemplateStore(BaseSqliteStore[AudioCaptureTemplate]):
    """Storage for audio capture templates.

    All templates are persisted to the database.
    On startup, if no templates exist, one is auto-created using the
    highest-priority available engine.
    """

    _table_name = "audio_templates"
    _entity_name = "Audio capture template"

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

    # Backward-compatible aliases
    get_all_templates = BaseSqliteStore.get_all
    get_template = BaseSqliteStore.get

    def _ensure_initial_template(self) -> None:
        """Auto-create a template if none exist, using the best available engine."""
        if self._items:
            return

        best_engine = AudioEngineRegistry.get_best_available_engine()
        if not best_engine:
            logger.warning("No audio engines available, cannot create initial template")
            return

        engine_class = AudioEngineRegistry.get_engine(best_engine)
        default_config = engine_class.get_default_config()
        now = datetime.now(timezone.utc)
        template_id = f"atpl_{uuid.uuid4().hex[:8]}"

        template = AudioCaptureTemplate(
            id=template_id,
            name="Default Audio",
            engine_type=best_engine,
            engine_config=default_config,
            created_at=now,
            updated_at=now,
            description=f"Default audio template using {best_engine.upper()} engine",
        )

        self._items[template_id] = template
        self._save_item(template_id, template)
        logger.info(
            f"Auto-created initial audio template: {template.name} "
            f"({template_id}, engine={best_engine})"
        )

    def get_default_template_id(self) -> Optional[str]:
        """Return the ID of the first template, or None if none exist."""
        if self._items:
            return next(iter(self._items))
        return None

    def create_template(
        self,
        name: str,
        engine_type: str,
        engine_config: Dict[str, Any],
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> AudioCaptureTemplate:
        self._check_name_unique(name)

        template_id = f"atpl_{uuid.uuid4().hex[:8]}"
        now = datetime.now(timezone.utc)
        template = AudioCaptureTemplate(
            id=template_id,
            name=name,
            engine_type=engine_type,
            engine_config=engine_config,
            created_at=now,
            updated_at=now,
            description=description,
            tags=tags or [],
        )

        self._items[template_id] = template
        self._save_item(template_id, template)
        logger.info(f"Created audio template: {name} ({template_id})")
        return template

    def update_template(
        self,
        template_id: str,
        name: Optional[str] = None,
        engine_type: Optional[str] = None,
        engine_config: Optional[Dict[str, Any]] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> AudioCaptureTemplate:
        template = self.get(template_id)

        if name is not None:
            self._check_name_unique(name, exclude_id=template_id)
            template.name = name
        if engine_type is not None:
            template.engine_type = engine_type
        if engine_config is not None:
            template.engine_config = engine_config
        if description is not None:
            template.description = description
        if tags is not None:
            template.tags = tags

        template.updated_at = datetime.now(timezone.utc)
        self._save_item(template_id, template)
        logger.info(f"Updated audio template: {template_id}")
        return template

    def delete_template(self, template_id: str, audio_source_store=None) -> None:
        """Delete a template.

        Args:
            template_id: Template ID
            audio_source_store: Optional AudioSourceStore for reference check

        Raises:
            ValueError: If template not found or still referenced
        """
        if template_id not in self._items:
            raise ValueError(f"{self._entity_name} not found: {template_id}")

        # Check if any capture audio source references this template
        if audio_source_store is not None:
            from wled_controller.storage.audio_source import CaptureAudioSource

            for source in audio_source_store.get_all_sources():
                if (
                    isinstance(source, CaptureAudioSource)
                    and getattr(source, "audio_template_id", None) == template_id
                ):
                    raise ValueError(
                        f"Cannot delete audio template '{template_id}': "
                        f"referenced by audio source '{source.name}' ({source.id})"
                    )

        del self._items[template_id]
        self._delete_item(template_id)
        logger.info(f"Deleted audio template: {template_id}")
