-- t-paliad-184 / Fristen Phase 3 Slice 3 Step C — data-move 77 rows
-- from paliad.event_deadlines → paliad.deadline_rules so the Phase-3
-- unified backend can serve both pipelines.
--
-- Source rows are PRESERVED (mig 086's read-only trigger blocks
-- further writes; mig 090 in Slice 9 drops the table once every
-- caller has cut over). The data-move is one-way; legacy callers
-- continue reading event_deadlines via plain SELECTs until Slice 9.
--
-- Mapping (per design §3.C):
--
--   paliad.event_deadlines               →  paliad.deadline_rules
--   -------------------------               ----------------------
--   id                                      (new gen_random_uuid())
--   trigger_event_id                        trigger_event_id           (Phase 3 column from mig 078)
--   title         (EN, NOT NULL)            name_en                    (NOT NULL)
--   title_de      (DE, NOT NULL DEFAULT '') name                       (NOT NULL — every row has non-empty title_de in live data)
--   duration_value                          duration_value
--   duration_unit (days/weeks/months/working_days) duration_unit
--   timing        (before/after)            timing
--   notes         (DE)                      deadline_notes             (DE)
--   notes_en      (EN, nullable)            deadline_notes_en          (EN, nullable)
--   alt_duration_value                      alt_duration_value
--   alt_duration_unit                       alt_duration_unit
--   combine_op    (max/min, nullable)       combine_op                 (Phase 3 column from mig 078)
--   legal_source                            legal_source
--   is_active                               is_active
--   created_at                              published_at               (preserves chronology — lifecycle_state='published' on every row)
--                                           updated_at = now()         (this is the publish event)
--
-- Pipeline-A-only fields default:
--   proceeding_type_id        = NULL      (event-rooted, no proceeding)
--   parent_id                 = NULL      (Pipeline C is flat, no chain)
--   spawn_proceeding_type_id  = NULL      (no spawn)
--   code                      = NULL      (no local rule code in Pipeline C)
--   primary_party             = NULL      (event_deadlines has no party column)
--   event_type                = NULL      (filing/hearing/decision is a
--                                           Pipeline-A category)
--   is_court_set              = false     (no court-set Pipeline-C rules
--                                           in the corpus; legal-review
--                                           pass can flip Zustellung-* if
--                                           those ever land here)
--   is_spawn                  = false
--   is_mandatory              = true      (Pipeline C has no mandatory
--                                           bool; design §2.3 says default
--                                           'mandatory' is correct for
--                                           statutory event-driven deadlines)
--   is_optional               = false
--   priority                  = 'mandatory'
--   condition_expr            = NULL      (Pipeline C has no flag gating)
--   condition_flag            = NULL
--   sequence_order            = 1000 + event_deadlines.id
--                                           (large offset so Pipeline-C
--                                           rows sort AFTER any future
--                                           hand-edited Pipeline-A
--                                           sequence_orders without
--                                           colliding with the
--                                           existing 0–171 range)
--   lifecycle_state           = 'published'
--
-- Idempotency: WHERE NOT EXISTS guard on (trigger_event_id, name) skips
-- rows that already exist in deadline_rules. Re-running the migration
-- is a no-op.
--
-- Hard assertion at end: COUNT(deadline_rules WHERE trigger_event_id
-- IS NOT NULL) == COUNT(event_deadlines WHERE is_active = true) (77 = 77).
-- RAISE EXCEPTION on mismatch so a partial move fails the migration
-- loudly instead of poisoning Slice 4.
--
-- Audit-reason cites design §3.C — the rationale persists in the
-- paliad.deadline_rule_audit log forever via the mig 079 trigger.

SELECT set_config(
    'paliad.audit_reason',
    'pipeline C migration 085: data-move event_deadlines → deadline_rules per design §3.C — '
        || 'preserves source rows; mig 086 wraps the source table read-only',
    true);

INSERT INTO paliad.deadline_rules (
    id,
    proceeding_type_id,
    parent_id,
    trigger_event_id,
    spawn_proceeding_type_id,
    code,
    name,
    name_en,
    primary_party,
    event_type,
    is_mandatory,
    is_optional,
    is_court_set,
    is_spawn,
    duration_value,
    duration_unit,
    timing,
    alt_duration_value,
    alt_duration_unit,
    combine_op,
    rule_code,
    deadline_notes,
    deadline_notes_en,
    legal_source,
    condition_expr,
    condition_flag,
    sequence_order,
    is_active,
    priority,
    lifecycle_state,
    draft_of,
    published_at,
    created_at,
    updated_at
)
SELECT
    gen_random_uuid()                                       AS id,
    NULL::integer                                           AS proceeding_type_id,
    NULL::uuid                                              AS parent_id,
    ed.trigger_event_id                                     AS trigger_event_id,
    NULL::integer                                           AS spawn_proceeding_type_id,
    NULL::text                                              AS code,
    ed.title_de                                             AS name,
    ed.title                                                AS name_en,
    NULL::text                                              AS primary_party,
    NULL::text                                              AS event_type,
    true                                                    AS is_mandatory,
    false                                                   AS is_optional,
    false                                                   AS is_court_set,
    false                                                   AS is_spawn,
    ed.duration_value                                       AS duration_value,
    ed.duration_unit                                        AS duration_unit,
    ed.timing                                               AS timing,
    ed.alt_duration_value                                   AS alt_duration_value,
    ed.alt_duration_unit                                    AS alt_duration_unit,
    ed.combine_op                                           AS combine_op,
    NULL::text                                              AS rule_code,
    NULLIF(ed.notes, '')                                    AS deadline_notes,
    ed.notes_en                                             AS deadline_notes_en,
    ed.legal_source                                         AS legal_source,
    NULL::jsonb                                             AS condition_expr,
    NULL::text[]                                            AS condition_flag,
    (1000 + ed.id)::integer                                 AS sequence_order,
    ed.is_active                                            AS is_active,
    'mandatory'                                             AS priority,
    'published'                                             AS lifecycle_state,
    NULL::uuid                                              AS draft_of,
    ed.created_at                                           AS published_at,
    ed.created_at                                           AS created_at,
    now()                                                   AS updated_at
FROM paliad.event_deadlines ed
WHERE ed.is_active = true
  AND NOT EXISTS (
        SELECT 1
          FROM paliad.deadline_rules dr
         WHERE dr.trigger_event_id = ed.trigger_event_id
           AND dr.name = ed.title_de
  );

-- Hard assertion: every active event_deadlines row must have a matching
-- deadline_rules row by (trigger_event_id, name). If the counts diverge,
-- something in the WHERE NOT EXISTS clause (likely a stale duplicate)
-- prevented a real insert — fail the migration rather than ship a
-- partial Pipeline-C corpus.
DO $$
DECLARE
    n_source  int;
    n_target  int;
BEGIN
    SELECT count(*) INTO n_source
      FROM paliad.event_deadlines WHERE is_active = true;

    SELECT count(*) INTO n_target
      FROM paliad.deadline_rules WHERE trigger_event_id IS NOT NULL;

    RAISE NOTICE 'mig 085: event_deadlines(active)=%, deadline_rules(trigger_event_id IS NOT NULL)=%',
                 n_source, n_target;

    IF n_target <> n_source THEN
        RAISE EXCEPTION 'mig 085: data-move incomplete — expected % unified rows, got %. '
                        'Investigate event_deadlines (trigger_event_id, title_de) duplicates '
                        'OR re-applied migration on dirtied target.',
                        n_source, n_target;
    END IF;
END $$;
