-- t-paliad-136 Phase C: RoP-rigorous tree taxonomy revision.
--
-- Targeted data fixes to paliad.event_category_concepts based on the v4
-- audit (docs/plans/unified-fristenrechner-v4.md §3). Pure data migration.
-- No schema change. All operations idempotent (DELETE matches by slug
-- triple; INSERT … ON CONFLICT DO UPDATE for re-runs).
--
-- NO `RAISE EXCEPTION` coverage gate at the bottom — m's Q7 (2026-05-05)
-- moved gating to a Go-side test (see internal/services/event_category_
-- coverage_test.go) so a stale assertion can never block server boot.
-- Last night's outage was caused by exactly that pattern at the end of
-- migration 049 — kept there because it shipped, but no new gates added.
--
-- Six fix groups:
--   1. cms-eingang.gericht.hinweisbeschluss — drop DE_INF row (no
--      Hinweisbeschluss in DE infringement; concept lives only in DE_NULL).
--   2. cms-eingang.gegenseite.upc-inf.klageschrift — drop notice-of-
--      defence-intention | UPC_INF (no UPC rule for that concept; the
--      r23 reaction is captured by statement-of-defence directly).
--   3. UPC R.221 cost-appeal sequence (m's Q5): for each kostenfest-
--      setzung-related leaf, surface BOTH the leave-to-appeal step
--      (UPC_COST_APPEAL, R.221.1, 15 days) at sort 100 and the eventual
--      notice-of-appeal step (UPC_APP, R.220.1, conditional on leave
--      granted) at sort 200. Replaces the wrong notice-of-appeal |
--      UPC_COST_APPEAL row from the v3 seed.
--   4. ich-moechte-einreichen.berufung.upc-coa-orders — replace the
--      buggy application-for-leave-to-appeal | UPC_APP_ORDERS row
--      (concept doesn't exist in that proceeding) with request-for-
--      discretionary-review | UPC_APP_ORDERS (R.220.3).
--   5. cms-eingang.gericht.anordnung — narrow request-for-
--      discretionary-review from NULL (cross-cutting) to UPC_APP_ORDERS.
--   6. reply-to-cross-appeal coverage: add (concept × UPC_APP) rows
--      under the existing upc-{inf,rev}.berufungsschrift leaves so the
--      reply leaf is reachable. Plus three new leaves under ich-moechte-
--      einreichen.spaetere-schriftsaetze for proactive entry: r116-
--      eingaben, anschlussberufung-upc, reply-to-cross-appeal-upc.
--
-- Deferred per m's Q4: bescheid-mit-frist mapping. Will land separately.

BEGIN;

-- ============================================================================
-- 1. cms-eingang.gericht.hinweisbeschluss
--    DROP response-to-preliminary-opinion | DE_INF
--    Reason: DE_INF (LG infringement) has no Hinweisbeschluss step. The
--    Hinweisbeschluss is a BPatG-only mechanism per PatG §83. Matview
--    has this concept exclusively in DE_NULL. The DE_INF junction row
--    silently dropped any pill (concept_id matched but no matview row
--    for the proc) — confused the user via overbroad pre-Phase-A
--    leakage and produced empty cards post-Phase-A.
-- ============================================================================

DELETE FROM paliad.event_category_concepts
 WHERE event_category_id = (
        SELECT id FROM paliad.event_categories
         WHERE slug = 'cms-eingang.gericht.hinweisbeschluss'
       )
   AND concept_id = (
        SELECT id FROM paliad.deadline_concepts
         WHERE slug = 'response-to-preliminary-opinion'
       )
   AND proceeding_type_code = 'DE_INF';

-- ============================================================================
-- 2. cms-eingang.gegenseite.upc-inf.klageschrift
--    DROP notice-of-defence-intention | UPC_INF
--    Reason: UPC has no "notice of intention to defend" rule in the
--    deadline_rules corpus. The 1-month UPC R.23 reaction is encoded
--    via statement-of-defence directly (already mapped at sort 200).
-- ============================================================================

DELETE FROM paliad.event_category_concepts
 WHERE event_category_id = (
        SELECT id FROM paliad.event_categories
         WHERE slug = 'cms-eingang.gegenseite.upc-inf.klageschrift'
       )
   AND concept_id = (
        SELECT id FROM paliad.deadline_concepts
         WHERE slug = 'notice-of-defence-intention'
       )
   AND proceeding_type_code = 'UPC_INF';

-- ============================================================================
-- 3. UPC R.221 cost-appeal sequence — m's Q5 (2026-05-05).
--    Surface BOTH application-for-leave-to-appeal (sort 100, R.221.1,
--    15 days, UPC_COST_APPEAL proceeding) AND notice-of-appeal (sort
--    200, conditional on leave granted, R.220.1, UPC_APP proceeding).
--    Applies to three leaves where the v3 seed mistakenly mapped only
--    notice-of-appeal | UPC_COST_APPEAL (concept-proc combo has no
--    matching rule, silently dropped to no pill post-Phase-A).
-- ============================================================================

DELETE FROM paliad.event_category_concepts
 WHERE event_category_id IN (
        SELECT id FROM paliad.event_categories
         WHERE slug IN (
            'cms-eingang.gericht.kostenfestsetzung',
            'beschluss-entscheidung.kostenfestsetzung',
            'ich-moechte-einreichen.berufung.upc-cost'
         )
       )
   AND concept_id = (
        SELECT id FROM paliad.deadline_concepts
         WHERE slug = 'notice-of-appeal'
       )
   AND proceeding_type_code = 'UPC_COST_APPEAL';

INSERT INTO paliad.event_category_concepts
        (event_category_id, concept_id, proceeding_type_code, sort_order)
SELECT  ec.id, c.id, m.proc, m.sort_order
   FROM (VALUES
        ('cms-eingang.gericht.kostenfestsetzung',
            'application-for-leave-to-appeal', 'UPC_COST_APPEAL', 100),
        ('cms-eingang.gericht.kostenfestsetzung',
            'notice-of-appeal',                'UPC_APP',         200),
        ('beschluss-entscheidung.kostenfestsetzung',
            'application-for-leave-to-appeal', 'UPC_COST_APPEAL', 100),
        ('beschluss-entscheidung.kostenfestsetzung',
            'notice-of-appeal',                'UPC_APP',         200),
        ('ich-moechte-einreichen.berufung.upc-cost',
            'application-for-leave-to-appeal', 'UPC_COST_APPEAL', 100),
        ('ich-moechte-einreichen.berufung.upc-cost',
            'notice-of-appeal',                'UPC_APP',         200)
   ) AS m(leaf_slug, concept_slug, proc, sort_order)
   JOIN paliad.event_categories  ec ON ec.slug = m.leaf_slug
   JOIN paliad.deadline_concepts c  ON c.slug  = m.concept_slug
   ON CONFLICT (event_category_id, concept_id, proceeding_type_code)
       DO UPDATE SET sort_order = EXCLUDED.sort_order;

-- ============================================================================
-- 4. ich-moechte-einreichen.berufung.upc-coa-orders
--    Replace application-for-leave-to-appeal | UPC_APP_ORDERS (no rule
--    for that concept-proc combo) with request-for-discretionary-review
--    | UPC_APP_ORDERS (R.220.3). The other row (appeal-with-leave |
--    UPC_APP_ORDERS, R.220.2) is correct — keep it untouched.
-- ============================================================================

DELETE FROM paliad.event_category_concepts
 WHERE event_category_id = (
        SELECT id FROM paliad.event_categories
         WHERE slug = 'ich-moechte-einreichen.berufung.upc-coa-orders'
       )
   AND concept_id = (
        SELECT id FROM paliad.deadline_concepts
         WHERE slug = 'application-for-leave-to-appeal'
       )
   AND proceeding_type_code = 'UPC_APP_ORDERS';

INSERT INTO paliad.event_category_concepts
        (event_category_id, concept_id, proceeding_type_code, sort_order)
SELECT  ec.id, c.id, 'UPC_APP_ORDERS', 200
   FROM paliad.event_categories  ec
   JOIN paliad.deadline_concepts c
        ON c.slug = 'request-for-discretionary-review'
  WHERE ec.slug = 'ich-moechte-einreichen.berufung.upc-coa-orders'
   ON CONFLICT (event_category_id, concept_id, proceeding_type_code)
       DO UPDATE SET sort_order = EXCLUDED.sort_order;

-- ============================================================================
-- 5. cms-eingang.gericht.anordnung
--    Narrow request-for-discretionary-review NULL → UPC_APP_ORDERS.
--    Reason: R.220.3 review applies specifically to UPC_APP_ORDERS (the
--    Anordnungen / 15-day track), not as a generic cross-cutting trigger.
--    NULL was a v3-seed approximation pre-narrowing-fix.
-- ============================================================================

DELETE FROM paliad.event_category_concepts
 WHERE event_category_id = (
        SELECT id FROM paliad.event_categories
         WHERE slug = 'cms-eingang.gericht.anordnung'
       )
   AND concept_id = (
        SELECT id FROM paliad.deadline_concepts
         WHERE slug = 'request-for-discretionary-review'
       )
   AND proceeding_type_code IS NULL;

INSERT INTO paliad.event_category_concepts
        (event_category_id, concept_id, proceeding_type_code, sort_order)
SELECT  ec.id, c.id, 'UPC_APP_ORDERS', 100
   FROM paliad.event_categories  ec
   JOIN paliad.deadline_concepts c
        ON c.slug = 'request-for-discretionary-review'
  WHERE ec.slug = 'cms-eingang.gericht.anordnung'
   ON CONFLICT (event_category_id, concept_id, proceeding_type_code)
       DO UPDATE SET sort_order = EXCLUDED.sort_order;

-- ============================================================================
-- 6a. reply-to-cross-appeal coverage: add (concept × UPC_APP) rows
--     under the two existing UPC berufungsschrift leaves. The opponent
--     filed Anschlussberufung (R.237) and the user needs to respond
--     (R.238.1, 2 months).
-- ============================================================================

INSERT INTO paliad.event_category_concepts
        (event_category_id, concept_id, proceeding_type_code, sort_order)
SELECT  ec.id, c.id, 'UPC_APP', 300
   FROM (VALUES
        ('cms-eingang.gegenseite.upc-inf.berufungsschrift'),
        ('cms-eingang.gegenseite.upc-rev.berufungsschrift')
   ) AS m(leaf_slug)
   JOIN paliad.event_categories  ec ON ec.slug = m.leaf_slug
   JOIN paliad.deadline_concepts c
        ON c.slug = 'reply-to-cross-appeal'
   ON CONFLICT (event_category_id, concept_id, proceeding_type_code)
       DO UPDATE SET sort_order = EXCLUDED.sort_order;

-- ============================================================================
-- 6b. New leaves under ich-moechte-einreichen.spaetere-schriftsaetze:
--     proactive entry points the v3 seed missed.
--       - r116-eingaben         — R.116 final submissions before EPO oral hearing
--       - anschlussberufung-upc — UPC cross-appeal (R.237)
--       - reply-to-cross-appeal-upc — UPC reply to cross-appeal (R.238)
-- ============================================================================

INSERT INTO paliad.event_categories
        (slug, parent_id, label_de, label_en, icon, sort_order, is_leaf)
SELECT  s.slug, p.id, s.label_de, s.label_en, '↩', s.sort_order, true
   FROM paliad.event_categories p
   CROSS JOIN (VALUES
        ('ich-moechte-einreichen.spaetere-schriftsaetze.r116-eingaben',
         'Eingaben vor EPA mündl. Verhandlung (R.116)',
         'Final submissions before EPO oral hearing (R.116)', 700),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.anschlussberufung-upc',
         'Anschlussberufung UPC (R.237)',
         'UPC cross-appeal (R.237)', 800),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.reply-to-cross-appeal-upc',
         'Erwiderung auf Anschlussberufung UPC (R.238)',
         'Reply to UPC cross-appeal (R.238)', 900)
   ) AS s(slug, label_de, label_en, sort_order)
  WHERE p.slug = 'ich-moechte-einreichen.spaetere-schriftsaetze'
    ON CONFLICT (slug) DO NOTHING;

