"""Tests for routing quality evaluators."""

from __future__ import annotations

import pytest

from abi_evals.routing_eval import (
    check_deterministic_replay,
    check_fallback_correctness,
    evaluate_routing_quality,
    validate_decision_record,
)


def _make_record(**overrides: object) -> dict:
    """Return a minimal valid routing decision record with optional overrides."""
    base = {
        "schema_version": "routing-decision/1.0",
        "task_id": "task-001",
        "selected_model": "gpt-4o",
        "selected_channel": "api",
        "record_hash": "a" * 64,
    }
    base.update(overrides)
    return base


# ---------------------------------------------------------------------------
# validate_decision_record
# ---------------------------------------------------------------------------


class TestValidateDecisionRecord:
    def test_validate_decision_record_valid(self):
        ok, msg = validate_decision_record(_make_record())
        assert ok is True
        assert msg == "ok"

    def test_validate_decision_record_missing_fields(self):
        record = {"schema_version": "routing-decision/1.0"}
        ok, msg = validate_decision_record(record)
        assert ok is False
        assert "missing required fields" in msg


# ---------------------------------------------------------------------------
# check_deterministic_replay
# ---------------------------------------------------------------------------


class TestDeterministicReplay:
    def test_deterministic_replay_stable(self):
        """A pure engine function should produce identical hashes on every call."""
        record = _make_record()

        def engine(task: dict) -> dict:
            return dict(record)

        ok, msg = check_deterministic_replay(engine, {"input": "x"}, n=10)
        assert ok is True
        assert msg == "ok"


# ---------------------------------------------------------------------------
# check_fallback_correctness
# ---------------------------------------------------------------------------


class TestFallbackCorrectness:
    def test_fallback_correctness_with_reason(self):
        record = _make_record(
            fallback_used=True,
            fallback_reason="primary model over capacity",
        )
        ok, msg = check_fallback_correctness(record, expected_primary="gpt-4o")
        assert ok is True
        assert msg == "ok"

    def test_fallback_correctness_missing_reason(self):
        record = _make_record(fallback_used=True)
        ok, msg = check_fallback_correctness(record, expected_primary="gpt-4o")
        assert ok is False
        assert "fallback_reason" in msg


# ---------------------------------------------------------------------------
# evaluate_routing_quality
# ---------------------------------------------------------------------------


class TestEvaluateRoutingQuality:
    def test_evaluate_routing_quality_summary(self):
        records = [
            _make_record(),
            _make_record(),
            {"schema_version": "routing-decision/1.0"},  # missing fields
        ]
        summary = evaluate_routing_quality(records)
        assert summary["total"] == 3
        assert summary["passed"] == 2
        assert summary["failed"] == 1
        assert summary["pass_rate"] == pytest.approx(2 / 3)
        assert len(summary["details"]) == 3
