"""Tests for coalex.evaluate() SDK function."""

from unittest.mock import MagicMock, patch

import pytest
from coalex.config import CoalexConfig
from coalex.evaluate import KNOWN_METRICS, EvaluationDecision, evaluate


class TestEvaluateFunction:
    def test_requires_register(self):
        """Raises RuntimeError when register() hasn't been called."""
        with (
            patch("coalex._config", None),
            patch("coalex._api_key", None),
            pytest.raises(RuntimeError, match="register"),
        ):
            evaluate(
                trace_id="t1",
                input={"q": "test"},
                output={"r": "test"},
                metrics={"r": ["f1"]},
            )

    def test_validates_unknown_metrics(self):
        """Raises ValueError for unknown metric names."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        with pytest.raises(ValueError, match="Unknown metrics"):
            evaluate(
                trace_id="t1",
                input={"q": "test"},
                output={"r": "test"},
                metrics={"r": ["f1", "nonexistent_metric"]},
                _config=cfg,
                _api_key="test-key",
            )

    def test_returns_auto_approved_decision(self):
        """Returns EvaluationDecision with auto_approved status."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "status": "auto_approved",
            "risk_score": 0.05,
            "escalation_id": None,
        }
        mock_response.raise_for_status = MagicMock()

        with patch("coalex.evaluate.httpx.Client") as mock_client_cls:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.post.return_value = mock_response
            mock_client_cls.return_value = mock_client

            result = evaluate(
                trace_id="t1",
                input={"q": "test"},
                output={"r": "test"},
                metrics={"r": ["f1"]},
                _config=cfg,
                _api_key="test-key",
            )

        assert isinstance(result, EvaluationDecision)
        assert result.status == "auto_approved"
        assert result.risk_score == 0.05
        assert result.escalation_id is None

    def test_returns_escalated_decision_with_id(self):
        """Returns EvaluationDecision with escalation_id when escalated."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "status": "escalated",
            "risk_score": 0.70,
            "escalation_id": "esc_abc123",
        }
        mock_response.raise_for_status = MagicMock()

        with patch("coalex.evaluate.httpx.Client") as mock_client_cls:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.post.return_value = mock_response
            mock_client_cls.return_value = mock_client

            result = evaluate(
                trace_id="t1",
                input={"q": "test"},
                output={"r": "test"},
                metrics={"r": ["f1", "word_overlap"]},
                _config=cfg,
                _api_key="test-key",
            )

        assert result.status == "escalated"
        assert result.risk_score == 0.70
        assert result.escalation_id == "esc_abc123"

    def test_payload_does_not_include_expected(self):
        """Verify that the payload sent to the API does not contain 'expected'."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "status": "auto_approved",
            "risk_score": 0.05,
            "escalation_id": None,
        }
        mock_response.raise_for_status = MagicMock()

        with patch("coalex.evaluate.httpx.Client") as mock_client_cls:
            mock_client = MagicMock()
            mock_client.__enter__ = MagicMock(return_value=mock_client)
            mock_client.__exit__ = MagicMock(return_value=False)
            mock_client.post.return_value = mock_response
            mock_client_cls.return_value = mock_client

            evaluate(
                trace_id="t1",
                input={"q": "test"},
                output={"r": "test"},
                metrics={"r": ["f1"]},
                _config=cfg,
                _api_key="test-key",
            )

            # Verify the payload sent to the API
            call_args = mock_client.post.call_args
            payload = call_args.kwargs.get("json") or call_args[1].get("json")
            assert "expected" not in payload

    def test_known_metrics_catalog(self):
        """All documented metric names are in the catalog."""
        expected = {
            "f1",
            "word_overlap",
            "bleu",
            "rouge_l",
            "semantic_similarity",
            "exact_match",
            "levenshtein",
            "contains",
        }
        assert expected == KNOWN_METRICS
