"""Tests for PlaceOfServiceValidator."""

from __future__ import annotations

from claim_validator.constants import Severity
from claim_validator.models.results import ValidatorOutput
from claim_validator.validators.rule_based.place_of_service import PlaceOfServiceValidator

from tests.conftest import build_claim_unchecked


def _base_claim(**overrides) -> dict:
    """Minimal claim dict for POS testing."""
    data: dict = {
        "billing_provider_npi": "1234567893",
        "subscriber_id": "XYZ123456",
        "diagnosis_codes": [{"code": "J06.9", "pointer": 1}],
        "lines": [
            {
                "procedure_code": "99213",
                "diagnosis_pointers": [1],
                "charge_amount": 150.00,
            },
        ],
    }
    data.update(overrides)
    return data


class TestPlaceOfServiceClaimLevel:
    """Claim-level POS validation."""

    def setup_method(self) -> None:
        self.validator = PlaceOfServiceValidator()

    def test_valid_pos_no_findings(self) -> None:
        claim = build_claim_unchecked(**_base_claim(place_of_service="11"))
        result = self.validator.validate(claim)
        assert isinstance(result, ValidatorOutput)
        assert result.findings == []

    def test_invalid_pos_produces_finding(self) -> None:
        claim = build_claim_unchecked(**_base_claim(place_of_service="ZZ"))
        result = self.validator.validate(claim)
        findings = [f for f in result.findings if f.code == "INVALID_PLACE_OF_SERVICE"]
        assert len(findings) == 1
        assert findings[0].severity == Severity.ERROR
        assert findings[0].field_name == "place_of_service"
        assert findings[0].line_number is None

    def test_none_pos_skipped(self) -> None:
        claim = build_claim_unchecked(**_base_claim(place_of_service=None))
        result = self.validator.validate(claim)
        assert result.findings == []

    def test_empty_pos_skipped(self) -> None:
        claim = build_claim_unchecked(**_base_claim(place_of_service=""))
        result = self.validator.validate(claim)
        assert result.findings == []

    def test_whitespace_pos_skipped(self) -> None:
        claim = build_claim_unchecked(**_base_claim(place_of_service="  "))
        result = self.validator.validate(claim)
        assert result.findings == []


class TestPlaceOfServiceLineLevel:
    """Line-level POS validation."""

    def setup_method(self) -> None:
        self.validator = PlaceOfServiceValidator()

    def test_valid_line_pos_no_findings(self) -> None:
        data = _base_claim()
        data["lines"] = [
            {
                "procedure_code": "99213",
                "diagnosis_pointers": [1],
                "charge_amount": 150.00,
                "place_of_service": "11",
            },
        ]
        claim = build_claim_unchecked(**data)
        result = self.validator.validate(claim)
        assert result.findings == []

    def test_invalid_line_pos_produces_finding(self) -> None:
        data = _base_claim()
        data["lines"] = [
            {
                "procedure_code": "99213",
                "diagnosis_pointers": [1],
                "charge_amount": 150.00,
                "place_of_service": "ZZ",
            },
        ]
        claim = build_claim_unchecked(**data)
        result = self.validator.validate(claim)
        findings = [f for f in result.findings if f.code == "INVALID_PLACE_OF_SERVICE"]
        assert len(findings) == 1
        assert findings[0].line_number == 1
        assert findings[0].severity == Severity.ERROR

    def test_none_line_pos_skipped(self) -> None:
        data = _base_claim()
        data["lines"] = [
            {
                "procedure_code": "99213",
                "diagnosis_pointers": [1],
                "charge_amount": 150.00,
                "place_of_service": None,
            },
        ]
        claim = build_claim_unchecked(**data)
        result = self.validator.validate(claim)
        assert result.findings == []

    def test_multiple_lines_second_invalid(self) -> None:
        data = _base_claim()
        data["lines"] = [
            {
                "procedure_code": "99213",
                "diagnosis_pointers": [1],
                "charge_amount": 150.00,
                "place_of_service": "11",
            },
            {
                "procedure_code": "99214",
                "diagnosis_pointers": [1],
                "charge_amount": 200.00,
                "place_of_service": "XX",
            },
        ]
        claim = build_claim_unchecked(**data)
        result = self.validator.validate(claim)
        findings = [f for f in result.findings if f.code == "INVALID_PLACE_OF_SERVICE"]
        assert len(findings) == 1
        assert findings[0].line_number == 2
