"""
providers/registry.py — Provider factory.

Keys are resolved from:
  1. Per-user setting (user_settings table) — if user_id is provided
  2. Global credential_store (system:anthropic_api_key / system:openrouter_api_key / system:openai_api_key)

API keys are never read from .env — configure them via Settings → Credentials.
"""
from __future__ import annotations

from .base import AIProvider


async def _resolve_key(provider: str, user_id: str | None = None) -> str:
    """Resolve the API key for a provider: user setting → global credential store."""
    from ..database import credential_store, user_settings_store

    if user_id:
        user_key = await user_settings_store.get(user_id, f"{provider}_api_key")
        if user_key:
            return user_key

    return await credential_store.get(f"system:{provider}_api_key") or ""


async def _get_default_provider() -> str:
    """Return the default provider name: credential_store → settings → 'anthropic'."""
    from ..database import credential_store
    from ..config import settings
    val = await credential_store.get("system:default_provider")
    if val and val in {"anthropic", "openrouter", "openai"}:
        return val
    return settings.default_provider


async def get_provider(user_id: str | None = None) -> AIProvider:
    """Return the default provider, with keys resolved for the given user."""
    return await get_provider_for_name(await _get_default_provider(), user_id=user_id)


async def get_provider_for_name(name: str, user_id: str | None = None) -> AIProvider:
    """Return a provider instance configured with the resolved key."""
    key = await _resolve_key(name, user_id=user_id)
    if not key:
        raise RuntimeError(
            f"No API key configured for provider '{name}'. "
            "Set it in Settings → General or via environment variable."
        )

    if name == "anthropic":
        from .anthropic_provider import AnthropicProvider
        return AnthropicProvider(api_key=key)
    elif name == "openrouter":
        from .openrouter_provider import OpenRouterProvider
        return OpenRouterProvider(api_key=key, app_name="oAI-Web")
    elif name == "openai":
        from .openai_provider import OpenAIProvider
        return OpenAIProvider(api_key=key)
    else:
        raise RuntimeError(
            f"Unknown provider '{name}'. Valid values: 'anthropic', 'openrouter', 'openai'"
        )


async def get_provider_for_model(model_str: str, user_id: str | None = None) -> tuple[AIProvider, str]:
    """
    Parse a "provider:model" string and return (provider_instance, bare_model_id).

    If the model string has no provider prefix, the default provider is used.
    Examples:
      "anthropic:claude-sonnet-5"  → (AnthropicProvider, "claude-sonnet-5")
      "openrouter:openai/gpt-4o"     → (OpenRouterProvider, "openai/gpt-4o")
      "claude-sonnet-5"            → (default_provider,   "claude-sonnet-5")
    """
    _known = {"anthropic", "openrouter", "openai"}
    if ":" in model_str:
        prefix, bare = model_str.split(":", 1)
        if prefix in _known:
            return await get_provider_for_name(prefix, user_id=user_id), bare
    # No recognised prefix — use default provider, full string as model ID
    return await get_provider_for_name(await _get_default_provider(), user_id=user_id), model_str


async def get_available_providers(user_id: str | None = None) -> list[str]:
    """Return names of providers that have a valid API key for the given user."""
    available = []
    if await _resolve_key("anthropic", user_id=user_id):
        available.append("anthropic")
    if await _resolve_key("openrouter", user_id=user_id):
        available.append("openrouter")
    if await _resolve_key("openai", user_id=user_id):
        available.append("openai")
    return available
