-- 139_deadline_rules_unified_view — Slice B.3 read cutover (t-paliad-305 / m/paliad#93)
--
-- Creates paliad.deadline_rules_unified — a Postgres VIEW that
-- re-projects paliad.sequencing_rules + paliad.procedural_events +
-- paliad.legal_sources back into the legacy paliad.deadline_rules
-- column shape.
--
-- Why a view instead of rewriting every SELECT in Go:
--
--   - 19 read sites across 11 service files reference
--     paliad.deadline_rules. Rewriting each by hand multiplies the
--     opportunity for off-by-one bugs in the JOIN.
--   - The view has the same column names + types as the legacy table,
--     so the change in Go is a 1-token substitution per query
--     (FROM paliad.deadline_rules → FROM paliad.deadline_rules_unified)
--     with no struct or scanner changes.
--   - When B.4 drops paliad.deadline_rules, this view stays — it
--     becomes the canonical legacy-shape reader for any code that
--     hasn't been migrated to direct sr/pe/ls reads.
--
-- Column mapping (per design §4.2):
--   - id, proceeding_type_id, parent_id, primary_party, duration_*,
--     timing, sequence_order, is_spawn/court_set/bilateral, priority,
--     rule_code, rule_codes, deadline_notes(_en), condition_expr,
--     choices_offered, applies_to_target, trigger_event_id,
--     spawn_proceeding_type_id, anchor_alt, alt_duration_*,
--     alt_rule_code, combine_op, lifecycle_state, draft_of,
--     published_at, is_active, created_at, updated_at, spawn_label
--       → from paliad.sequencing_rules
--   - submission_code           → procedural_events.code
--   - name, name_en, description→ procedural_events
--   - event_type                → procedural_events.event_kind (renamed)
--   - concept_id                → procedural_events
--   - legal_source              → legal_sources.citation (via legal_source_id FK)
--
-- The view is READ-ONLY by default. Writes still go to the underlying
-- tables — RuleEditorService is refactored in the same slice to write
-- directly to sr/pe/ls. paliad.deadline_rules is FROZEN from B.3 onward
-- (no new writes); the dual-write helper from B.2 is decommissioned.

-- The CHECK constraint on sequencing_rules.primary_party doesn't exist
-- yet (mig 135 only constrained deadline_rules.primary_party). The view
-- inherits whatever value sr.primary_party carries; mig 136's backfill
-- set sr.primary_party = dr.primary_party so the canonical four-value
-- vocab is already in place. A later slice can add the same CHECK to
-- sequencing_rules itself.

CREATE OR REPLACE VIEW paliad.deadline_rules_unified AS
SELECT
    sr.id,
    sr.proceeding_type_id,
    sr.parent_id,
    pe.code                    AS submission_code,
    pe.name,
    pe.name_en,
    pe.description,
    sr.primary_party,
    pe.event_kind              AS event_type,
    sr.duration_value,
    sr.duration_unit,
    sr.timing,
    sr.alt_duration_value,
    sr.alt_duration_unit,
    sr.alt_rule_code,
    sr.anchor_alt,
    sr.combine_op,
    sr.rule_code,
    sr.deadline_notes,
    sr.deadline_notes_en,
    sr.sequence_order,
    sr.is_spawn,
    sr.spawn_label,
    sr.spawn_proceeding_type_id,
    sr.is_bilateral,
    sr.is_court_set,
    sr.priority,
    sr.condition_expr,
    pe.concept_id,
    ls.citation                AS legal_source,
    sr.trigger_event_id,
    sr.rule_codes,
    sr.choices_offered,
    sr.applies_to_target,
    sr.lifecycle_state,
    sr.draft_of,
    sr.published_at,
    sr.is_active,
    sr.created_at,
    sr.updated_at
  FROM paliad.sequencing_rules sr
  JOIN paliad.procedural_events pe ON pe.id = sr.procedural_event_id
  LEFT JOIN paliad.legal_sources  ls ON ls.id = pe.legal_source_id;

COMMENT ON VIEW paliad.deadline_rules_unified IS
    'Slice B.3 (mig 139, t-paliad-305): legacy-shape projection over '
    'sequencing_rules + procedural_events + legal_sources. Read-only — '
    'writes go directly to the three underlying tables via '
    'RuleEditorService. Survives B.4 destructive drop of '
    'paliad.deadline_rules; the view will then be the only '
    'legacy-shape reader.';

-- Post-apply integrity check: confirm the view's row count matches the
-- live sequencing_rules row count. A mismatch would indicate either a
-- mid-deploy race (rare) or a JOIN issue (the LEFT JOIN to legal_sources
-- never drops rows, the INNER JOIN to procedural_events drops sr rows
-- whose procedural_event_id is NULL — but that column is NOT NULL on
-- the table so it can't happen). Belt-and-braces.
DO $$
DECLARE
    v_view_count int;
    v_sr_count   int;
BEGIN
    SELECT COUNT(*) INTO v_view_count FROM paliad.deadline_rules_unified;
    SELECT COUNT(*) INTO v_sr_count   FROM paliad.sequencing_rules;
    IF v_view_count <> v_sr_count THEN
        RAISE EXCEPTION '[mig 139] FAILED POST: view row count % does not match sequencing_rules row count %. '
            'Possible cause: a sequencing_rules row references a procedural_event_id that does not exist (NOT NULL FK should prevent this).',
            v_view_count, v_sr_count;
    END IF;
    RAISE NOTICE '[mig 139] view OK — deadline_rules_unified rows = % (= sequencing_rules)',
        v_view_count;
END $$;
