"""SP7 — 835 ingest persists ServiceLinePayment rows + links CAS rows.

Spec §3.1, §3.3, T6.
"""
from datetime import date, datetime, timezone
from decimal import Decimal
import uuid

from sqlalchemy import select

from cyclone.db import (
    Batch,
    CasAdjustment,
    Remittance,
    ServiceLinePayment,
    SessionLocal,
)
from cyclone.parsers.models_835 import (
    ClaimAdjustment,
    ClaimPayment,
    ServicePayment,
)
from cyclone.store import _persist_835_remit, _remittance_835_row


def _make_batch() -> str:
    bid = str(uuid.uuid4())
    with SessionLocal()() as s:
        s.add(Batch(
            id=bid, kind="835", input_filename="x.835",
            parsed_at=datetime.now(timezone.utc),
            totals_json={"total_claims": 1, "total_paid": "0"},
            validation_json={"passed": True, "warnings": [], "errors": []},
            raw_result_json={"_": "stub"},
        ))
        s.commit()
    return bid


def test_persist_835_creates_one_service_line_payment_per_svc_composite():
    bid = _make_batch()
    cp = ClaimPayment(
        payer_claim_control_number="PCN-SLP-1",
        status_code="1",
        total_charge=Decimal("200.00"),
        total_paid=Decimal("150.00"),
        service_payments=[
            ServicePayment(
                line_number=1, procedure_qualifier="HC",
                procedure_code="99213", charge=Decimal("100.00"),
                payment=Decimal("80.00"),
                service_date=date(2026, 6, 1),
                adjustments=[ClaimAdjustment(group_code="CO", reason_code="45", amount=Decimal("20.00"))],
            ),
            ServicePayment(
                line_number=2, procedure_qualifier="HC",
                procedure_code="99214", charge=Decimal("100.00"),
                payment=Decimal("70.00"),
                service_date=date(2026, 6, 1),
                adjustments=[],
            ),
        ],
    )
    with SessionLocal()() as s:
        remit = _remittance_835_row(cp, bid)
        s.add(remit)
        s.flush()
        _persist_835_remit(s, cp, remit.id)
        s.commit()

        slps = list(
            s.execute(
                select(ServiceLinePayment).order_by(ServiceLinePayment.line_number)
            ).scalars().all()
        )
        assert len(slps) == 2
        assert slps[0].procedure_code == "99213"
        assert slps[0].payment == Decimal("80.00")
        assert slps[1].procedure_code == "99214"
        assert slps[1].payment == Decimal("70.00")
        assert slps[0].remittance_id == remit.id


def test_svc_level_cas_adjustments_link_to_service_line_payment():
    """CAS rows that follow an SVC composite must point at the SLP."""
    bid = _make_batch()
    cp = ClaimPayment(
        payer_claim_control_number="PCN-SLP-2",
        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"),
                adjustments=[ClaimAdjustment(group_code="CO", reason_code="45", amount=Decimal("20.00"))],
            ),
        ],
    )
    with SessionLocal()() as s:
        remit = _remittance_835_row(cp, bid)
        s.add(remit)
        s.flush()
        _persist_835_remit(s, cp, remit.id)
        s.commit()

        cas = list(s.execute(select(CasAdjustment)).scalars().all())
        assert len(cas) == 1
        assert cas[0].service_line_payment_id is not None

        slp = s.execute(
            select(ServiceLinePayment).where(
                ServiceLinePayment.id == cas[0].service_line_payment_id
            )
        ).scalar_one()
        assert slp.procedure_code == "99213"


def test_modifiers_persisted_as_json_array():
    bid = _make_batch()
    cp = ClaimPayment(
        payer_claim_control_number="PCN-SLP-3",
        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", modifiers=["25", "59"],
                charge=Decimal("100.00"), payment=Decimal("80.00"),
                adjustments=[],
            ),
        ],
    )
    with SessionLocal()() as s:
        remit = _remittance_835_row(cp, bid)
        s.add(remit)
        s.flush()
        _persist_835_remit(s, cp, remit.id)
        s.commit()

        slp = s.execute(select(ServiceLinePayment)).scalar_one()
        import json as _json
        assert _json.loads(slp.modifiers_json) == ["25", "59"]


def test_empty_service_payments_is_noop():
    """A 835 with no SVC composites produces no ServiceLinePayment rows."""
    bid = _make_batch()
    cp = ClaimPayment(
        payer_claim_control_number="PCN-SLP-4",
        status_code="1",
        total_charge=Decimal("0.00"),
        total_paid=Decimal("0.00"),
        service_payments=[],
    )
    with SessionLocal()() as s:
        remit = _remittance_835_row(cp, bid)
        s.add(remit)
        s.flush()
        _persist_835_remit(s, cp, remit.id)
        s.commit()

        slps = list(s.execute(select(ServiceLinePayment)).scalars().all())
        assert slps == []
        cas = list(s.execute(select(CasAdjustment)).scalars().all())
        assert cas == []
