"""Backend registry for Cleave TUI.

This module provides a registry of available backends and utilities
for backend discovery and selection.

Usage:
    from cleave.tui.backends import get_backend, list_backends

    # Get a specific backend
    backend = get_backend("claude")

    # List all available backends
    for name in list_backends():
        print(name)
"""

from cleave.tui.backends.base import (
    Backend,
    BackendAuthError,
    BackendConfig,
    BackendConnectionError,
    BackendError,
    BackendQueryError,
    BackendState,
    Message,
)

# Backend registry - populated lazily
_BACKENDS: dict[str, type[Backend]] = {}


def _ensure_registry() -> None:
    """Populate the backend registry if empty."""
    global _BACKENDS
    if _BACKENDS:
        return

    # Always register Claude backend (may fail at runtime if SDK missing)
    from cleave.tui.backends.claude import ClaudeBackend

    _BACKENDS["claude"] = ClaudeBackend

    # Try to register OpenAI-compatible backend
    try:
        from cleave.tui.backends.openai_compat import OpenAICompatBackend

        _BACKENDS["openai"] = OpenAICompatBackend
        _BACKENDS["ollama"] = OpenAICompatBackend
        _BACKENDS["vllm"] = OpenAICompatBackend
        _BACKENDS["llamacpp"] = OpenAICompatBackend
    except ImportError:
        pass  # Optional dependency not installed


def list_backends() -> list[str]:
    """List available backend names.

    Returns:
        List of backend identifiers.
    """
    _ensure_registry()
    return list(_BACKENDS.keys())


def get_backend(name: str) -> Backend:
    """Get a backend instance by name.

    Args:
        name: Backend identifier (e.g., 'claude', 'ollama').

    Returns:
        Backend instance.

    Raises:
        KeyError: If backend not found.
    """
    _ensure_registry()
    if name not in _BACKENDS:
        available = ", ".join(_BACKENDS.keys())
        raise KeyError(f"Unknown backend '{name}'. Available: {available}")
    return _BACKENDS[name]()


def get_backend_class(name: str) -> type[Backend]:
    """Get a backend class by name.

    Args:
        name: Backend identifier.

    Returns:
        Backend class.

    Raises:
        KeyError: If backend not found.
    """
    _ensure_registry()
    if name not in _BACKENDS:
        available = ", ".join(_BACKENDS.keys())
        raise KeyError(f"Unknown backend '{name}'. Available: {available}")
    return _BACKENDS[name]


def register_backend(name: str, backend_class: type[Backend]) -> None:
    """Register a custom backend.

    Args:
        name: Backend identifier.
        backend_class: Backend class to register.
    """
    _ensure_registry()
    _BACKENDS[name] = backend_class


def detect_available_backend() -> str | None:
    """Auto-detect which backend is available.

    Checks in order:
    1. Claude SDK (if authenticated)
    2. Ollama (if running locally)
    3. OpenAI (if API key set)

    Returns:
        Backend name, or None if none available.
    """
    _ensure_registry()

    # Try Claude first
    if "claude" in _BACKENDS:
        is_auth, _ = _BACKENDS["claude"].check_auth()
        if is_auth:
            return "claude"

    # Try Ollama (local)
    if "ollama" in _BACKENDS:
        is_auth, _ = _BACKENDS["ollama"].check_auth()
        if is_auth:
            return "ollama"

    # Try OpenAI (cloud)
    if "openai" in _BACKENDS:
        is_auth, _ = _BACKENDS["openai"].check_auth()
        if is_auth:
            return "openai"

    return None


__all__ = [
    # Base types
    "Backend",
    "BackendConfig",
    "BackendState",
    "Message",
    # Exceptions
    "BackendError",
    "BackendAuthError",
    "BackendConnectionError",
    "BackendQueryError",
    # Registry functions
    "get_backend",
    "get_backend_class",
    "list_backends",
    "register_backend",
    "detect_available_backend",
]
