-- 138_appeal_target_backfill_merits_order — t-paliad-303, m/paliad#134
--
-- Slice B1 (mig 134) introduced the unified upc.apl.unified proceeding type
-- with 5 appeal_target enum values: endentscheidung, kostenentscheidung,
-- anordnung, schadensbemessung, bucheinsicht. The first three each carry
-- rules; schadensbemessung and bucheinsicht returned an empty timeline
-- because no rules referenced them yet.
--
-- m's 2026-05-26 decision (#134): extend applies_to_target on the existing
-- rules — Schadensbemessung := merits track (R.224 anchored on R.118
-- substantive decisions), Bucheinsicht := order track (R.220.2 +
-- R.224.2.b + R.235.2 + R.237 + R.238.2 etc.). Legal premise verified
-- against the 16 live rules — every endentscheidung rule is a generic
-- R.224 merits step, every anordnung rule is a generic R.220/224/235/237/
-- 238 order step. No rule carries content specific to a particular kind
-- of underlying decision/order. Audit on the comment trail of #134.

-- ---------------------------------------------------------------
-- 0. Audit reason (required by mig 079 trigger for any UPDATE on
--    paliad.deadline_rules — both UPDATEs below trigger it).
-- ---------------------------------------------------------------

SELECT set_config(
    'paliad.audit_reason',
    'mig 138: t-paliad-303 — extend applies_to_target for Schadensbemessung (merits) + Bucheinsicht (order) per m/paliad#134',
    true);

-- ---------------------------------------------------------------
-- 1. Audit-first DO block.
--
-- Resolve upc.apl.unified, count the rows we are about to touch, and
-- RAISE EXCEPTION if anything looks wrong (proceeding type missing,
-- merits/order rule counts off, or a rule already carries the new
-- target — which would mean an earlier partial run).
-- ---------------------------------------------------------------

DO $$
DECLARE
    rec record;
    upc_apl_id int;
    merits_count int;
    order_count int;
    schad_already int;
    buch_already int;
BEGIN
    SELECT id INTO upc_apl_id
      FROM paliad.proceeding_types
     WHERE code = 'upc.apl.unified';
    IF upc_apl_id IS NULL THEN
        RAISE EXCEPTION '[mig 138] upc.apl.unified proceeding_type not found — mig 134 must run first';
    END IF;
    RAISE NOTICE '[mig 138] upc.apl.unified proceeding_type_id = %', upc_apl_id;

    SELECT COUNT(*) INTO merits_count
      FROM paliad.deadline_rules
     WHERE proceeding_type_id = upc_apl_id
       AND is_active = true
       AND 'endentscheidung' = ANY(applies_to_target);
    SELECT COUNT(*) INTO order_count
      FROM paliad.deadline_rules
     WHERE proceeding_type_id = upc_apl_id
       AND is_active = true
       AND 'anordnung' = ANY(applies_to_target);

    RAISE NOTICE '[mig 138] live counts: endentscheidung=% anordnung=%', merits_count, order_count;
    IF merits_count <> 7 THEN
        RAISE EXCEPTION '[mig 138] expected 7 endentscheidung rules under upc.apl.unified, got %', merits_count;
    END IF;
    IF order_count <> 7 THEN
        RAISE EXCEPTION '[mig 138] expected 7 anordnung rules under upc.apl.unified, got %', order_count;
    END IF;

    SELECT COUNT(*) INTO schad_already
      FROM paliad.deadline_rules
     WHERE proceeding_type_id = upc_apl_id
       AND is_active = true
       AND 'schadensbemessung' = ANY(applies_to_target);
    SELECT COUNT(*) INTO buch_already
      FROM paliad.deadline_rules
     WHERE proceeding_type_id = upc_apl_id
       AND is_active = true
       AND 'bucheinsicht' = ANY(applies_to_target);
    IF schad_already > 0 THEN
        RAISE EXCEPTION '[mig 138] % rules already carry schadensbemessung — partial run?', schad_already;
    END IF;
    IF buch_already > 0 THEN
        RAISE EXCEPTION '[mig 138] % rules already carry bucheinsicht — partial run?', buch_already;
    END IF;

    RAISE NOTICE '[mig 138] rules to extend with schadensbemessung (merits track):';
    FOR rec IN
        SELECT dr.id, dr.rule_code, dr.legal_source, dr.name, dr.applies_to_target
          FROM paliad.deadline_rules dr
         WHERE dr.proceeding_type_id = upc_apl_id
           AND dr.is_active = true
           AND 'endentscheidung' = ANY(dr.applies_to_target)
         ORDER BY dr.sequence_order, dr.rule_code NULLS LAST
    LOOP
        RAISE NOTICE '[mig 138]   merits  %  %  %  pre=%  →  post=%',
            COALESCE(rec.rule_code, '(no-code)'),
            COALESCE(rec.legal_source, '(no-source)'),
            rec.name,
            rec.applies_to_target,
            rec.applies_to_target || 'schadensbemessung'::text;
    END LOOP;

    RAISE NOTICE '[mig 138] rules to extend with bucheinsicht (order track):';
    FOR rec IN
        SELECT dr.id, dr.rule_code, dr.legal_source, dr.name, dr.applies_to_target
          FROM paliad.deadline_rules dr
         WHERE dr.proceeding_type_id = upc_apl_id
           AND dr.is_active = true
           AND 'anordnung' = ANY(dr.applies_to_target)
         ORDER BY dr.sequence_order, dr.rule_code NULLS LAST
    LOOP
        RAISE NOTICE '[mig 138]   order   %  %  %  pre=%  →  post=%',
            COALESCE(rec.rule_code, '(no-code)'),
            COALESCE(rec.legal_source, '(no-source)'),
            rec.name,
            rec.applies_to_target,
            rec.applies_to_target || 'bucheinsicht'::text;
    END LOOP;
