"""Tests for coalex.resolve() SDK function (COA-149)."""

from unittest.mock import MagicMock, patch

import pytest
from coalex.config import CoalexConfig
from coalex.resolve import VALID_DECISIONS, ResolutionResult, resolve


class TestResolveFunction:
    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"),
        ):
            resolve(escalation_id="esc_123", decision="approved")

    def test_validates_decision(self):
        """Raises ValueError for invalid decision values."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        with pytest.raises(ValueError, match="decision must be one of"):
            resolve(
                escalation_id="esc_123",
                decision="invalid",
                _config=cfg,
                _api_key="test-key",
            )

    def test_requires_corrections_for_corrected(self):
        """Raises ValueError when decision='corrected' without corrections."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        with pytest.raises(ValueError, match="corrections required"):
            resolve(
                escalation_id="esc_123",
                decision="corrected",
                _config=cfg,
                _api_key="test-key",
            )

    def test_returns_resolution_result(self):
        """Returns ResolutionResult with metrics on success."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "escalation_id": "esc_123",
            "status": "approved",
            "metrics": [
                {"field": "response", "metrics": {"f1": 0.91, "word_overlap": 0.85}},
            ],
            "resolved_at": "2026-03-05T10:00:00+00:00",
            "resolved_by": None,
        }
        mock_response.raise_for_status = MagicMock()

        with patch("coalex.resolve.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 = resolve(
                escalation_id="esc_123",
                decision="approved",
                _config=cfg,
                _api_key="test-key",
            )

        assert isinstance(result, ResolutionResult)
        assert result.escalation_id == "esc_123"
        assert result.status == "approved"
        assert len(result.metrics) == 1
        assert result.metrics[0].field == "response"
        assert result.metrics[0].metrics["f1"] == 0.91

    def test_posts_correct_payload(self):
        """Verifies the HTTP request payload structure."""
        cfg = CoalexConfig(endpoint="http://localhost:8080")
        mock_response = MagicMock()
        mock_response.json.return_value = {
            "escalation_id": "esc_123",
            "status": "corrected",
            "metrics": [],
            "resolved_at": "2026-03-05T10:00:00+00:00",
            "resolved_by": "jane@acme.com",
        }
        mock_response.raise_for_status = MagicMock()

        with patch("coalex.resolve.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

            resolve(
                escalation_id="esc_123",
                decision="corrected",
                corrections={"response": "corrected output"},
                reviewer="jane@acme.com",
                reason="Minor fix",
                _config=cfg,
                _api_key="test-key",
            )

            mock_client.post.assert_called_once()
            call_args = mock_client.post.call_args
            assert call_args[0][0] == "http://localhost:8080/api/v1/escalations/esc_123/resolve"
            payload = call_args[1]["json"]
            assert payload["decision"] == "corrected"
            assert payload["corrections"] == {"response": "corrected output"}
            assert payload["reviewer"] == "jane@acme.com"
            assert payload["reason"] == "Minor fix"
            assert call_args[1]["headers"]["Authorization"] == "Bearer test-key"

    def test_valid_decisions_catalog(self):
        """All valid decision values are in the catalog."""
        assert {"approved", "rejected", "corrected"} == VALID_DECISIONS

    def test_result_is_frozen(self):
        """ResolutionResult is immutable."""
        result = ResolutionResult(
            escalation_id="esc_123",
            status="approved",
            metrics=[],
            resolved_at="2026-03-05T10:00:00+00:00",
        )
        with pytest.raises(AttributeError):
            result.status = "rejected"  # type: ignore[misc]
