"""SP7 — inbox lanes expose matched_remittance line counts.

For each claim row in the rejected / done_today lanes that has a
matched remittance, the row must include a ``matched_remittance`` block
with ``id``, ``matched_lines``, and ``total_lines``. These power the
``MatchedRemitCard`` badge in T17.

Architecture note: 837 service lines live in ``Claim.raw_json``, so
``total_lines`` is read from the JSON blob.
"""
from datetime import date, datetime, timezone
from decimal import Decimal
import uuid

import pytest
from fastapi.testclient import TestClient

from cyclone import db
from cyclone.api import app
from cyclone.parsers.models_835 import ClaimPayment, ServicePayment
from cyclone.reconcile import run as reconcile_run
from cyclone.store import _persist_835_remit, _remittance_835_row


@pytest.fixture(autouse=True)
def _clear_app_state():
    yield
    if hasattr(app.state, "dismissed_pairs"):
        app.state.dismissed_pairs = set()


@pytest.fixture
def client() -> TestClient:
    return TestClient(app)


def _seed_pair_with_two_lines():
    """One 837 claim (2 service lines) + one 835 remit (1 svc composite
    matching line 1). After reconcile: 1 matched, 1 unmatched_837_only.
    Returns the claim_id (and the remittance_id via matched_remittance).
    """
    bid_837 = str(uuid.uuid4())
    bid_835 = str(uuid.uuid4())
    claim_id = "CLM-INBOX-1"

    svc_lines_json = [
        {
            "line_number": 1,
            "procedure": {"qualifier": "HC", "code": "99213", "modifiers": []},
            "charge": "100.00",
            "unit_type": "UN",
            "units": "1",
            "place_of_service": "11",
            "service_date": "2026-06-01",
            "provider_reference": None,
        },
        {
            "line_number": 2,
            "procedure": {"qualifier": "HC", "code": "99214", "modifiers": []},
            "charge": "100.00",
            "unit_type": "UN",
            "units": "1",
            "place_of_service": "11",
            "service_date": "2026-06-01",
            "provider_reference": None,
        },
    ]

    with db.SessionLocal()() as s:
        # 837 batch + claim
        s.add(db.Batch(
            id=bid_837, kind="837p", input_filename="x.837",
            parsed_at=datetime.now(timezone.utc),
            totals_json={}, validation_json={}, raw_result_json={},
        ))
        s.add(db.Claim(
            id=claim_id,
            patient_control_number="PCN-INBOX",
            charge_amount=Decimal("200.00"),
            provider_npi="1234567890",
            payer_id="SKCO0",
            service_date_from=date(2026, 6, 1),
            service_date_to=date(2026, 6, 1),
            state=db.ClaimState.SUBMITTED,
            batch_id=bid_837,
            raw_json={"service_lines": svc_lines_json},
        ))
        # 835 batch + remit
        s.add(db.Batch(
            id=bid_835, kind="835", input_filename="x.835",
            parsed_at=datetime.now(timezone.utc),
            totals_json={}, validation_json={}, raw_result_json={},
        ))
        cp = ClaimPayment(
            payer_claim_control_number="PCN-INBOX",
            status_code="1",
            total_charge=Decimal("100.00"),
            total_paid=Decimal("80.00"),
            service_payments=[
                ServicePayment(
                    line_number=1, procedure_qualifier="HC",
                    procedure_code="99213",
                    charge=Decimal("100.00"),
                    payment=Decimal("80.00"),
                    units=Decimal("1"),
                    service_date=date(2026, 6, 1),
                ),
            ],
        )
        remit = _remittance_835_row(cp, bid_835)
        s.add(remit)
        s.flush()
        _persist_835_remit(s, cp, remit.id)
        # Force the claim to a terminal state so it lands in done_today.
        # Run reconcile which auto-matches by PCN + sets state to PAID.
        reconcile_run(s, bid_835)
        s.commit()

    return claim_id, bid_837


def test_done_today_lane_includes_matched_remittance_line_counts(client):
    claim_id, bid_837 = _seed_pair_with_two_lines()
    # Backfill state_changed_at so the claim lands in the done_today lane
    # (reconcile.run() doesn't write it; the API surface is exercised by
    # the existing manual-match flow which sets it).
    from sqlalchemy.orm import Session
    with db.SessionLocal()() as s:
        # Migration 0014: composite PK (batch_id, id). Use filter-by-id
        # since we don't have a single canonical batch_id (the test seeds
        # both 837 and 835 batches under fresh UUIDs).
        cl = s.query(db.Claim).filter(db.Claim.id == claim_id).first()
        cl.state_changed_at = datetime.now(timezone.utc)
        s.commit()

    r = client.get("/api/inbox/lanes")
    assert r.status_code == 200
    body = r.json()
    # The seeded claim should be in done_today (auto-reconciled by run()).
    ids = [row["id"] for row in body["done_today"]]
    assert claim_id in ids, f"expected claim in done_today, got ids={ids}"
    row = next(r for r in body["done_today"] if r["id"] == claim_id)
    mr = row.get("matched_remittance")
    assert mr is not None, "expected matched_remittance block on done_today claim row"
    assert "id" in mr
    assert mr["total_lines"] == 2  # two 837 service lines
    assert mr["matched_lines"] == 1  # only line 1 has a matching SVC composite
