"""FastAPI dependency injection: agent factory, API key resolution, language lookup."""

import os

from fastapi import HTTPException, status

from yaduha.agent.anthropic import AnthropicAgent
from yaduha.agent.gemini import GeminiAgent
from yaduha.agent.ollama import OllamaAgent
from yaduha.agent.openai import OpenAIAgent
from yaduha.api.models import AgentConfig, EvaluatorConfig
from yaduha.evaluator import Evaluator, OpenAIEvaluator
from yaduha.language.exceptions import LanguageNotFoundError
from yaduha.language.language import Language
from yaduha.loader import LanguageLoader

_PROVIDERS = {
    "openai": {
        "cls": OpenAIAgent,
        "env_var": "OPENAI_API_KEY",
        "header": "x-openai-key",
        "requires_key": True,
    },
    "anthropic": {
        "cls": AnthropicAgent,
        "env_var": "ANTHROPIC_API_KEY",
        "header": "x-anthropic-key",
        "requires_key": True,
    },
    "gemini": {
        "cls": GeminiAgent,
        "env_var": "GEMINI_API_KEY",
        "header": "x-gemini-key",
        "requires_key": True,
    },
    "ollama": {
        "cls": OllamaAgent,
        "env_var": None,
        "header": None,
        "requires_key": False,
    },
}


def _resolve_api_key(provider: str, headers: dict[str, str]) -> str | None:
    info = _PROVIDERS[provider]
    if not info["requires_key"]:
        return None
    # Provider-specific header
    if info["header"] and info["header"] in headers:
        return headers[info["header"]]
    # Generic header
    if "x-api-key" in headers:
        return headers["x-api-key"]
    # Environment variable
    if info["env_var"]:
        key = os.environ.get(info["env_var"])
        if key:
            return key
    return None


def create_agent(config: AgentConfig, headers: dict[str, str]):
    if config.provider not in _PROVIDERS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Unknown provider '{config.provider}'. Available: {list(_PROVIDERS)}",
        )

    info = _PROVIDERS[config.provider]

    if info["requires_key"]:
        api_key = _resolve_api_key(config.provider, headers)
        if not api_key:
            raise HTTPException(
                status_code=status.HTTP_401_UNAUTHORIZED,
                detail=(
                    f"No API key for provider '{config.provider}'. "
                    f"Set {info['env_var']} env var or pass '{info['header']}' header."
                ),
            )
        try:
            return info["cls"](
                model=config.model,
                api_key=api_key,
                temperature=config.temperature,
            )
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid agent configuration: {e}",
            )
    else:
        try:
            return info["cls"](model=config.model, temperature=config.temperature)
        except Exception as e:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"Invalid agent configuration: {e}",
            )


_EVALUATORS = {
    "openai_embedding": {
        "cls": OpenAIEvaluator,
        "key_provider": "openai",
    },
}

# Register evaluators that don't need API keys (available when optional deps installed)
try:
    from yaduha.evaluator.chrf import ChrfEvaluator

    _EVALUATORS["chrf"] = {"cls": ChrfEvaluator, "key_provider": None}
except ImportError:
    pass

try:
    from yaduha.evaluator.bleu import BleuEvaluator

    _EVALUATORS["bleu"] = {"cls": BleuEvaluator, "key_provider": None}
except ImportError:
    pass

try:
    from yaduha.evaluator.bertscore import BertScoreEvaluator

    _EVALUATORS["bertscore"] = {"cls": BertScoreEvaluator, "key_provider": None}
except ImportError:
    pass

try:
    from yaduha.evaluator.comet import CometEvaluator

    _EVALUATORS["comet"] = {"cls": CometEvaluator, "key_provider": None}
except ImportError:
    pass


def create_evaluator(config: EvaluatorConfig, headers: dict[str, str]) -> Evaluator:
    if config.type not in _EVALUATORS:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Unknown evaluator type '{config.type}'. Available: {list(_EVALUATORS)}",
        )

    info = _EVALUATORS[config.type]

    kwargs: dict = {}
    if config.model:
        kwargs["model"] = config.model
    if info["key_provider"]:
        api_key = _resolve_api_key(info["key_provider"], headers)
        if api_key:
            kwargs["api_key"] = api_key

    return info["cls"](**kwargs)


def get_language(language_code: str) -> Language:
    try:
        return LanguageLoader.load_language(language_code)
    except LanguageNotFoundError:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"Language '{language_code}' not found. Use GET /languages to list installed languages.",
        )


def get_sentence_type(language: Language, sentence_type_name: str):
    for st in language.sentence_types:
        if st.__name__ == sentence_type_name:
            return st
    raise HTTPException(
        status_code=status.HTTP_404_NOT_FOUND,
        detail=(
            f"Sentence type '{sentence_type_name}' not found in language '{language.code}'. "
            f"Available: {[st.__name__ for st in language.sentence_types]}"
        ),
    )
