"""CARC / RARC code lookup tables for 835 CAS segments.

The 835 ERA (Health Care Claim Payment/Advice) transaction carries claim
adjustment information in ``CAS`` segments. Each ``CAS`` row has:

- a **group code** (CAS01): ``CO`` Contractual Obligation, ``PR``
  Patient Responsibility, ``OA`` Other Adjustments, ``PI`` Payer
  Initiated Reductions, ``CR`` Correction and Reversals.
- a **reason code** (CAS02): the **CARC** (Claim Adjustment Reason Code)
  maintained by the X12 / WPC (Washington Publishing Company) committee.
- an amount and optional quantity.

This module is the in-memory lookup that turns those opaque codes into
human-readable labels for the UI. It is **not** the canonical source of
truth — the official list lives at
https://x12.org/codes/claim-adjustment-reason-codes and is updated
quarterly. ``LAST_UPDATED`` below is the snapshot date for the dict
shipped with this build.

Public API (mirrors :func:`cyclone.parsers.models_835.claim_status_label`):

- ``LAST_UPDATED`` — ISO date string (YYYY-MM-DD) of the dict snapshot.
- :func:`reason_label` — given ``(group, reason)`` returns the human
  label, or ``f"Unknown ({group}-{reason})"`` if not in the dict.
- :func:`all_known_codes` — sorted ``[(group, reason, label), ...]``
  for UIs that want to render the full table (e.g. an "all CARC codes"
  reference page).

The dict is keyed ``(group, reason)`` because the same numeric reason
(e.g. ``97``) can appear under multiple groups (``CO-97`` "payment
is included in another service/procedure", ``OA-97`` "benefit
included in payment for another service") with different meanings.
"""

from __future__ import annotations

from typing import Final


# Snapshot date for the bundled dict. Bump this when shipping a refresh.
LAST_UPDATED: Final[str] = "2026-06-20"


# --------------------------------------------------------------------------- #
# CARC labels — keyed (group, reason).
#
# Sources cross-referenced:
#   - X12 / WPC "Claim Adjustment Reason Codes" master list
#   - CMS / Noridian "Medicare CARC/RARC" reference pages (most-used codes)
#   - Colorado Medicaid 835 companion guide (CAS codes we see in practice)
#
# Wording is paraphrased for compactness; the spec requires labels be
# "non-empty human-readable" — exact WPC wording is not asserted. Tests
# pin the *contract* (non-empty, distinct per code) rather than the text.
# --------------------------------------------------------------------------- #


