-- t-paliad-190 / Fristen Phase 3 Slice 10 — staging table for the
-- fuzzy-match orphans produced by mig 090. Per design §3.I + m's Q10
-- ruling: legacy paliad.deadlines rows whose title can't be uniquely
-- bound to a deadline_rule via fuzzy matching are NOT silently left
-- NULL — they're logged here so a legal-review pass can hand-link
-- the ambiguous tail.
--
-- Mig 089 ships the table; mig 090 does the actual backfill +
-- populates this table. Numbering reflects the dependency order
-- (the backfill SELECTs into this table, so the table must exist
-- first).
--
-- Schema notes:
--   - deadline_id is the FK to paliad.deadlines.id with ON DELETE
--     CASCADE so a hand-deletion of an orphan deadline cleans up
--     its staging row too. (Deadlines are normally archived, not
--     deleted; the cascade is defensive.)
--   - project_id stays denormalised so the admin orphan-review UI
--     can group orphans by project without re-joining deadlines.
--   - reason is a free-text discriminator: 'no_match' | 'ambiguous'
--     today; the editor in Slice 11 may add 'manual_unbound' or
--     similar in the future.
--   - resolved_at + resolved_rule_id are NULL on insert; the admin
--     orphan-review UI sets them when an editor hand-links the row,
--     so the table doubles as an audit trail of the legal-review
--     pass. The matching paliad.deadlines.rule_id is updated at the
--     same time (the UPDATE on deadlines fires its own audit row
--     once an audit trigger lives on that table; today no trigger,
--     so the staging row is the audit artefact).
--
-- RLS: admin-only read. The orphan list contains real deadline titles
-- + project ids, so non-admins should not see it. The Slice 11 rule
-- editor surface gates this further.

CREATE TABLE IF NOT EXISTS paliad.deadline_rule_backfill_orphans (
    id                uuid          PRIMARY KEY DEFAULT gen_random_uuid(),
    deadline_id       uuid          NOT NULL
                        REFERENCES paliad.deadlines(id) ON DELETE CASCADE,
    title             text          NOT NULL,
    project_id        uuid,
    proceeding_code   text,
    reason            text          NOT NULL
                        CHECK (reason IN ('no_match', 'ambiguous', 'no_project', 'manual_unbound')),
    candidate_count   int           NOT NULL DEFAULT 0,
    candidate_rule_ids uuid[]       NOT NULL DEFAULT '{}',
    resolved_at       timestamptz,
    resolved_rule_id  uuid
                        REFERENCES paliad.deadline_rules(id) ON DELETE SET NULL,
    created_at        timestamptz   NOT NULL DEFAULT now()
);

CREATE INDEX IF NOT EXISTS deadline_rule_backfill_orphans_deadline_id_idx
    ON paliad.deadline_rule_backfill_orphans (deadline_id);

CREATE INDEX IF NOT EXISTS deadline_rule_backfill_orphans_unresolved_idx
    ON paliad.deadline_rule_backfill_orphans (created_at DESC)
    WHERE resolved_at IS NULL;

COMMENT ON TABLE paliad.deadline_rule_backfill_orphans IS
    'Slice 10 (mig 089/090, t-paliad-190): staging for legacy '
    'paliad.deadlines rows that the fuzzy-match backfill could not '
    'uniquely bind to a deadline_rule. Each row holds the deadline '
    'context + the candidate rule IDs the matcher found (0 → '
    '''no_match''; ≥2 → ''ambiguous'') so a legal-review pass can '
    'hand-link without rerunning the match. resolved_at + '
    'resolved_rule_id flip when the admin orphan-review UI binds the '
    'row.';

-- RLS: admin-only read.
ALTER TABLE paliad.deadline_rule_backfill_orphans ENABLE ROW LEVEL SECURITY;

DROP POLICY IF EXISTS deadline_rule_backfill_orphans_select ON paliad.deadline_rule_backfill_orphans;

CREATE POLICY deadline_rule_backfill_orphans_select
    ON paliad.deadline_rule_backfill_orphans FOR SELECT
    USING (
        EXISTS (
            SELECT 1 FROM paliad.users u
             WHERE u.id = auth.uid()
               AND u.global_role = 'global_admin'
        )
    );
