"""Tests that ``CycloneStore.iter_claims`` populates ``receivedAmount``
from the matched ``Remittance.total_paid``.

Before SP_Auth follow-up: every claim came back with
``receivedAmount: 0.0`` regardless of whether it had been paired with
a paid remittance, so the Dashboard's "Received" KPI was always $0
even when claims had been paid and reconciled.

The fix: ``iter_claims`` bulk-loads ``Remittance.total_paid`` for every
matched claim id in the result set (single SQL, no N+1) and stamps
the sum onto each claim dict.
"""

from __future__ import annotations

import json
from datetime import date, datetime, timezone
from decimal import Decimal

import pytest

from cyclone import db
from cyclone.db import ActivityEvent, Batch, Claim, ClaimState, Remittance
from cyclone.store import store as global_store


@pytest.fixture(autouse=True)
def _setup(tmp_path, monkeypatch):
    monkeypatch.setenv("CYCLONE_DB_URL", f"sqlite:///{tmp_path}/test.db")
    db._reset_for_tests()
    db.init_db()


def _make_batch(s, batch_id: str) -> None:
    s.add(Batch(
        id=batch_id,
        kind="837p",
        input_filename="seed.edi",
        parsed_at=datetime(2026, 6, 19, 12, 0, tzinfo=timezone.utc),
        totals_json={"total_claims": 3},
        validation_json={"passed": True, "warnings": [], "errors": []},
        raw_result_json={"_": "stub"},
    ))


def _make_claim(s, claim_id: str, batch_id: str, *, matched_remit_id: str | None = None) -> None:
    s.add(Claim(
        id=claim_id,
        batch_id=batch_id,
        patient_control_number=claim_id,
        service_date_from=date(2026, 6, 1),
        service_date_to=date(2026, 6, 1),
        charge_amount=Decimal("200.00"),
        provider_npi="1234567890",
        payer_id="SKCO0",
        state=ClaimState.PAID,
        matched_remittance_id=matched_remit_id,
    ))


def _make_remit(s, remit_id: str, batch_id: str, *, total_paid: Decimal) -> None:
    s.add(Remittance(
        id=remit_id,
        batch_id=batch_id,
        payer_claim_control_number=remit_id,
        claim_id=None,
        status_code="1",
        total_charge=Decimal("200.00"),
        total_paid=total_paid,
        adjustment_amount=Decimal("0"),
        received_at=datetime(2026, 6, 20, 12, 0, tzinfo=timezone.utc),
    ))


def test_iter_claims_populates_received_amount_from_matched_remittance():
    """A matched claim should reflect its remittance's ``total_paid``."""
    with db.SessionLocal()() as s:
        _make_batch(s, "b1")
        _make_remit(s, "r1", "b1", total_paid=Decimal("180.00"))
        _make_claim(s, "CLM-A", "b1", matched_remit_id="r1")
        s.commit()

    items = global_store.iter_claims(limit=10)
    by_id = {c["id"]: c for c in items}
    assert by_id["CLM-A"]["receivedAmount"] == pytest.approx(180.00)


def test_iter_claims_unmatched_claim_has_zero_received():
    """Claims with no matched remittance still get 0.0, not stale data."""
    with db.SessionLocal()() as s:
        _make_batch(s, "b1")
        _make_claim(s, "CLM-U", "b1", matched_remit_id=None)
        s.commit()

    items = global_store.iter_claims(limit=10)
    by_id = {c["id"]: c for c in items}
    assert by_id["CLM-U"]["receivedAmount"] == 0.0


def test_iter_claims_handles_orphan_match_fk():
    """A claim with a stale ``matched_remittance_id`` whose remittance row
    was deleted should default to 0.0 rather than blow up."""
    with db.SessionLocal()() as s:
        _make_batch(s, "b1")
        _make_claim(s, "CLM-ORPHAN", "b1", matched_remit_id="r-deleted")
        s.commit()

    # No remittance row exists — the FK is dangling, which can happen
    # if the remittance was deleted between match and now.
    items = global_store.iter_claims(limit=10)
    by_id = {c["id"]: c for c in items}
    assert by_id["CLM-ORPHAN"]["receivedAmount"] == 0.0


def test_iter_claims_bulk_loads_multiple_matches_in_one_pass():
    """All matched claims in a page reflect their distinct remittance
    totals — the bulk load must aggregate per remittance id."""
    with db.SessionLocal()() as s:
        _make_batch(s, "b1")
        _make_remit(s, "r1", "b1", total_paid=Decimal("120.00"))
        _make_remit(s, "r2", "b1", total_paid=Decimal("175.50"))
        _make_remit(s, "r3", "b1", total_paid=Decimal("0"))
        _make_claim(s, "CLM-1", "b1", matched_remit_id="r1")
        _make_claim(s, "CLM-2", "b1", matched_remit_id="r2")
        _make_claim(s, "CLM-3", "b1", matched_remit_id="r3")
        _make_claim(s, "CLM-4", "b1", matched_remit_id=None)
        s.commit()

    items = global_store.iter_claims(limit=10)
    by_id = {c["id"]: c for c in items}
    assert by_id["CLM-1"]["receivedAmount"] == pytest.approx(120.00)
    assert by_id["CLM-2"]["receivedAmount"] == pytest.approx(175.50)
    assert by_id["CLM-3"]["receivedAmount"] == pytest.approx(0.0)
    assert by_id["CLM-4"]["receivedAmount"] == 0.0