"""Postprocessing template storage using SQLite."""

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

from wled_controller.core.filters.filter_instance import FilterInstance
from wled_controller.core.filters.registry import FilterRegistry
from wled_controller.storage.base_sqlite_store import BaseSqliteStore
from wled_controller.storage.database import Database
from wled_controller.storage.picture_source import ProcessedPictureSource
from wled_controller.storage.postprocessing_template import PostprocessingTemplate
from wled_controller.utils import get_logger

logger = get_logger(__name__)


class PostprocessingTemplateStore(BaseSqliteStore[PostprocessingTemplate]):
    """Storage for postprocessing templates.

    All templates are persisted to the database.
    On startup, if no templates exist, a default one is auto-created.
    """

    _table_name = "postprocessing_templates"
    _entity_name = "Postprocessing template"
    _version = "2.0.0"

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

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

    def _ensure_initial_template(self) -> None:
        """Auto-create a default postprocessing template if none exist."""
        if self._items:
            return

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

        template = PostprocessingTemplate(
            id=template_id,
            name="Default",
            filters=[
                FilterInstance("brightness", {"value": 1.0}),
                FilterInstance("saturation", {"value": 1.0}),
                FilterInstance("gamma", {"value": 2.2}),
            ],
            created_at=now,
            updated_at=now,
            description="Default postprocessing template",
        )

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

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

        if filters is None:
            filters = []

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

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

        template = PostprocessingTemplate(
            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 postprocessing 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,
    ) -> PostprocessingTemplate:
        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 FilterRegistry.is_registered(fi.filter_id):
                    raise ValueError(f"Unknown 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 postprocessing template: {template_id}")
        return template

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

        Returns a flat list of FilterInstance objects with no filter_template entries.
        """
        if _visited is None:
            _visited = set()
        resolved = []
        for fi in filter_instances:
            if fi.filter_id == "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 filter template '{template_id}' not found, skipping")
            else:
                resolved.append(fi)
        return resolved

    def get_sources_referencing(self, template_id: str, picture_source_store) -> List[str]:
        """Return names of picture sources that reference this template."""
        return [
            stream.name for stream in picture_source_store.get_all_streams()
            if isinstance(stream, ProcessedPictureSource) and stream.postprocessing_template_id == template_id
        ]