END $$;

-- ---------------------------------------------------------------
-- 2. Extend applies_to_target.
--
-- Narrow WHERE clauses key off upc.apl.unified + existing target +
-- absence of new target, so the UPDATEs are idempotent in spirit
-- (the audit block above already RAISE EXCEPTIONed if any row
-- already had the new value).
-- ---------------------------------------------------------------

-- 2a. Schadensbemessung := merits track (7 rules expected).
UPDATE paliad.deadline_rules dr
   SET applies_to_target = applies_to_target || 'schadensbemessung'::text
  FROM paliad.proceeding_types pt
 WHERE pt.id = dr.proceeding_type_id
   AND pt.code = 'upc.apl.unified'
   AND dr.is_active = true
   AND 'endentscheidung' = ANY(dr.applies_to_target)
   AND NOT ('schadensbemessung' = ANY(dr.applies_to_target));

-- 2b. Bucheinsicht := order track (7 rules expected).
UPDATE paliad.deadline_rules dr
   SET applies_to_target = applies_to_target || 'bucheinsicht'::text
  FROM paliad.proceeding_types pt
 WHERE pt.id = dr.proceeding_type_id
   AND pt.code = 'upc.apl.unified'
   AND dr.is_active = true
   AND 'anordnung' = ANY(dr.applies_to_target)
   AND NOT ('bucheinsicht' = ANY(dr.applies_to_target));

-- ---------------------------------------------------------------
-- 3. Post-migration sanity check.
--
-- Hard-fail on any divergence: the two new targets must each cover
-- 7 rules, the original three targets must be unchanged in count,
-- and no rule has lost its prior target.
-- ---------------------------------------------------------------

DO $$
DECLARE
    schad_post int;
    buch_post int;
    end_post int;
    anord_post int;
    cost_post int;
    target_distribution record;
BEGIN
    SELECT COUNT(*) INTO schad_post
      FROM paliad.deadline_rules dr
      JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
     WHERE pt.code = 'upc.apl.unified'
       AND dr.is_active = true
       AND 'schadensbemessung' = ANY(dr.applies_to_target);
    SELECT COUNT(*) INTO buch_post
      FROM paliad.deadline_rules dr
      JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
     WHERE pt.code = 'upc.apl.unified'
       AND dr.is_active = true
       AND 'bucheinsicht' = ANY(dr.applies_to_target);
    SELECT COUNT(*) INTO end_post
      FROM paliad.deadline_rules dr
      JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
     WHERE pt.code = 'upc.apl.unified'
       AND dr.is_active = true
       AND 'endentscheidung' = ANY(dr.applies_to_target);
    SELECT COUNT(*) INTO anord_post
      FROM paliad.deadline_rules dr
      JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
     WHERE pt.code = 'upc.apl.unified'
       AND dr.is_active = true
       AND 'anordnung' = ANY(dr.applies_to_target);
    SELECT COUNT(*) INTO cost_post
      FROM paliad.deadline_rules dr
      JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
     WHERE pt.code = 'upc.apl.unified'
       AND dr.is_active = true
       AND 'kostenentscheidung' = ANY(dr.applies_to_target);

    RAISE NOTICE '[mig 138] post: schadensbemessung=%  bucheinsicht=%  endentscheidung=%  anordnung=%  kostenentscheidung=%',
        schad_post, buch_post, end_post, anord_post, cost_post;

    IF schad_post <> 7 THEN
        RAISE EXCEPTION '[mig 138] FAILED — expected 7 schadensbemessung rules, got %', schad_post;
    END IF;
    IF buch_post <> 7 THEN
        RAISE EXCEPTION '[mig 138] FAILED — expected 7 bucheinsicht rules, got %', buch_post;
    END IF;
    IF end_post <> 7 THEN
        RAISE EXCEPTION '[mig 138] FAILED — endentscheidung count drifted: expected 7, got %', end_post;
    END IF;
    IF anord_post <> 7 THEN
        RAISE EXCEPTION '[mig 138] FAILED — anordnung count drifted: expected 7, got %', anord_post;
    END IF;
    IF cost_post <> 2 THEN
        RAISE EXCEPTION '[mig 138] FAILED — kostenentscheidung count drifted: expected 2, got %', cost_post;
    END IF;

    FOR target_distribution IN
        SELECT unnest(applies_to_target) AS target, COUNT(*) AS n
          FROM paliad.deadline_rules dr
          JOIN paliad.proceeding_types pt ON pt.id = dr.proceeding_type_id
         WHERE pt.code = 'upc.apl.unified' AND dr.is_active = true
         GROUP BY unnest(applies_to_target)
         ORDER BY 1
    LOOP
        RAISE NOTICE '[mig 138] post: applies_to_target=%  count=%',
            target_distribution.target, target_distribution.n;
    END LOOP;
END $$;
