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

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

from wled_controller.core.audio.filters.registry import AudioFilterRegistry
from wled_controller.core.filters.filter_instance import FilterInstance
from wled_controller.storage.audio_processing_template import AudioProcessingTemplate
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 AudioProcessingTemplateStore(BaseSqliteStore[AudioProcessingTemplate]):
    """Storage for audio processing templates.

    All templates are persisted to the database.
    """

    _table_name = "audio_processing_templates"
    _entity_name = "Audio processing template"
    _version = "1.0.0"

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

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

    def create_template(
        self,
        name: str,
        filters: Optional[List[FilterInstance]] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> AudioProcessingTemplate:
        self._check_name_unique(name)

        if filters is None:
            filters = []

        # Validate filter IDs
        for fi in filters:
            if not AudioFilterRegistry.is_registered(fi.filter_id):
                raise ValueError(f"Unknown audio filter type: '{fi.filter_id}'")

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

        template = AudioProcessingTemplate(
            id=template_id,
            name=name,
            filters=filters,
            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 processing template: {name} ({template_id})")
        return template

    def update_template(
        self,
        template_id: str,
        name: Optional[str] = None,
        filters: Optional[List[FilterInstance]] = None,
        description: Optional[str] = None,
        tags: Optional[List[str]] = None,
    ) -> AudioProcessingTemplate:
        template = self.get(template_id)

        if name is not None:
            self._check_name_unique(name, exclude_id=template_id)
            template.name = name
        if filters is not None:
            # Validate filter IDs
            for fi in filters:
                if not AudioFilterRegistry.is_registered(fi.filter_id):
                    raise ValueError(f"Unknown audio filter type: '{fi.filter_id}'")
            template.filters = filters
        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 processing template: {template_id}")
        return template

    def resolve_filter_instances(self, filter_instances, _visited=None):
        """Recursively resolve filter instances, expanding audio_filter_template references.

        Returns a flat list of FilterInstance objects with no audio_filter_template entries.
        """
        if _visited is None:
            _visited = set()
        resolved = []
        for fi in filter_instances:
            if fi.filter_id == "audio_filter_template":
                template_id = fi.options.get("template_id", "")
                if not template_id or template_id in _visited:
                    continue
                try:
                    ref_template = self.get_template(template_id)
                    _visited.add(template_id)
                    resolved.extend(self.resolve_filter_instances(ref_template.filters, _visited))
                    _visited.discard(template_id)
                except ValueError:
                    logger.warning(
                        f"Referenced audio filter template '{template_id}' not found, skipping"
                    )
            else:
                resolved.append(fi)
        return resolved