INSERT INTO paliad.event_category_concepts
        (event_category_id, concept_id, proceeding_type_code, sort_order)
SELECT  ec.id, c.id, m.proc, m.sort_order
   FROM (VALUES
        ('ich-moechte-einreichen.spaetere-schriftsaetze.r116-eingaben',
            'r116-final-submissions', 'EPA_OPP', 100),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.r116-eingaben',
            'r116-final-submissions', 'EPA_APP', 200),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.anschlussberufung-upc',
            'cross-appeal',           'UPC_APP',        100),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.anschlussberufung-upc',
            'cross-appeal',           'UPC_APP_ORDERS', 200),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.reply-to-cross-appeal-upc',
            'reply-to-cross-appeal',  'UPC_APP',        100),
        ('ich-moechte-einreichen.spaetere-schriftsaetze.reply-to-cross-appeal-upc',
            'reply-to-cross-appeal',  'UPC_APP_ORDERS', 200)
   ) AS m(leaf_slug, concept_slug, proc, sort_order)
   JOIN paliad.event_categories  ec ON ec.slug = m.leaf_slug
   JOIN paliad.deadline_concepts c  ON c.slug  = m.concept_slug
   ON CONFLICT (event_category_id, concept_id, proceeding_type_code)
       DO UPDATE SET sort_order = EXCLUDED.sort_order;

COMMIT;
