"""Model utility functions for Lattice.

Pure logic for model-specific configurations and constraints.
All functions are Core layer — no I/O, only @pre/@post + doctests.
"""

from __future__ import annotations

import deal


@deal.pre(lambda model: isinstance(model, str) and len(model) > 0)
@deal.post(lambda result: isinstance(result, bool))
def is_gpt5_model(model: str) -> bool:
    """Check if model requires temperature=1.

    GPT-5 models only support temperature=1. Other values cause:
    litellm.UnsupportedParamsError: gpt-5 models don't support temperature=X.

    Args:
        model: Model identifier (e.g., "openai/gpt-5-mini", "openai/gpt-5").

    Returns:
        True if model is a GPT-5 variant requiring temperature=1.

    >>> is_gpt5_model("openai/gpt-5")
    True
    >>> is_gpt5_model("openai/gpt-5-mini")
    True
    >>> is_gpt5_model("openai/gpt-5-turbo")
    True
    >>> is_gpt5_model("openai/gpt-4")
    False
    >>> is_gpt5_model("gpt-5")
    True
    >>> is_gpt5_model("anthropic/claude-3")
    False
    """
    # Normalize: strip provider prefix if present, then check
    model_name = model.split("/")[-1] if "/" in model else model
    return model_name.startswith("gpt-5")


@deal.pre(lambda model, temperature: isinstance(model, str) and len(model) > 0 and isinstance(temperature, (int, float)))
@deal.post(lambda result: isinstance(result, float))
def normalize_temperature(model: str, temperature: float) -> float:
    """Normalize temperature for models with restrictions.

    GPT-5 models only support temperature=1. This function silently
    adjusts the temperature to avoid API errors.

    Args:
        model: Model identifier.
        temperature: Requested temperature.

    Returns:
        Normalized temperature (1.0 for GPT-5, original otherwise).

    >>> normalize_temperature("openai/gpt-5", 0.7)
    1.0
    >>> normalize_temperature("openai/gpt-5-mini", 0.5)
    1.0
    >>> normalize_temperature("gpt-5", 0.3)
    1.0
    >>> normalize_temperature("openai/gpt-4", 0.7)
    0.7
    >>> normalize_temperature("anthropic/claude-3", 0.5)
    0.5
    """
    if is_gpt5_model(model):
        return 1.0
    return float(temperature)


@deal.pre(lambda model: isinstance(model, str) and len(model) > 0)
@deal.post(lambda result: isinstance(result, str))
def extract_provider(model: str) -> str:
    """Extract provider from litellm model string.

    Litellm models use format: "provider/model" or "provider/org/model".

    Args:
        model: Model identifier (e.g., "openai/gpt-4").

    Returns:
        Provider name (e.g., "openai").

    >>> extract_provider("openai/gpt-4")
    'openai'
    >>> extract_provider("openrouter/google/gemini-3-flash-preview")
    'openrouter'
    >>> extract_provider("ollama/nomic-embed-text")
    'ollama'
    >>> extract_provider("anthropic/claude-3-opus")
    'anthropic'
    """
    return model.split("/")[0]


__all__ = [
    "extract_provider",
    "is_gpt5_model",
    "normalize_temperature",
]
