"""Provider factory using pattern matching."""

from collections.abc import Mapping

from .base import ModelProvider


class ProviderFactory:
    """Creates providers using pattern matching on model prefixes."""

    def __init__(self, config: Mapping[str, str]):
        """Initialize factory with config.

        Args:
            config: Provider credentials for all supported providers
        """
        self.config = dict(config)
        self._cache: dict[str, ModelProvider] = {}

    def get_provider_for_model(self, model: str) -> ModelProvider:
        """Get provider using pattern matching on prefix.

        Args:
            model: Model string in format "provider/model-name"

        Returns:
            ModelProvider instance for the given model

        Raises:
            ValueError: If model format is invalid
        """
        if "/" not in model:
            raise ValueError(
                f"Model must include provider prefix: '{model}'. "
                f"Example: 'openai/gpt-4o' or 'anthropic/claude-3'"
            )

        prefix = model.split("/")[0]

        if prefix in self._cache:
            return self._cache[prefix]

        # Pattern match on prefix to create provider
        provider: ModelProvider

        match prefix:
            case "openai":
                from openai import AsyncOpenAI, OpenAI

                from .openai import OpenAIProvider

                api_key = self.config.get("openai_api_key")
                if not api_key:
                    raise ValueError("OpenAI API key not configured")

                sync_client = OpenAI(
                    api_key=api_key,
                    organization=self.config.get("openai_organization"),
                    project=self.config.get("openai_project"),
                )
                async_client = AsyncOpenAI(
                    api_key=api_key,
                    organization=self.config.get("openai_organization"),
                    project=self.config.get("openai_project"),
                )
                provider = OpenAIProvider(
                    sync_client=sync_client, async_client=async_client
                )

            case "anthropic" | "google" | "vertex_ai":
                # These all use LiteLLM with provider-specific config
                from .litellm import LiteLLMProvider

                # Capture prefix and provide typed getter to satisfy type checkers
                captured_prefix = prefix

                def _cfg_getter() -> dict[str, str]:
                    return self._get_litellm_config(captured_prefix)

                litellm_provider: ModelProvider = LiteLLMProvider(
                    config_getter=_cfg_getter
                )
                provider = litellm_provider

            case _:
                # Unknown prefix - try LiteLLM as fallback
                from .litellm import LiteLLMProvider

                def _fallback_getter() -> dict[str, str]:
                    return dict(self.config)

                fallback_provider: ModelProvider = LiteLLMProvider(
                    config_getter=_fallback_getter
                )
                provider = fallback_provider

        self._cache[prefix] = provider
        return provider

    def _get_litellm_config(self, prefix: str) -> dict[str, str]:
        """Get provider-specific config for LiteLLM.

        Args:
            prefix: Provider prefix (anthropic, google, vertex_ai)

        Returns:
            Config dict for the specific provider
        """
        match prefix:
            case "anthropic":
                api_key = self.config.get("anthropic_api_key", "")
                if not api_key:
                    raise ValueError("Anthropic API key not configured")
                return {"api_key": api_key}
            case "google":
                return {"api_key": self.config.get("google_api_key", "")}
            case "vertex_ai":
                return {
                    "vertex_project": self.config.get("vertex_project", ""),
                    "vertex_location": self.config.get("vertex_location", ""),
                }
            case _:
                return {}

    def reset_cache(self) -> None:
        """Reset the provider cache (useful for testing)."""
        self._cache.clear()
