"""Check registry and registration decorator."""

from __future__ import annotations

from typing import Any, Callable, TypeVar

from ai_qa.core.check import BaseCheck
from ai_qa.exceptions import CheckNotFoundError

T = TypeVar("T", bound=BaseCheck)


class CheckRegistry:
    """Registry for all available checks.

    Checks are registered via the @register decorator.
    """

    _checks: dict[str, type[BaseCheck]] = {}

    @classmethod
    def register(cls, name: str, check_class: type[BaseCheck]) -> None:
        """Register a check class.

        Args:
            name: Check name (e.g., "schema", "regex").
            check_class: Check class (must extend BaseCheck).
        """
        cls._checks[name] = check_class

    @classmethod
    def get(cls, name: str) -> type[BaseCheck]:
        """Get check class by name.

        Args:
            name: Check name.

        Returns:
            Check class.

        Raises:
            CheckNotFoundError: If check not found.
        """
        if name not in cls._checks:
            available = ", ".join(sorted(cls._checks.keys()))
            raise CheckNotFoundError(
                f"Check '{name}' not found.\n" f"Available checks: {available}"
            )
        return cls._checks[name]

    @classmethod
    def list(cls) -> list[str]:
        """List all registered check names.

        Returns:
            Sorted list of check names.
        """
        return sorted(cls._checks.keys())

    @classmethod
    def instantiate(cls, name: str, **kwargs: Any) -> BaseCheck:
        """Create an instance of a check.

        Args:
            name: Check name.
            **kwargs: Arguments to pass to check constructor.

        Returns:
            Check instance.

        Raises:
            CheckNotFoundError: If check not found.
        """
        check_class = cls.get(name)
        return check_class(**kwargs)


def register(name: str) -> Callable[[type[T]], type[T]]:
    """Decorator to register a check.

    Usage:
        @register("my_check")
        class MyCheck(BaseCheck):
            ...

    Args:
        name: Check name for registration.

    Returns:
        Decorator function.
    """

    def decorator(check_class: type[T]) -> type[T]:
        check_class.name = name
        CheckRegistry.register(name, check_class)
        return check_class

    return decorator


def get_check(name: str, **kwargs: Any) -> BaseCheck:
    """Get a check instance by name.

    Args:
        name: Check name.
        **kwargs: Arguments to pass to check constructor.

    Returns:
        Check instance.

    Raises:
        CheckNotFoundError: If check not found.
    """
    return CheckRegistry.instantiate(name, **kwargs)


def list_checks() -> list[str]:
    """List all registered check names.

    Returns:
        Sorted list of check names.
    """
    return CheckRegistry.list()
