-- version: 18
-- SP28: per-ACK auto-link join table.
--
-- Closes the operator gap where every inbound 999 / 277CA / TA1 ack was
-- persisted but never durably linked back to the claim it
-- acknowledges. One row per AK2 set-response for 999, per ClaimStatus
-- for 277CA, per TA1 envelope (with claim_id NULL + batch_id set).
--
-- Granularity (per-AK2) is preserved by ``ak2_index`` and the unique
-- index ``ux_claim_acks_dedup`` — an auto-link of
-- (claim, 999, ak2_index=3) is idempotent on re-ingest of the same
-- 999 file (the index enforces this at the DB layer; the helper
-- pre-checks to avoid IntegrityError log noise).
--
-- Notes:
--   * ``claim_id`` is nullable so TA1 envelope-level links to the
--     originating Batch can land here (FK to batches.id). The
--     CHECK constraint makes sure at least one of (claim_id,
--     batch_id) is set on every row — see spec §3.1.
--   * ``set_control_number`` records the value the upstream ACK
--     ACTUALLY CARRIED (== source 837 ST02 for Gainwell batches). It
--     is the orphan-traceability field — the link survives even when
--     the join had to fall back from ST02 to PCN matching.
--   * ``set_accept_reject_code`` carries the AK5 code (A/E/R/X) for
--     999 or the STC category code (A1/A2/A3/A4/A6/A7 etc.) for 277CA.
--     TA1 stores the envelope-level ack code here (A/R/E).
--   * No FK constraint on ``(ack_kind, ack_id)`` — there are three
--     separate ack tables (``acks``, ``ta1_acks``, ``two77ca_acks``).
--     Application code enforces the discriminator.

CREATE TABLE claim_acks (
    id                      INTEGER PRIMARY KEY AUTOINCREMENT,
    claim_id                TEXT REFERENCES claims(id) ON DELETE CASCADE,
    batch_id                TEXT REFERENCES batches(id) ON DELETE CASCADE,
    ack_id                  INTEGER NOT NULL,
    ack_kind                TEXT NOT NULL CHECK (ack_kind IN ('999', '277ca', 'ta1')),
    ak2_index               INTEGER,
    set_control_number      TEXT,
    set_accept_reject_code  TEXT,
    linked_at               DATETIME NOT NULL,
    linked_by               TEXT NOT NULL CHECK (linked_by IN ('auto', 'manual')),
    CHECK ((claim_id IS NOT NULL) OR (batch_id IS NOT NULL))
);

CREATE INDEX ix_claim_acks_claim_id ON claim_acks(claim_id);
CREATE INDEX ix_claim_acks_batch_id ON claim_acks(batch_id);
CREATE INDEX ix_claim_acks_ack ON claim_acks(ack_kind, ack_id);

-- Dedup: an auto-link of (claim, 999, ak2_index=3) is idempotent on re-ingest.
CREATE UNIQUE INDEX ux_claim_acks_dedup
    ON claim_acks(claim_id, ack_kind, ack_id, ak2_index)
    WHERE claim_id IS NOT NULL AND ak2_index IS NOT NULL;
