"""Central default model identifiers for generated configs and built-in tools."""

from __future__ import annotations

from dataclasses import dataclass
from types import MappingProxyType
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from collections.abc import Mapping

__all__ = (
    "AWS_BEDROCK_CLAUDE_OPUS",
    "AZURE_OPENAI_DEFAULT_DEPLOYMENT",
    "CLAUDE_PROVIDER_DEFAULT_SAMPLING_MODEL_SUFFIXES",
    "CODEX_GPT",
    "CODEX_GPT_ENDPOINT",
    "CONFIG_INIT_MODEL_ALTERNATIVES",
    "CONFIG_INIT_MODEL_PRESETS",
    "DEEPSEEK_V4_PRO",
    "GOOGLE_AVATAR_IMAGE",
    "GOOGLE_AVATAR_PROMPT",
    "GOOGLE_IMAGE",
    "GOOGLE_PROVIDER_DEFAULT_SAMPLING_MODEL_SUFFIXES",
    "GOOGLE_VEO",
    "GROQ_TRANSCRIPTION",
    "GROQ_TTS",
    "KIMI_K3",
    "LLAMA_CPP_BASE_URL_DEFAULT",
    "LLAMA_CPP_GEMMA",
    "LLAMA_CPP_QWEN",
    "LOCAL_OPENAI_API_KEY_DEFAULT",
    "LOCAL_QWEN_CONTEXT_WINDOW",
    "LOCAL_QWEN_PRESET_NAME",
    "MEMORY_OLLAMA_LLM",
    "OLLAMA_GEMMA",
    "OLLAMA_HOST_DEFAULT",
    "OLLAMA_QWEN",
    "OPENAI_DALLE",
    "OPENAI_EMBEDDING_DIMENSIONS",
    "OPENAI_EMBEDDING_LARGE",
    "OPENAI_EMBEDDING_SMALL",
    "OPENAI_GPT_LUNA",
    "OPENAI_GPT_TERRA",
    "OPENAI_IMAGE",
    "OPENAI_REALTIME",
    "OPENAI_REALTIME_TRANSCRIPTION",
    "OPENAI_TOOL_SEARCH_MIN_GPT_VERSION",
    "OPENAI_TRANSCRIPTION",
    "OPENAI_TTS",
    "SAAS_MODEL_PRESETS",
    "SENTENCE_TRANSFORMERS_DEFAULT",
    "TOOL_SEARCH_UNSUPPORTED_MODEL_ID_PREFIXES",
    "ZAI_BASE_URL_DEFAULT",
    "ModelPreset",
    "llama_cpp_server_command",
)


@dataclass(frozen=True)
class ModelPreset:
    """Provider/model pair used by generated configuration."""

    provider: str
    id: str
    context_window: int | None = None

    def to_config_dict(self) -> dict[str, int | str]:
        """Return the minimal YAML-safe model config mapping."""
        config: dict[str, int | str] = {"provider": self.provider, "id": self.id}
        if self.context_window is not None:
            config["context_window"] = self.context_window
        return config


_ANTHROPIC_FABLE = "claude-fable-5"
_ANTHROPIC_OPUS = "claude-opus-5"
_ANTHROPIC_SONNET = "claude-sonnet-5"
_ANTHROPIC_HAIKU = "claude-haiku-4-5"
# Claude models that predate tool_search_tool_regex_20251119 (Opus 4.1 and
# earlier — a closed set, so new releases take the native tool-search path
# without a list update). Prefixes cover the aliases plus the dated
# `-YYYYMMDD` and Vertex `@YYYYMMDD` snapshot spellings.
TOOL_SEARCH_UNSUPPORTED_MODEL_ID_PREFIXES = (
    "claude-2",
    "claude-3",
    "claude-opus-4-0",
    "claude-opus-4-1",
    "claude-opus-4-20250514",
    "claude-opus-4@",
    "claude-sonnet-4-0",
    "claude-sonnet-4-20250514",
    "claude-sonnet-4@",
)
_AWS_BEDROCK_CLAUDE_FABLE = "anthropic.claude-fable-5"
AWS_BEDROCK_CLAUDE_OPUS = "anthropic.claude-opus-5"
_AWS_BEDROCK_CLAUDE_SONNET = "anthropic.claude-sonnet-5"
_AWS_BEDROCK_CLAUDE_HAIKU = "anthropic.claude-haiku-4-5"
CODEX_GPT = "gpt-5.6"
CODEX_GPT_ENDPOINT = "gpt-5.6-sol"
KIMI_K3 = "k3"
_OPENAI_GPT = "gpt-5.6"
# OpenAI's Responses-API tool_search tool requires gpt-5.4 or newer; gating
# parses the gpt-N.M version from the model id so new releases take the
# native tool-search path without a list update.
OPENAI_TOOL_SEARCH_MIN_GPT_VERSION = (5, 4)
OPENAI_GPT_TERRA = "gpt-5.6-terra"
OPENAI_GPT_LUNA = "gpt-5.6-luna"
AZURE_OPENAI_DEFAULT_DEPLOYMENT = "your-azure-openai-deployment"

