"""Abstract provider command handler interface."""

from __future__ import annotations

from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from typing import Any

from ..database.models import (
    CommandConfig, CommandTracker, CommandTrackerListener,
    ServiceProvider, TelegramBot,
)


@dataclass(frozen=True)
class CommandResponse:
    """A single response from one tracker's command execution."""

    text: str | None = None
    media: list[dict[str, Any]] = field(default_factory=list)


class ProviderCommandHandler(ABC):
    """Base class for provider-specific bot command handlers.

    Each provider (Immich, Gitea, etc.) implements this interface to handle
    its own set of commands. The dispatch layer routes commands to the
    correct handler based on the provider type.

    Each handler call receives a single (tracker, config, provider) context.
    """

    provider_type: str

    @abstractmethod
    def get_provider_commands(self) -> set[str]:
        """Return the set of command names this handler owns.

        These are provider-specific commands (e.g., 'albums' for Immich,
        'repos' for Gitea). Universal commands like 'help' and 'start'
        are handled by the main dispatcher.
        """

    @abstractmethod
    async def handle(
        self,
        cmd: str,
        args: str,
        count: int,
        locale: str,
        response_mode: str,
        provider: ServiceProvider,
        cmd_templates: dict[str, dict[str, str]],
        bot: TelegramBot,
        tracker: CommandTracker,
        config: CommandConfig,
        *,
        listener: CommandTrackerListener | None = None,
        allowed_album_ids: set[str] | None = None,
        page: int = 1,
    ) -> CommandResponse | None:
        """Handle a provider-specific command for a single tracker.

        Args:
            cmd: The command name (without '/').
            args: Arguments after the command.
            count: Number of results to return.
            locale: User's locale ('en', 'ru').
            response_mode: 'media' or 'text' (from this tracker's config).
            provider: The service provider instance for this tracker.
            cmd_templates: Template slots for this tracker's command template config.
            bot: The Telegram bot instance.
            tracker: The command tracker being dispatched.
            config: The command config for this tracker.
            listener: The listener row for this (tracker, bot) pair.
            allowed_album_ids: Precomputed album scope for this (bot, chat)
                pair.  Resolved by the dispatcher from the listener override
                (if set) or the notification-routing graph.  ``None`` means
                "no scope restriction" (rarely the right default for album
                providers — empty set is the common case).
            page: 1-based page number for paginated commands (/search, /find).

        Returns:
            A CommandResponse, or None if unhandled.
        """

    def get_rate_categories(self) -> dict[str, str]:
        """Return rate limit category mapping for this provider's commands.

        Keys are command names, values are category strings.
        Commands not listed default to 'default' category.
        """
        return {}
