from __future__ import annotations

"""SDK decisions resource tests — mocked HTTP."""

import os
import sys

import pytest

sys.path.insert(0, os.path.join(os.path.dirname(__file__), ".."))

import httpx
from nexure import AuthenticationError, DecisionList, DecisionRecord, ForensicReport, Nexure
from pytest_httpx import HTTPXMock

MOCK_DECISION = {
    "id": "dec_abc123def456",
    "decision_type": "credit_underwriting",
    "sequence_number": 1,
    "hash": "a" * 64,
    "previous_hash": "0" * 64,
    "package_id": "pkg_abc123def456",
    "brief_id": None,
    "action": "approve",
    "conditions": None,
    "reasoning": None,
    "decided_by": "reviewer_schen",
    "decided_at": "2025-01-15T10:30:00Z",
    "overrode_model": False,
    "overrode_brief": False,
    "override_reason": None,
    "evidence_snapshot": {"fico_score": 711},
    "trust_score": None,
    "classification": None,
    "tenant_id": "tenant_dev",
    "created_at": "2025-01-15T10:30:00Z",
}

MOCK_PACKAGE = {
    "id": "pkg_abc123def456",
    "decision_type": "credit_underwriting",
    "subject": None,
    "evidence": {"fico_score": 711},
    "policy_context": None,
    "model_output": None,
    "source_system": None,
    "source_agent": None,
    "metadata": None,
    "tenant_id": "tenant_dev",
    "created_at": "2025-01-15T10:30:00Z",
}


class TestDecisionsRecord:
    """nx.decisions.record()"""

    def test_record_returns_decision_record(self, httpx_mock: HTTPXMock):
        """record() should return a DecisionRecord model."""
        httpx_mock.add_response(
            method="POST",
            url="http://test:8000/v1/decisions",
            json=MOCK_DECISION,
            status_code=201,
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.record(
            decision_type="credit_underwriting",
            evidence={"fico_score": 711},
            action="approve",
            decided_by="reviewer_schen",
        )
        nx.close()

        assert isinstance(result, DecisionRecord)
        assert result.id == "dec_abc123def456"
        assert result.action == "approve"
        assert result.sequence_number == 1

    def test_auth_error_raises(self, httpx_mock: HTTPXMock):
        """401 response should raise AuthenticationError."""
        httpx_mock.add_response(
            method="POST",
            url="http://test:8000/v1/decisions",
            json={"error": {"type": "authentication_error", "message": "Invalid API key"}},
            status_code=401,
        )

        nx = Nexure(api_key="bad_key", base_url="http://test:8000/v1")
        with pytest.raises(AuthenticationError, match="Invalid API key"):
            nx.decisions.record(
                decision_type="test",
                evidence={"x": 1},
                action="approve",
                decided_by="tester",
            )
        nx.close()


class TestDecisionsGet:
    """nx.decisions.get()"""

    def test_get_returns_decision(self, httpx_mock: HTTPXMock):
        httpx_mock.add_response(
            method="GET",
            url="http://test:8000/v1/decisions/dec_abc123def456",
            json=MOCK_DECISION,
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.get("dec_abc123def456")
        nx.close()

        assert isinstance(result, DecisionRecord)
        assert result.id == "dec_abc123def456"


class TestDecisionsList:
    """nx.decisions.list()"""

    def test_list_returns_decision_list(self, httpx_mock: HTTPXMock):
        httpx_mock.add_response(
            method="GET",
            url=httpx.URL(
                "http://test:8000/v1/decisions",
                params={"limit": "50", "offset": "0"},
            ),
            json={
                "decisions": [MOCK_DECISION],
                "total": 1,
                "page": 1,
                "page_size": 50,
                "has_more": False,
                "limit": 50,
                "offset": 0,
            },
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.list()
        nx.close()

        assert isinstance(result, DecisionList)
        assert result.total == 1
        assert len(result.decisions) == 1
        assert result.decisions[0].id == "dec_abc123def456"

    def test_list_with_filters(self, httpx_mock: HTTPXMock):
        """list() passes date and override filters correctly."""
        httpx_mock.add_response(
            method="GET",
            url=httpx.URL(
                "http://test:8000/v1/decisions",
                params={
                    "limit": "10",
                    "offset": "5",
                    "action": "deny",
                    "overrode_model": "true",
                    "start_date": "2025-01-01",
                    "end_date": "2025-12-31",
                },
            ),
            json={
                "decisions": [],
                "total": 0,
                "page": 1,
                "page_size": 10,
                "has_more": False,
                "limit": 10,
                "offset": 5,
            },
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.list(
            limit=10,
            offset=5,
            action="deny",
            overrides_only=True,
            start_date="2025-01-01",
            end_date="2025-12-31",
        )
        nx.close()

        assert isinstance(result, DecisionList)
        assert result.total == 0


class TestDecisionsRecordLinking:
    """nx.decisions.record() with package_id and brief_id."""

    def test_record_with_package_id(self, httpx_mock: HTTPXMock):
        """record(package_id=...) sends package_id in payload."""
        linked = {**MOCK_DECISION, "package_id": "pkg_existing123"}
        httpx_mock.add_response(
            method="POST",
            url="http://test:8000/v1/decisions",
            json=linked,
            status_code=201,
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.record(
            decision_type="credit_underwriting",
            evidence={"fico_score": 711},
            action="approve",
            decided_by="reviewer_schen",
            package_id="pkg_existing123",
        )
        nx.close()

        assert isinstance(result, DecisionRecord)
        assert result.package_id == "pkg_existing123"

    def test_record_with_brief_id(self, httpx_mock: HTTPXMock):
        """record(brief_id=...) sends brief_id in payload."""
        linked = {**MOCK_DECISION, "brief_id": "brf_existing456"}
        httpx_mock.add_response(
            method="POST",
            url="http://test:8000/v1/decisions",
            json=linked,
            status_code=201,
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.record(
            decision_type="credit_underwriting",
            evidence={"fico_score": 711},
            action="approve",
            decided_by="reviewer_schen",
            brief_id="brf_existing456",
        )
        nx.close()

        assert isinstance(result, DecisionRecord)
        assert result.brief_id == "brf_existing456"


class TestDecisionsForensics:
    """nx.decisions.forensics()"""

    def test_forensics_returns_full_report(self, httpx_mock: HTTPXMock):
        httpx_mock.add_response(
            method="GET",
            url="http://test:8000/v1/decisions/dec_abc123def456/forensics",
            json={
                "record": MOCK_DECISION,
                "package": MOCK_PACKAGE,
                "brief": None,
                "chain_verified": True,
                "chain_position": 1,
                "chain_length": 10,
            },
        )

        nx = Nexure(api_key="test_key", base_url="http://test:8000/v1")
        result = nx.decisions.forensics("dec_abc123def456")
        nx.close()

        assert isinstance(result, ForensicReport)
        assert result.chain_verified is True
        assert result.chain_position == 1
        assert result.chain_length == 10
        assert result.record.id == "dec_abc123def456"
        assert result.package.id == "pkg_abc123def456"
        assert result.brief is None
