"""MQTT source storage using SQLite."""

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

from ledgrab.storage.base_sqlite_store import BaseSqliteStore
from ledgrab.storage.database import Database
from ledgrab.storage.mqtt_source import MQTTSource
from ledgrab.utils import get_logger, secret_box

logger = get_logger(__name__)


class MQTTSourceStore(BaseSqliteStore[MQTTSource]):
    """Persistent storage for MQTT sources (broker connections)."""

    _table_name = "mqtt_sources"
    _entity_name = "MQTT source"

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

    def _migrate_plaintext_passwords(self) -> None:
        """Encrypt any stored MQTT broker passwords still in plaintext at rest.

        Mirrors the HA-token migration: inspect raw DB rows, re-save items
        that lack the encryption envelope so the next persistence pass
        writes them in encrypted form.
        """
        migrated = 0
        try:
            rows = self._db.load_all(self._table_name)
        except Exception as exc:
            logger.error("Could not inspect rows for MQTT password migration: %s", exc)
            return
        for row in rows:
            sid = row.get("id")
            raw_pw = row.get("password", "") or ""
            if not sid or not raw_pw:
                continue
            if secret_box.is_encrypted(raw_pw):
                continue
            source = self._items.get(sid)
            if source is None:
                continue
            try:
                self._save_item(sid, source)
                migrated += 1
            except Exception as exc:
                logger.error("Failed to migrate MQTT password for %s: %s", sid, exc)
        if migrated:
            logger.warning(
                "MIGRATION: encrypted %d plaintext MQTT broker password(s) at rest.",
                migrated,
            )

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

    def create_source(
        self,
        name: str,
        broker_host: str,
        broker_port: int = 1883,
        username: str = "",
        password: str = "",
        client_id: str = "ledgrab",
        base_topic: str = "ledgrab",
        description: str | None = None,
        tags: List[str] | None = None,
        icon: str | None = None,
        icon_color: str | None = None,
    ) -> MQTTSource:
        if not broker_host:
            raise ValueError("broker_host is required")

        self._check_name_unique(name)

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

        source = MQTTSource(
            id=sid,
            name=name,
            created_at=now,
            updated_at=now,
            broker_host=broker_host,
            broker_port=broker_port,
            username=username,
            password=password,
            client_id=client_id,
            base_topic=base_topic,
            description=description,
            tags=tags or [],
            icon=icon or "",
            icon_color=icon_color or "",
        )

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

    def update_source(
        self,
        source_id: str,
        name: str | None = None,
        broker_host: str | None = None,
        broker_port: int | None = None,
        username: str | None = None,
        password: str | None = None,
        client_id: str | None = None,
        base_topic: str | None = None,
        description: str | None = None,
        tags: List[str] | None = None,
        icon: str | None = None,
        icon_color: str | None = None,
    ) -> MQTTSource:
        existing = self.get(source_id)

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

        updated = MQTTSource(
            id=existing.id,
            name=name if name is not None else existing.name,
            created_at=existing.created_at,
            updated_at=datetime.now(timezone.utc),
            broker_host=broker_host if broker_host is not None else existing.broker_host,
            broker_port=broker_port if broker_port is not None else existing.broker_port,
            username=username if username is not None else existing.username,
            password=password if password is not None else existing.password,
            client_id=client_id if client_id is not None else existing.client_id,
            base_topic=base_topic if base_topic is not None else existing.base_topic,
            description=description if description is not None else existing.description,
            tags=tags if tags is not None else existing.tags,
            icon=icon if icon is not None else existing.icon,
            icon_color=icon_color if icon_color is not None else existing.icon_color,
        )

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