"""Write a :class:`ParseResult835` to disk as one JSON file per claim + summary.json.

Parallel to :mod:`cyclone.parsers.writer` for the 837P parser. Kept
separate because the 835 writer is not just a duck-typed copy of the
837P one — the ``payout`` payload includes the BPR/TRN/1000A/1000B
headers alongside each claim file (so the UI can render the full ERA
context per claim), and we want to be free to evolve the layout
independently.
"""

from __future__ import annotations

import json
import re
from pathlib import Path

from cyclone.parsers.models_835 import ParseResult835

_UNSAFE = re.compile(r"[^A-Za-z0-9._-]")


def _sanitize(s: str) -> str:
    return _UNSAFE.sub("-", s).strip("-") or "claim"


def _filename(control_number: str, transaction_date_iso: str, claim_id: str, used: set[str]) -> str:
    base = f"payout-{_sanitize(control_number)}-{_sanitize(transaction_date_iso.replace('-', ''))}-{_sanitize(claim_id)}.json"
    if base not in used:
        return base
    stem = base[:-5]
    n = 2
    while True:
        cand = f"{stem}-{n}.json"
        if cand not in used:
            return cand
        n += 1


def write_outputs_835(result: ParseResult835, output_dir: Path) -> list[Path]:
    """Write one JSON file per claim payment + a ``summary.json``.

    Each claim file is enriched with the batch-level envelope/financial/
    trace/payer/payee so the UI can render the full ERA context without
    cross-referencing the summary. The ``summary.json`` is the canonical
    counts file.
    """
    output_dir = Path(output_dir)
    output_dir.mkdir(parents=True, exist_ok=True)

    txn_date = result.envelope.transaction_date.isoformat() if result.envelope else "unknown"
    control = result.envelope.control_number if result.envelope else "unknown"

    used: set[str] = set()
    paths: list[Path] = []
    # Pre-serialize the batch-level fields so each claim file embeds them.
    envelope_obj = json.loads(result.envelope.model_dump_json())
    financial_obj = json.loads(result.financial_info.model_dump_json())
    trace_obj = json.loads(result.trace.model_dump_json())
    payer_obj = json.loads(result.payer.model_dump_json())
    payee_obj = json.loads(result.payee.model_dump_json())

    for claim in result.claims:
        name = _filename(control, txn_date, claim.payer_claim_control_number, used)
        used.add(name)
        path = output_dir / name
        claim_obj = json.loads(claim.model_dump_json())
        payload = {
            "envelope": envelope_obj,
            "financial_info": financial_obj,
            "trace": trace_obj,
            "payer": payer_obj,
            "payee": payee_obj,
            "claim": claim_obj,
        }
        path.write_text(json.dumps(payload, indent=2))
        paths.append(path)

    summary_path = output_dir / "summary.json"
    summary_path.write_text(result.summary.model_dump_json(indent=2))
    return paths
