"""Typed scheduled-action registry and qBittorrent sampling action."""

from __future__ import annotations

import time
from dataclasses import dataclass
from typing import Any, Protocol

from media_library_viewer_api.services.qbittorrent_store import QbittorrentSampleStore
from media_library_viewer_api.widgets.sources import ServiceRecord, _qbittorrent_client

QBITTORRENT_SPEED_ACTION = "qbittorrent.speed_sample"


def _safe_int(value: Any, default: int = 0) -> int:
    try:
        return int(value)
    except (TypeError, ValueError):
        return default


@dataclass(frozen=True)
class ActionResult:
    data: dict[str, Any]


class ScheduledAction(Protocol):
    action_key: str

    def run(self, service: ServiceRecord) -> ActionResult:
        """Run one action for one service instance."""
        return ActionResult(data={})


class QbittorrentSpeedAction:
    action_key = QBITTORRENT_SPEED_ACTION

    def run(self, service: ServiceRecord) -> ActionResult:
        base_url = str(service.config.get("base_url") or "")
        username = str(service.secrets.get("username") or "")
        password = str(service.secrets.get("password") or "")
        timeout = _safe_int(service.config.get("timeout_seconds") or 60, 60)
        if not base_url or not username or not password:
            raise ValueError("qBittorrent service is missing base_url, username, or password")

        client = _qbittorrent_client((service.id, base_url, username, password, timeout))
        payload = client.maindata()
        server_state = payload.get("server_state", {})
        dl_speed = _safe_int(server_state.get("dl_info_speed", 0) or 0)
        up_speed = _safe_int(server_state.get("up_info_speed", 0) or 0)
        ts = _safe_int(time.time())
        store = QbittorrentSampleStore()
        store.append(
            service.id,
            ts,
            dl_speed,
            up_speed,
            retention_seconds=_safe_int(service.config.get("sample_retention_seconds") or 1800, 1800),
            max_rows=_safe_int(service.config.get("sample_max_rows") or 1200, 1200),
        )
        return ActionResult(data={"ts": ts, "dl_speed": dl_speed, "up_speed": up_speed})


_ACTIONS: dict[str, ScheduledAction] = {
    QBITTORRENT_SPEED_ACTION: QbittorrentSpeedAction(),
}


def get_scheduled_action(action_key: str) -> ScheduledAction | None:
    return _ACTIONS.get(action_key)


def list_scheduled_actions() -> list[str]:
    return sorted(_ACTIONS)


__all__ = [
    "ActionResult",
    "QBITTORRENT_SPEED_ACTION",
    "ScheduledAction",
    "get_scheduled_action",
    "list_scheduled_actions",
]