_GOOGLE_GEMINI_FLASH = "gemini-3.6-flash"
_GOOGLE_GEMINI_LITE = "gemini-3.5-flash-lite"
GOOGLE_AVATAR_PROMPT = _GOOGLE_GEMINI_LITE
GOOGLE_IMAGE = "gemini-3.1-flash-image"
GOOGLE_AVATAR_IMAGE = GOOGLE_IMAGE
GOOGLE_VEO = "veo-3.1-generate-preview"
GOOGLE_PROVIDER_DEFAULT_SAMPLING_MODEL_SUFFIXES = (
    _GOOGLE_GEMINI_FLASH,
    _GOOGLE_GEMINI_LITE,
)
CLAUDE_PROVIDER_DEFAULT_SAMPLING_MODEL_SUFFIXES = (
    _ANTHROPIC_FABLE,
    _ANTHROPIC_OPUS,
    _ANTHROPIC_SONNET,
)

_OPENROUTER_CLAUDE_FABLE = "anthropic/claude-fable-5"
_OPENROUTER_CLAUDE_OPUS = "anthropic/claude-opus-5"
_OPENROUTER_CLAUDE_SONNET = "anthropic/claude-sonnet-5"
_OPENROUTER_CLAUDE_HAIKU = "anthropic/claude-haiku-4.5"
_OPENROUTER_GEMINI_FLASH = f"google/{_GOOGLE_GEMINI_FLASH}"
_OPENROUTER_GEMINI_LITE = f"google/{_GOOGLE_GEMINI_LITE}"
_OPENROUTER_OPENAI_TERRA = "openai/gpt-5.6-terra"
_OPENROUTER_NEMOTRON = "nvidia/nemotron-3-super-120b-a12b:free"
_OPENROUTER_DEEPSEEK = "deepseek/deepseek-v4-pro"
_OPENROUTER_GLM = "z-ai/glm-5.2"
_OPENROUTER_KIMI = "moonshotai/kimi-k3"
_OPENROUTER_TENCENT_HY3 = "tencent/hy3-preview"

ZAI_BASE_URL_DEFAULT = "https://api.z.ai/api/paas/v4"

OLLAMA_GEMMA = "gemma4"
OLLAMA_QWEN = "qwen3.6:27b"
OLLAMA_HOST_DEFAULT = "http://localhost:11434"

LLAMA_CPP_GEMMA = "unsloth/gemma-4-26B-A4B-it-GGUF:UD-Q4_K_M"
LLAMA_CPP_QWEN = "unsloth/Qwen3.6-27B-GGUF:UD-Q4_K_XL"
LLAMA_CPP_BASE_URL_DEFAULT = "http://localhost:8080/v1"
LOCAL_OPENAI_API_KEY_DEFAULT = "sk-no-key-required"
LOCAL_QWEN_PRESET_NAME = "qwen3_6_27b"
LOCAL_QWEN_CONTEXT_WINDOW = 256_000
MEMORY_OLLAMA_LLM = OLLAMA_GEMMA

OPENAI_EMBEDDING_SMALL = "text-embedding-3-small"
OPENAI_EMBEDDING_LARGE = "text-embedding-3-large"
SENTENCE_TRANSFORMERS_DEFAULT = "sentence-transformers/all-MiniLM-L6-v2"

OPENAI_TRANSCRIPTION = "gpt-4o-transcribe"
OPENAI_REALTIME_TRANSCRIPTION = "gpt-realtime-whisper"
OPENAI_TTS = "gpt-4o-mini-tts"
OPENAI_REALTIME = "gpt-realtime-2.1"
OPENAI_IMAGE = "gpt-image-2"
OPENAI_DALLE = "dall-e-3"

GROQ_TRANSCRIPTION = "whisper-large-v3"
GROQ_TTS = "playai-tts"

DEEPSEEK_V4_PRO = "deepseek-v4-pro"

CONFIG_INIT_MODEL_PRESETS: Mapping[str, ModelPreset] = MappingProxyType(
    {
        "anthropic": ModelPreset("anthropic", _ANTHROPIC_SONNET, 1_000_000),
        "bedrock_claude": ModelPreset("bedrock_claude", AWS_BEDROCK_CLAUDE_OPUS, 1_000_000),
        "azure": ModelPreset("azure", AZURE_OPENAI_DEFAULT_DEPLOYMENT),
        "codex": ModelPreset("codex", CODEX_GPT, 258_000),
        "kimi": ModelPreset("kimi", KIMI_K3, 1_048_576),
        "llama_cpp": ModelPreset("llama_cpp", LLAMA_CPP_GEMMA, 128_000),
        "ollama": ModelPreset("ollama", OLLAMA_GEMMA, 128_000),
        "openai": ModelPreset("openai", _OPENAI_GPT, 1_050_000),
        "openrouter": ModelPreset("openrouter", _OPENROUTER_CLAUDE_SONNET, 1_000_000),
        "vertexai_claude": ModelPreset("vertexai_claude", _ANTHROPIC_SONNET, 1_000_000),
    },
)

