"""LLM model definitions and provider configurations."""

from __future__ import annotations

import logging
import os
from typing import Literal

import sentry_sdk
from pydantic.dataclasses import dataclass as pydantic_dataclass

logger = logging.getLogger(__name__)


@pydantic_dataclass
class LLM:
    name: str  # On Azure OpenAI Service, this is the deployment name
    model_type: Literal["openai", "anthropic", "google"]
    input_cost: float | None = None  # USD per 1M tokens
    cached_input_cost: float | None = None
    output_cost: float | None = None


@pydantic_dataclass
class OpenAI_GPT_4_1(LLM):
    name: str = "gpt-4.1"
    model_type: Literal["openai", "anthropic", "google"] = "openai"
    input_cost: float = 2.00
    cached_input_cost: float = 0.50
    output_cost: float = 8.00


@pydantic_dataclass
class OpenAI_GPT_5_Mini(LLM):
    name: str = "gpt-5-mini"
    model_type: Literal["openai", "anthropic", "google"] = "openai"
    input_cost: float = 0.25
    cached_input_cost: float = 0.03
    output_cost: float = 2.00


@pydantic_dataclass
class Anthropic_Claude_Sonnet_4_5(LLM):
    name: str = "us.anthropic.claude-sonnet-4-5-20250929-v1:0"
    model_type: Literal["openai", "anthropic", "google"] = "anthropic"
    input_cost: float = 3.00
    output_cost: float = 15.00


@pydantic_dataclass
class Anthropic_Claude_Haiku_4_5(LLM):
    name: str = "us.anthropic.claude-haiku-4-5-20251001-v1:0"
    model_type: Literal["openai", "anthropic", "google"] = "anthropic"
    input_cost: float = 1.00
    output_cost: float = 5.00


# =============================================================================
# Model Selection (based on available providers)
# =============================================================================

has_openai = bool(os.environ.get("AZURE_OPENAI_API_KEY"))
has_anthropic = bool(os.environ.get("AWS_ACCESS_KEY_ID") and os.environ.get("AWS_SECRET_ACCESS_KEY"))

if has_openai:
    OPENAI_MODEL: LLM = OpenAI_GPT_5_Mini()
else:
    logger.warning("AZURE_OPENAI_API_KEY not set, falling back to Anthropic for OpenAI-preferred tasks")
    sentry_sdk.capture_message("AZURE_OPENAI_API_KEY not set, falling back to Anthropic", level="warning")
    OPENAI_MODEL = Anthropic_Claude_Sonnet_4_5()

if has_anthropic:
    ANTHROPIC_MODEL: LLM = Anthropic_Claude_Sonnet_4_5()
    HAIKU_MODEL: LLM = Anthropic_Claude_Haiku_4_5()
else:
    logger.warning("AWS credentials not set, falling back to OpenAI for Anthropic-preferred tasks")
    sentry_sdk.capture_message("AWS credentials not set, falling back to OpenAI", level="warning")
    ANTHROPIC_MODEL = OpenAI_GPT_5_Mini()
    HAIKU_MODEL = OpenAI_GPT_5_Mini()

TASK_MODELS: dict[str, LLM] = {
    "EXECUTE_MODEL": OPENAI_MODEL,
    "OPTIMIZE_MODEL": OPENAI_MODEL,
    "RANKING_MODEL": OPENAI_MODEL,
    "REFINEMENT_MODEL": ANTHROPIC_MODEL,
    "EXPLANATIONS_MODEL": ANTHROPIC_MODEL,
    "OPTIMIZATION_REVIEW_MODEL": ANTHROPIC_MODEL,
    "CODE_REPAIR_MODEL": ANTHROPIC_MODEL,
    "ADAPTIVE_OPTIMIZE_MODEL": ANTHROPIC_MODEL,
}


def __getattr__(name: str) -> LLM:
    if name in TASK_MODELS:
        return TASK_MODELS[name]
    msg = f"module {__name__!r} has no attribute {name!r}"
    raise AttributeError(msg)
