"""Provider registry — resolves ALIVE_PROVIDER to a concrete LLMProvider."""

import importlib
import json
import os

from alive.llm.base import LLMProvider

PROVIDERS: dict[str, str] = {
    "claude": "alive.llm.claude_provider:ClaudeProvider",
    "openai": "alive.llm.openai_provider:OpenAIProvider",
    "ollama": "alive.llm.ollama_provider:OllamaProvider",
    "deepseek": "alive.llm.deepseek_provider:DeepSeekProvider",
}

# Maps provider names to the env vars they check for API keys
_PROVIDER_KEY_VARS: dict[str, list[str]] = {
    "claude": ["ALIVE_CLAUDE_KEY", "ANTHROPIC_API_KEY"],
    "openai": ["ALIVE_OPENAI_KEY", "OPENAI_API_KEY"],
    "deepseek": ["ALIVE_DEEPSEEK_KEY", "DEEPSEEK_API_KEY"],
    "ollama": [],  # no key needed
}


def _load_config() -> dict:
    """Load ~/.alive/config.json if it exists."""
    from alive.config import CONFIG_FILE

    if CONFIG_FILE.exists():
        try:
            return json.loads(CONFIG_FILE.read_text())
        except (json.JSONDecodeError, OSError):
            return {}
    return {}


def _inject_config_keys(cfg: dict) -> None:
    """Set env vars from config.json keys if not already set."""
    key_map = {
        "claude_key": "ANTHROPIC_API_KEY",
        "openai_key": "OPENAI_API_KEY",
        "deepseek_key": "DEEPSEEK_API_KEY",
    }
    for config_key, env_var in key_map.items():
        value = cfg.get(config_key)
        if value and not os.environ.get(env_var):
            os.environ[env_var] = value


def _auto_detect_provider() -> str:
    """Auto-detect the best available provider from API keys.

    Priority: claude > openai > deepseek > ollama (always available).
    """
    for name in ["claude", "openai", "deepseek"]:
        env_vars = _PROVIDER_KEY_VARS[name]
        if any(os.environ.get(var) for var in env_vars):
            return name
    return "ollama"


def _instantiate(name: str) -> LLMProvider:
    """Import and instantiate a provider by name."""
    module_path, class_name = PROVIDERS[name].rsplit(":", 1)
    module = importlib.import_module(module_path)
    cls = getattr(module, class_name)
    return cls()


def get_provider(name: str | None = None) -> LLMProvider:
    """Instantiate the requested (or auto-detected) LLM provider.

    Resolution order:
    1. Explicit ``name`` argument
    2. ``ALIVE_PROVIDER`` environment variable
    3. ``provider`` field in ``~/.alive/config.json``
    4. Auto-detect from available API keys (claude > openai > deepseek > ollama)
    """
    # Load config and inject saved API keys into env
    cfg = _load_config()
    _inject_config_keys(cfg)

    # Resolve provider name
    resolved = (
        name
        or os.environ.get("ALIVE_PROVIDER")
        or cfg.get("provider")
    )

    if resolved:
        if resolved not in PROVIDERS:
            raise ValueError(
                f"Unknown provider '{resolved}'. "
                f"Choose from: {', '.join(PROVIDERS)}\n\n"
                f"Set a provider with: alive config --provider <name>"
            )
        return _instantiate(resolved)

    # Auto-detect from available API keys
    detected = _auto_detect_provider()
    return _instantiate(detected)