_CARC_LABELS: Final[dict[tuple[str, str], str]] = {
    # -- Contractual Obligation (CO) -------------------------------------
    ("CO", "16"): "Claim/service lacks information for adjudication",
    ("CO", "18"): "Exact duplicate claim/service",
    ("CO", "22"): "This care may be covered by another payer",
    ("CO", "29"): "The time limit for filing has expired",
    ("CO", "45"): "Charge exceeds fee schedule/maximum allowable",
    ("CO", "50"): "Non-covered services — not deemed medical necessity",
    ("CO", "96"): "Non-covered charge(s)",
    ("CO", "97"): "Payment is included in another service/procedure",
    ("CO", "109"): "Claim not covered by this payer/contractor",
    ("CO", "119"): "Benefit maximum for this period has been reached",
    ("CO", "150"): "Payer deems the information submitted does not support this level of service",
    ("CO", "151"): "Payer deems the information submitted does not support this many services",
    ("CO", "167"): "Diagnosis not covered",
    ("CO", "197"): "Precertification/authorization absent",
    ("CO", "204"): "Service/equipment not covered under patient's plan",
    ("CO", "251"): "Credentialing / provider enrollment issue",
    ("CO", "252"): "Service not on formulary",
    ("CO", "253"): "Decision based on DRG / bundled payment methodology",
    ("CO", "254"): "Claim received from ordering/referring provider not enrolled",
    ("CO", "255"): "Claim received from servicing provider not enrolled",
    ("CO", "256"): "Service not payable under provider's contract",
    ("CO", "B7"): "Provider not certified / not eligible to be paid for this service",
    ("CO", "B8"): "Alternative services were available",
    ("CO", "B9"): "Patient enrolled in another plan that covers this service",
    ("CO", "B10"): "Allowed amount has been reduced by a competitive bid",
    ("CO", "B11"): "Claim/service not covered by this payer",
    ("CO", "B12"): "Service not covered under dental benefits",
    ("CO", "B13"): "Service not covered under vision benefits",
    ("CO", "B14"): "Service not covered under pharmacy benefit",
    ("CO", "B15"): "Service requires prior authorization",
    ("CO", "B16"): "New patient qualification not met",
    ("CO", "B20"): "Procedure/service paid under a global fee",
    ("CO", "B22"): "This care is covered by another payer per coordination of benefits",
    ("CO", "B23"): "Non-covered procedure/service — not billable to patient",
    ("CO", "W1"): "Workers' compensation claim adjudicated as non-compensable",
    ("CO", "W2"): "Workers' compensation claim — jurisdictional dispute",
    ("CO", "W3"): "Workers' compensation — covered by federal program",
    # -- Patient Responsibility (PR) -------------------------------------
    ("PR", "1"): "Deductible amount",
    ("PR", "2"): "Coinsurance amount",
    ("PR", "3"): "Co-payment amount",
    ("PR", "16"): "Claim/service lacks information — patient responsibility",
    ("PR", "22"): "Care may be covered by another payer — patient responsibility",
    ("PR", "29"): "Time limit for filing has expired — patient responsibility",
    ("PR", "45"): "Charge exceeds fee schedule — patient responsibility",
    ("PR", "50"): "Non-covered service — patient responsibility",
    ("PR", "96"): "Non-covered charge(s) — patient responsibility",
    ("PR", "97"): "Bundled service — patient responsibility",
    ("PR", "109"): "Not covered by this payer — patient responsibility",
    ("PR", "119"): "Benefit maximum reached — patient responsibility",
    ("PR", "150"): "Level-of-service not supported — patient responsibility",
    ("PR", "151"): "Frequency not supported — patient responsibility",
    ("PR", "204"): "Service not covered under plan — patient responsibility",
    ("PR", "B7"): "Provider not certified — patient responsibility",
    ("PR", "B11"): "Service not covered — patient responsibility",
    ("PR", "B22"): "Covered by another payer per COB — patient responsibility",
    ("PR", "B23"): "Non-covered procedure — billable to patient",
    # -- Other Adjustments (OA) ------------------------------------------
    ("OA", "16"): "Missing/invalid information — other adjustment",
    ("OA", "18"): "Exact duplicate claim/service — other adjustment",
    ("OA", "23"): "Impact of prior payer adjudication",
    ("OA", "29"): "Time limit for filing — other adjustment",
    ("OA", "45"): "Charge exceeds fee schedule — other adjustment",
    ("OA", "50"): "Non-covered service — other adjustment",
    ("OA", "97"): "Payment included in another service — other adjustment",
    ("OA", "109"): "Not covered by this payer — other adjustment",
    ("OA", "119"): "Benefit maximum reached — other adjustment",
    ("OA", "150"): "Level of service not supported — other adjustment",
    ("OA", "151"): "Frequency not supported — other adjustment",
    ("OA", "204"): "Service not covered — other adjustment",
    ("OA", "B7"): "Provider not certified — other adjustment",
    ("OA", "B11"): "Service not covered — other adjustment",
    ("OA", "B22"): "Covered by another payer — other adjustment",
    ("OA", "B23"): "Non-covered procedure — other adjustment",
    # -- Payer Initiated (PI) --------------------------------------------
    ("PI", "16"): "Missing information — payer-initiated reduction",
    ("PI", "21"): "Penalty for late filing",
    ("PI", "22"): "Care covered by another payer — payer-initiated reduction",
    ("PI", "25"): "Payment adjusted based on medical review",
    ("PI", "29"): "Time limit expired — payer-initiated reduction",
    ("PI", "45"): "Charge exceeds fee schedule — payer-initiated reduction",
    ("PI", "50"): "Non-covered service — payer-initiated reduction",
    ("PI", "97"): "Bundled service — payer-initiated reduction",
    ("PI", "109"): "Not covered by this payer — payer-initiated reduction",
    ("PI", "119"): "Benefit maximum — payer-initiated reduction",
    ("PI", "150"): "Level of service not supported — payer-initiated reduction",
    ("PI", "151"): "Frequency not supported — payer-initiated reduction",
    ("PI", "204"): "Service not covered under plan — payer-initiated reduction",
    ("PI", "B7"): "Provider not certified — payer-initiated reduction",
    ("PI", "B11"): "Service not covered — payer-initiated reduction",
    ("PI", "B22"): "Covered by another payer — payer-initiated reduction",
    ("PI", "B23"): "Non-covered procedure — payer-initiated reduction",
    # -- Correction and Reversal (CR) ------------------------------------
    ("CR", "1"): "Deductible amount — correction/reversal",
    ("CR", "2"): "Coinsurance amount — correction/reversal",
    ("CR", "3"): "Co-payment amount — correction/reversal",
    ("CR", "4"): "Procedure code inconsistency — correction/reversal",
    ("CR", "16"): "Missing information — correction/reversal",
    ("CR", "29"): "Time limit expired — correction/reversal",
    ("CR", "45"): "Charge exceeds fee schedule — correction/reversal",
    ("CR", "50"): "Non-covered service — correction/reversal",
    ("CR", "97"): "Bundled service — correction/reversal",
    ("CR", "109"): "Not covered by this payer — correction/reversal",
    ("CR", "119"): "Benefit maximum — correction/reversal",
    ("CR", "150"): "Level of service not supported — correction/reversal",
    ("CR", "151"): "Frequency not supported — correction/reversal",
    ("CR", "204"): "Service not covered — correction/reversal",
    ("CR", "B7"): "Provider not certified — correction/reversal",
    ("CR", "B11"): "Service not covered — correction/reversal",
    ("CR", "B22"): "Covered by another payer — correction/reversal",
    ("CR", "B23"): "Non-covered procedure — correction/reversal",
}


# --------------------------------------------------------------------------- #
# Public API
# --------------------------------------------------------------------------- #


def reason_label(group_code: str, reason_code: str) -> str:
    """Return the human-readable label for a ``(group, reason)`` pair.

    Falls back to ``f"Unknown ({group_code}-{reason_code})"`` when the
    code is not in the bundled dict. The fallback is a stable, parseable
    string so callers can distinguish "we don't know" from "known empty"
    (there are no known-empty labels in the dict).
    """
    return _CARC_LABELS.get(
        (group_code, reason_code),
        f"Unknown ({group_code}-{reason_code})",
    )


def all_known_codes() -> list[tuple[str, str, str]]:
    """Return every known code as a sorted ``[(group, reason, label), ...]``.

    The result is sorted lexicographically by ``(group, reason)`` so UIs
    can render the full table without further work. Pairs are unique by
    construction (the dict cannot have duplicate keys).
    """
    return sorted((g, r, lbl) for (g, r), lbl in _CARC_LABELS.items())


__all__ = [
    "LAST_UPDATED",
    "reason_label",
    "all_known_codes",
]