CONFIG_INIT_MODEL_ALTERNATIVES: Mapping[str, tuple[tuple[str, ModelPreset], ...]] = MappingProxyType(
    {
        "anthropic": (
            ("fable", ModelPreset("anthropic", _ANTHROPIC_FABLE, 1_000_000)),
            ("opus", ModelPreset("anthropic", _ANTHROPIC_OPUS, 1_000_000)),
            ("haiku", ModelPreset("anthropic", _ANTHROPIC_HAIKU, 200_000)),
        ),
        "bedrock_claude": (
            ("fable", ModelPreset("bedrock_claude", _AWS_BEDROCK_CLAUDE_FABLE, 1_000_000)),
            ("sonnet", ModelPreset("bedrock_claude", _AWS_BEDROCK_CLAUDE_SONNET, 1_000_000)),
            ("haiku", ModelPreset("bedrock_claude", _AWS_BEDROCK_CLAUDE_HAIKU, 200_000)),
        ),
        "openai": (
            ("openai_terra", ModelPreset("openai", OPENAI_GPT_TERRA, 1_050_000)),
            ("openai_luna", ModelPreset("openai", OPENAI_GPT_LUNA, 1_050_000)),
        ),
        "openrouter": (
            ("gpt5terra", ModelPreset("openrouter", _OPENROUTER_OPENAI_TERRA, 1_050_000)),
            ("fable", ModelPreset("openrouter", _OPENROUTER_CLAUDE_FABLE, 1_000_000)),
            ("opus", ModelPreset("openrouter", _OPENROUTER_CLAUDE_OPUS, 1_000_000)),
            ("haiku", ModelPreset("openrouter", _OPENROUTER_CLAUDE_HAIKU, 200_000)),
            ("gemini_flash", ModelPreset("openrouter", _OPENROUTER_GEMINI_FLASH, 1_048_576)),
            ("gemini_lite", ModelPreset("openrouter", _OPENROUTER_GEMINI_LITE, 1_048_576)),
            ("deepseek", ModelPreset("openrouter", _OPENROUTER_DEEPSEEK, 1_048_576)),
            ("glm", ModelPreset("openrouter", _OPENROUTER_GLM, 1_048_576)),
            ("kimi", ModelPreset("openrouter", _OPENROUTER_KIMI, 1_048_576)),
            ("tencent_hy3", ModelPreset("openrouter", _OPENROUTER_TENCENT_HY3, 262_144)),
            ("nemotron", ModelPreset("openrouter", _OPENROUTER_NEMOTRON, 262_144)),
        ),
        "vertexai_claude": (
            ("fable", ModelPreset("vertexai_claude", _ANTHROPIC_FABLE, 1_000_000)),
            ("opus", ModelPreset("vertexai_claude", _ANTHROPIC_OPUS, 1_000_000)),
            ("haiku", ModelPreset("vertexai_claude", _ANTHROPIC_HAIKU, 200_000)),
        ),
    },
)

SAAS_MODEL_PRESETS: Mapping[str, ModelPreset] = MappingProxyType(
    {
        "default": ModelPreset("openrouter", _OPENROUTER_GEMINI_FLASH, 1_048_576),
        "gpt5terra": ModelPreset("openrouter", _OPENROUTER_OPENAI_TERRA, 1_050_000),
        "gpt5luna": ModelPreset("openai", OPENAI_GPT_LUNA, 1_050_000),
        "fable": ModelPreset("openrouter", _OPENROUTER_CLAUDE_FABLE, 1_000_000),
        "opus": ModelPreset("openrouter", _OPENROUTER_CLAUDE_OPUS, 1_000_000),
        "sonnet": ModelPreset("openrouter", _OPENROUTER_CLAUDE_SONNET, 1_000_000),
        "haiku": ModelPreset("openrouter", _OPENROUTER_CLAUDE_HAIKU, 200_000),
        "gemini_flash": ModelPreset("openrouter", _OPENROUTER_GEMINI_FLASH, 1_048_576),
        "gemini_lite": ModelPreset("openrouter", _OPENROUTER_GEMINI_LITE, 1_048_576),
        "deepseek": ModelPreset("openrouter", _OPENROUTER_DEEPSEEK, 1_048_576),
        "glm": ModelPreset("openrouter", _OPENROUTER_GLM, 1_048_576),
        "kimi": ModelPreset("openrouter", _OPENROUTER_KIMI, 1_048_576),
        "tencent_hy3": ModelPreset("openrouter", _OPENROUTER_TENCENT_HY3, 262_144),
        "nemotron": ModelPreset("openrouter", _OPENROUTER_NEMOTRON, 262_144),
    },
)

OPENAI_EMBEDDING_DIMENSIONS: Mapping[str, int] = MappingProxyType(
    {
        OPENAI_EMBEDDING_LARGE: 3072,
        OPENAI_EMBEDDING_SMALL: 1536,
    },
)


def llama_cpp_server_command(model_id: str) -> str:
    """Return the llama.cpp OpenAI-compatible server command for a Hugging Face GGUF ref."""
    return f"llama-server -hf {model_id} --host 127.0.0.1 --port 8080"
