"""Tests for benchmark configuration definitions.

Validates: Requirements 16.2, 16.3, 16.5
"""
from __future__ import annotations

import pytest

from services.intelligence_pipeline_v3.benchmark.configurations import (
    BASELINE_CURRENT,
    BASELINE_STRICT_SCHEMA,
    BASELINE_TEMP_ZERO,
    BenchmarkConfig,
    StructuredOutputMode,
    list_configurations,
)


class TestBenchmarkConfig:
    """Tests for BenchmarkConfig model validation."""

    def test_valid_config_creation(self) -> None:
        config = BenchmarkConfig(
            config_name="test",
            description="A test config",
            model_name="test-model",
            temperature=0.5,
            max_output_tokens=1024,
            structured_output_mode=StructuredOutputMode.NONE,
        )
        assert config.config_name == "test"
        assert config.temperature == 0.5
        assert config.seed is None
        assert config.additional_params == {}

    def test_temperature_bounds(self) -> None:
        with pytest.raises(Exception):
            BenchmarkConfig(
                config_name="bad",
                description="bad temp",
                model_name="m",
                temperature=-0.1,
                max_output_tokens=100,
                structured_output_mode=StructuredOutputMode.NONE,
            )

        with pytest.raises(Exception):
            BenchmarkConfig(
                config_name="bad",
                description="bad temp",
                model_name="m",
                temperature=2.1,
                max_output_tokens=100,
                structured_output_mode=StructuredOutputMode.NONE,
            )

    def test_max_output_tokens_must_be_positive(self) -> None:
        with pytest.raises(Exception):
            BenchmarkConfig(
                config_name="bad",
                description="bad tokens",
                model_name="m",
                temperature=0.0,
                max_output_tokens=0,
                structured_output_mode=StructuredOutputMode.NONE,
            )

    def test_config_is_frozen(self) -> None:
        config = BenchmarkConfig(
            config_name="frozen",
            description="immutable",
            model_name="m",
            temperature=0.0,
            max_output_tokens=512,
            structured_output_mode=StructuredOutputMode.NONE,
        )
        with pytest.raises(Exception):
            config.temperature = 1.0  # type: ignore[misc]


class TestStandardConfigurations:
    """Tests for the predefined standard configurations."""

    def test_baseline_current_uses_temperature_07(self) -> None:
        assert BASELINE_CURRENT.temperature == 0.7

    def test_baseline_current_uses_json_object(self) -> None:
        assert BASELINE_CURRENT.structured_output_mode == StructuredOutputMode.JSON_OBJECT

    def test_baseline_current_no_seed(self) -> None:
        assert BASELINE_CURRENT.seed is None

    def test_baseline_temp_zero_is_deterministic(self) -> None:
        assert BASELINE_TEMP_ZERO.temperature == 0.0
        assert BASELINE_TEMP_ZERO.seed == 0

    def test_baseline_temp_zero_same_model(self) -> None:
        assert BASELINE_TEMP_ZERO.model_name == BASELINE_CURRENT.model_name

    def test_baseline_temp_zero_still_json_object(self) -> None:
        assert BASELINE_TEMP_ZERO.structured_output_mode == StructuredOutputMode.JSON_OBJECT

    def test_baseline_strict_schema_uses_json_schema(self) -> None:
        assert BASELINE_STRICT_SCHEMA.structured_output_mode == StructuredOutputMode.JSON_SCHEMA

    def test_baseline_strict_schema_temp_zero(self) -> None:
        assert BASELINE_STRICT_SCHEMA.temperature == 0.0

    def test_baseline_strict_schema_same_model(self) -> None:
        assert BASELINE_STRICT_SCHEMA.model_name == BASELINE_CURRENT.model_name

    def test_all_configs_have_unique_names(self) -> None:
        configs = list_configurations()
        names = [c.config_name for c in configs]
        assert len(names) == len(set(names))

    def test_list_configurations_returns_all_three(self) -> None:
        configs = list_configurations()
        assert len(configs) == 3
        names = {c.config_name for c in configs}
        assert "baseline_current" in names
        assert "baseline_temp_zero" in names
        assert "baseline_strict_schema" in names

    def test_all_configs_use_same_max_output_tokens(self) -> None:
        configs = list_configurations()
        tokens = {c.max_output_tokens for c in configs}
        assert len(tokens) == 1  # All should agree

    def test_all_configs_use_same_model(self) -> None:
        configs = list_configurations()
        models = {c.model_name for c in configs}
        assert len(models) == 1


class TestStructuredOutputMode:
    """Tests for the StructuredOutputMode enum."""

    def test_values(self) -> None:
        assert StructuredOutputMode.NONE.value == "none"
        assert StructuredOutputMode.JSON_OBJECT.value == "json_object"
        assert StructuredOutputMode.JSON_SCHEMA.value == "json_schema"

    def test_enum_members(self) -> None:
        assert len(StructuredOutputMode) == 3
