"""Tests for validate_institutional() top-level API function."""

from __future__ import annotations

import pytest

from claim_validator import validate_institutional
from claim_validator.constants import Severity
from claim_validator.models.institutional import (
    InstitutionalClaimData,
    InstitutionalServiceLine,
)
from claim_validator.models.results import PipelineResult


def _valid_institutional_dict() -> dict:
    """Minimal valid UB-04 institutional claim dict."""
    return {
        "billing_provider_npi": "1234567893",
        "attending_physician_npi": "9876543210",
        "bill_type_code": "111",
        "admission_date": "2026-01-10",
        "discharge_date": "2026-01-15",
        "admission_type_code": "1",
        "admission_source_code": "7",
        "patient_status_code": "01",
        "subscriber_id": "MEM123",
        "payer_id": "60054",
        "service_lines": [
            {"revenue_code": "0120", "rate": 500.00, "units": 5.0},
            {"revenue_code": "0250", "hcpcs_code": "J1234", "rate": 150.00},
        ],
        "total_charge_amount": 2650.00,
    }


class TestValidateInstitutionalValid:
    """Tests for valid institutional claims."""

    def test_valid_claim_dict_passes(self) -> None:
        result = validate_institutional(_valid_institutional_dict())
        assert isinstance(result, PipelineResult)
        assert result.passed is True
        assert result.errors == []

    def test_valid_claim_model_passes(self) -> None:
        claim = InstitutionalClaimData(
            billing_provider_npi="1234567893",
            attending_physician_npi="9876543210",
            bill_type_code="111",
            admission_date="2026-01-10",
            discharge_date="2026-01-15",
            admission_type_code="1",
            admission_source_code="7",
            patient_status_code="01",
            subscriber_id="MEM123",
            payer_id="60054",
            service_lines=[
                InstitutionalServiceLine(
                    revenue_code="0120", rate=500.00, units=5.0,
                ),
            ],
            total_charge_amount=500.00,
        )
        result = validate_institutional(claim)
        assert isinstance(result, PipelineResult)
        assert result.passed is True

    def test_returns_pipeline_result_with_phases(self) -> None:
        result = validate_institutional(_valid_institutional_dict())
        assert len(result.phase_results) == 1
        assert result.phase_results[0].phase == "rule_based"
        assert result.execution_time >= 0

    def test_runs_all_four_institutional_validators(self) -> None:
        result = validate_institutional(_valid_institutional_dict())
        validator_names = [
            vo.validator_name
            for vo in result.phase_results[0].validator_outputs
        ]
        assert "BillTypeValidator" in validator_names
        assert "RevenueCodeValidator" in validator_names
        assert "AdmissionValidator" in validator_names
        assert "InstitutionalCompletenessValidator" in validator_names


class TestValidateInstitutionalInvalid:
    """Tests for invalid institutional claims."""

    def test_invalid_bill_type_flags_error(self) -> None:
        data = _valid_institutional_dict()
        data["bill_type_code"] = "999"
        result = validate_institutional(data)
        assert result.passed is False
        error_codes = [f.code for f in result.errors]
        assert any("BILL_TYPE" in c for c in error_codes)

    def test_missing_bill_type_still_validates(self) -> None:
        """Missing bill_type_code should still run all validators."""
        data = _valid_institutional_dict()
        data["bill_type_code"] = None
        result = validate_institutional(data)
        assert isinstance(result, PipelineResult)

    def test_invalid_type_raises_value_error(self) -> None:
        with pytest.raises(ValueError, match="InstitutionalClaimData"):
            validate_institutional(42)  # type: ignore[arg-type]
