"""LLM API adapters for dotpromptz."""

from importlib import import_module
from typing import TYPE_CHECKING, Any

from ._base import Adapter, GenerateResponse, GeneratedImage, Usage

if TYPE_CHECKING:
    from .anthropic import AnthropicAdapter
    from .google import GoogleAdapter
    from .openai import OpenAIAdapter

__all__ = [
    'Adapter',
    'AnthropicAdapter',
    'GenerateResponse',
    'GeneratedImage',
    'GoogleAdapter',
    'OpenAIAdapter',
    'Usage',
    'get_adapter',
    'list_adapters',
]

# ---------------------------------------------------------------------------
# Adapter registry
# ---------------------------------------------------------------------------

_ADAPTER_PATHS: dict[str, tuple[str, str]] = {
    'openai': ('dotpromptz.adapters.openai', 'OpenAIAdapter'),
    'anthropic': ('dotpromptz.adapters.anthropic', 'AnthropicAdapter'),
    'google': ('dotpromptz.adapters.google', 'GoogleAdapter'),
}
_ADAPTERS: dict[str, type[Adapter]] = {}

_CLASS_TO_ADAPTER_NAME = {
    'OpenAIAdapter': 'openai',
    'AnthropicAdapter': 'anthropic',
    'GoogleAdapter': 'google',
}


def _load_adapter_class(name: str) -> type[Adapter]:
    """Load and cache an adapter class by name.

    Args:
        name: Registered adapter name (e.g. ``'openai'``).

    Returns:
        Adapter class type for the given adapter name.

    Raises:
        ImportError: If the adapter implementation cannot be imported.
    """
    cached = _ADAPTERS.get(name)
    if cached is not None:
        return cached

    module_path, class_name = _ADAPTER_PATHS[name]
    module = import_module(module_path)
    adapter_cls = getattr(module, class_name)
    _ADAPTERS[name] = adapter_cls
    return adapter_cls


def list_adapters() -> list[str]:
    """Return the names of all registered adapters.

    Returns:
        A sorted list of adapter name strings.
    """
    return sorted(_ADAPTER_PATHS.keys())


def get_adapter(name: str, **kwargs: Any) -> Adapter:
    """Instantiate an adapter by name.

    Args:
        name: One of the registered adapter names (see ``list_adapters()``).
        **kwargs: Keyword arguments forwarded to the adapter constructor.

    Returns:
        An ``Adapter`` instance.

    Raises:
        ValueError: If the adapter name is unknown.
    """
    if name not in _ADAPTER_PATHS:
        available = ', '.join(list_adapters())
        raise ValueError(f'Unknown adapter: {name!r}. Available: {available}')

    adapter_cls = _load_adapter_class(name)
    return adapter_cls(**kwargs)


def __getattr__(name: str) -> Any:
    """Lazily resolve adapter class attributes.

    Supports ``from dotpromptz.adapters import OpenAIAdapter`` without
    importing all provider SDKs at module import time.

    Args:
        name: Requested module attribute name.

    Returns:
        The requested adapter class object.

    Raises:
        AttributeError: If *name* is not a known module attribute.
    """
    adapter_name = _CLASS_TO_ADAPTER_NAME.get(name)
    if adapter_name is None:
        raise AttributeError(f'module {__name__!r} has no attribute {name!r}')
    return _load_adapter_class(adapter_name)
