from __future__ import annotations

import time
from dataclasses import dataclass, field
from typing import TYPE_CHECKING

from home_agent.core.logging import get_logger

if TYPE_CHECKING:
    from pathlib import Path

    from desktop_notifier.sync import DesktopNotifierSync

    from home_agent.contracts.types import Alert

_desktop_notifier_factory: type[DesktopNotifierSync] | None = None
_desktop_notifier_import_error: Exception | None = None

try:
    from desktop_notifier.sync import DesktopNotifierSync as _DesktopNotifierSync
except ImportError as exc:  # pragma: no cover - exercised via monkeypatch
    _desktop_notifier_import_error = exc
else:
    _desktop_notifier_factory = _DesktopNotifierSync


@dataclass
class ToastNotifier:
    log_path: Path
    _notifier: DesktopNotifierSync | None = field(init=False, default=None, repr=False)

    def __post_init__(self) -> None:
        self.log_path.parent.mkdir(parents=True, exist_ok=True)
        self._initialize_notifier()

    def notify(self, alert: Alert) -> None:
        self._append_log(alert)
        logger = get_logger(__name__)
        if self._notifier is None:
            logger.error(
                "notifications.desktop.failed",
                backend="desktop_notifier",
                app_name="home-agent",
                severity=alert.severity.value,
                title=alert.title,
                error="desktop notifier backend unavailable",
            )
            return

        logger.debug(
            "notifications.desktop.start",
            backend="desktop_notifier",
            app_name="home-agent",
            severity=alert.severity.value,
            title=alert.title,
        )
        started = time.perf_counter()
        try:
            self._notifier.send(title=alert.title, message=alert.body)
        except Exception as exc:
            logger.error(
                "notifications.desktop.failed",
                backend="desktop_notifier",
                app_name="home-agent",
                severity=alert.severity.value,
                title=alert.title,
                duration_ms=round((time.perf_counter() - started) * 1000, 3),
                error=str(exc),
            )
            return

        logger.debug(
            "notifications.desktop.completed",
            backend="desktop_notifier",
            app_name="home-agent",
            severity=alert.severity.value,
            title=alert.title,
            duration_ms=round((time.perf_counter() - started) * 1000, 3),
        )

    def _append_log(self, alert: Alert) -> None:
        with self.log_path.open("a", encoding="utf-8") as file:
            file.write(f"[{alert.severity}] {alert.title} - {alert.body}\n")

    def _initialize_notifier(self) -> None:
        logger = get_logger(__name__)
        if _desktop_notifier_factory is None:
            error = "desktop_notifier is not installed"
            if _desktop_notifier_import_error is not None:
                error = str(_desktop_notifier_import_error)
            logger.error(
                "notifications.desktop.init_failed",
                backend="desktop_notifier",
                app_name="home-agent",
                error=error,
            )
            return

        try:
            self._notifier = _desktop_notifier_factory(app_name="home-agent")
        except Exception as exc:
            logger.error(
                "notifications.desktop.init_failed",
                backend="desktop_notifier",
                app_name="home-agent",
                error=str(exc),
            )
