"""Configuration utilities for creating providers from config."""

from __future__ import annotations

from typing import TYPE_CHECKING

from oclawma.config import Config, ConfigurationError, ModelProfile
from oclawma.providers.base import BaseProvider
from oclawma.providers.fallback import FallbackProvider
from oclawma.providers.kimi import KimiProvider
from oclawma.providers.ollama import OllamaProvider

if TYPE_CHECKING:
    from oclawma.context import ContextBudget


def create_provider_from_profile(
    config: Config,
    profile_name: str | None = None,
) -> BaseProvider:
    """Create a provider instance from a configuration profile.

    Args:
        config: The loaded configuration.
        profile_name: Name of the profile to use. If None, uses active profile.

    Returns:
        Configured provider instance.

    Raises:
        ConfigurationError: If profile is not found or invalid.
    """
    if profile_name:
        profile = config.get_profile(profile_name)
        if not profile:
            raise ConfigurationError(f"Profile '{profile_name}' not found")
    else:
        profile = config.get_active_profile()

    return _create_provider_from_profile(profile)


def _create_provider_from_profile(profile: ModelProfile) -> BaseProvider:
    """Create provider from a profile."""
    if profile.provider == "ollama":
        return OllamaProvider(
            base_url=profile.base_url or "http://localhost:11434",
        )

    elif profile.provider == "kimi":
        api_key = profile.get_api_key()
        if not api_key:
            raise ConfigurationError(
                f"Profile '{profile.name}' requires an API key. "
                f"Set {profile.api_key_env} environment variable or configure api_key."
            )
        return KimiProvider(
            base_url=profile.base_url,
            api_key=api_key,
        )

    else:
        raise ConfigurationError(f"Unknown provider type: {profile.provider}")


def create_provider_with_fallback(config: Config) -> BaseProvider:
    """Create provider with fallback support based on configuration.

    Args:
        config: The loaded configuration.

    Returns:
        Provider instance, potentially with fallback support.
    """
    if not config.fallback.enabled:
        return create_provider_from_profile(config)

    # Get primary and fallback profiles
    primary_profile = config.get_profile(config.fallback.primary_profile)
    fallback_profile = config.get_profile(config.fallback.fallback_profile)

    if not primary_profile:
        raise ConfigurationError(f"Primary profile '{config.fallback.primary_profile}' not found")

    if not fallback_profile:
        # Fallback profile not found, just use primary
        return _create_provider_from_profile(primary_profile)

    # Create providers
    try:
        primary = _create_provider_from_profile(primary_profile)
    except ConfigurationError:
        # If primary is not configured (e.g., no API key), try fallback directly
        return _create_provider_from_profile(fallback_profile)

    try:
        fallback = _create_provider_from_profile(fallback_profile)
    except ConfigurationError:
        # Fallback not configured, just use primary
        return primary

    return FallbackProvider(primary, fallback)


def get_model_from_config(config: Config, profile_name: str | None = None) -> str:
    """Get the model name from configuration.

    Args:
        config: The loaded configuration.
        profile_name: Optional profile name override.

    Returns:
        Model name string.
    """
    if profile_name:
        profile = config.get_profile(profile_name)
        if profile:
            return profile.model

    return config.get_active_profile().model


def load_context_budget(config: Config) -> ContextBudget:  # noqa: F821
    """Load context budget from configuration.

    Args:
        config: The loaded configuration.

    Returns:
        ContextBudget instance with configured thresholds.
    """
    from oclawma.context import ContextBudget

    return ContextBudget(
        total_budget=config.budget.total_budget,
        warning_threshold=config.budget.warning_threshold,
        critical_threshold=config.budget.critical_threshold,
    )
