"""Central model capability policy.

Defines what each model supports (context window, max output tokens,
function calling, structured output, temperature) and provides preflight
validation before API calls.
"""

from __future__ import annotations

from dataclasses import dataclass
from typing import Optional


@dataclass(frozen=True)
class ModelCapability:
    """Capability profile for an OpenAI model."""

    context_window: int
    max_output_tokens: int
    supports_function_calling: bool = True
    supports_structured_output: bool = True
    supports_temperature: bool = True


# Known model capabilities (updated 2026-03)
MODEL_CAPABILITIES: dict[str, ModelCapability] = {
    "gpt-5-nano": ModelCapability(
        context_window=128_000,
        max_output_tokens=16_384,
        supports_temperature=False,  # GPT-5 family ignores temperature
    ),
    "gpt-5-mini": ModelCapability(
        context_window=272_000,
        max_output_tokens=16_384,
        supports_temperature=False,
    ),
    "gpt-5.4-nano": ModelCapability(
        context_window=128_000,
        max_output_tokens=16_384,
        supports_temperature=False,
    ),
    "gpt-5.4-mini": ModelCapability(
        context_window=272_000,
        max_output_tokens=16_384,
        supports_temperature=False,
    ),
    "gpt-4.1": ModelCapability(
        context_window=400_000,
        max_output_tokens=32_768,
        supports_temperature=True,
    ),
}


def get_capability(model: str) -> Optional[ModelCapability]:
    """Return capability profile for a model, or None if unknown."""
    return MODEL_CAPABILITIES.get(model)


def validate_request(
    model: str,
    *,
    max_output_tokens: int | None = None,
    needs_function_calling: bool = False,
    needs_structured_output: bool = False,
    needs_temperature: bool = False,
) -> None:
    """Validate that a model supports the requested features.

    Raises ValueError with actionable message if validation fails.
    Does nothing if the model is unknown (permissive for new models).
    """
    cap = get_capability(model)
    if cap is None:
        return  # Unknown model — allow (permissive policy)

    if max_output_tokens is not None and max_output_tokens > cap.max_output_tokens:
        raise ValueError(
            f"Model {model} max_output_tokens is {cap.max_output_tokens}, "
            f"but {max_output_tokens} was requested."
        )

    if needs_function_calling and not cap.supports_function_calling:
        raise ValueError(
            f"Model {model} does not support function calling."
        )

    if needs_structured_output and not cap.supports_structured_output:
        raise ValueError(
            f"Model {model} does not support structured output."
        )

    if needs_temperature and not cap.supports_temperature:
        raise ValueError(
            f"Model {model} does not support temperature parameter. "
            f"Temperature is ignored by GPT-5 family models."
        )


def should_strip_temperature(model: str) -> bool:
    """Return True if the model ignores temperature (GPT-5 family)."""
    cap = get_capability(model)
    if cap is None:
        return False
    return not cap.supports_temperature
