"""Tests for the 271 (Eligibility Benefit Response) parser.

SP3 Phase 4 (T21): single-pass segment walker that pulls the
information source / receiver / subscriber / patient / EB coverage
benefits out of a tokenized 271. The fixture
(``tests/fixtures/minimal_271.txt``) has two EB segments with
descriptions — one Medical Care, one Pharmacy — so we can assert
both the count and the per-benefit resolution of service-type codes.
"""
from __future__ import annotations

from pathlib import Path

import pytest

from cyclone.parsers.parse_271 import parse

FIXTURE = Path(__file__).parent / "fixtures" / "minimal_271.txt"


def test_parse_minimal_271_returns_two_benefits():
    """The fixture's two EB segments become two CoverageBenefit rows."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    assert len(result.coverage_benefits) == 2
    # First EB: medical care (code "1"). Second: pharmacy (code "88").
    assert result.coverage_benefits[0].service_type_code == "1"
    assert result.coverage_benefits[1].service_type_code == "88"


def test_parse_271_resolves_service_type_description():
    """``service_type_description`` is auto-populated from the EB01 code."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    assert result.coverage_benefits[0].service_type_description == "Medical Care"
    assert result.coverage_benefits[1].service_type_description == "Pharmacy"


def test_parse_271_in_plan_network_flag():
    """The first EB has Y for in-plan, the second has N."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    assert result.coverage_benefits[0].in_plan_network is True
    assert result.coverage_benefits[1].in_plan_network is False


def test_parse_271_envelope_built():
    """Envelope has the ISA/GS/ST fields. ST03 = implementation guide."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    env = result.envelope
    assert env.sender_id.strip() == "PAYERID"
    assert env.receiver_id.strip() == "PROVIDERID"
    assert env.control_number == "000000002"
    assert env.implementation_guide == "005010X279A1"
    # GS04 supplies the transaction date.
    assert env.transaction_date.year == 2024
    assert env.transaction_date.month == 1
    assert env.transaction_date.day == 1


def test_parse_271_msg_folded_into_additional_info():
    """MSG segments become ``BenefitAdditionalInfo`` rows on the EB."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    cb0 = result.coverage_benefits[0]
    assert len(cb0.additional_info) == 1
    assert cb0.additional_info[0].description == "Patient has active coverage"
    cb1 = result.coverage_benefits[1]
    assert len(cb1.additional_info) == 1
    assert cb1.additional_info[0].description == "Pharmacy copay $20"


def test_parse_271_subscriber_extracted():
    """Subscriber first/last name + member id come from NM1*IL."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    assert result.subscriber.first_name == "JOHN"
    assert result.subscriber.last_name == "DOE"
    assert result.subscriber.member_id == "MEMBER123"


def test_parse_271_invalid_edi_raises():
    """Garbage input must raise :class:`CycloneParseError`."""
    from cyclone.parsers.exceptions import CycloneParseError

    with pytest.raises(CycloneParseError):
        parse("not edi at all", input_file="garbage.txt")


def test_parse_271_summary_counts_eb_segments():
    """The summary reports the number of EB segments we parsed."""
    text = FIXTURE.read_text()
    result = parse(text, input_file="minimal_271.txt")
    assert result.summary.total_claims == 2
    assert result.summary.passed == 2
    assert result.summary.failed == 0
    assert result.summary.input_file == "minimal_271.txt"
