-- t-paliad-131 Phase C: search backend.
--
-- Two artefacts in one migration:
--
--   1. Fix a dangling concept slug from PR-7 (Phase B6). The four
--      Wiedereinsetzung trigger_events were inserted referencing concept
--      slug `re-establishment-of-rights`, but the concept was never
--      seeded — the slug was English-style while the concept-naming
--      convention (m's Q1, design §11) requires DE slugs for shared
--      cross-cutting concepts where the German term dominates HLC
--      vocabulary. Without the fix, the four Wiedereinsetzung rows
--      drop out of the unified search view's INNER JOIN and the
--      golden test `search "Wiedereinsetzung" → 1 concept × 4 pills`
--      cannot pass.
--
--   2. Create paliad.deadline_search — a materialised view that
--      flattens (deadline_concepts × deadline_rules) and (deadline_concepts
--      × trigger_events via slug) into one searchable shape. Indexed
--      with pg_trgm GIN on the columns the search query probes. See
--      design doc §4.6 + §6.
--
-- Refresh strategy: data only mutates via migration files at server
-- startup, so a refresh after migrations apply (in main.go) is enough.
-- No AFTER triggers, no pg_cron — keeps the migration pure SQL.

-- ============================================================================
-- 1. Wiedereinsetzung concept (fixes the PR-7 dangling slug)
-- ============================================================================

INSERT INTO paliad.deadline_concepts (slug, name_de, name_en, description, aliases, party, category, sort_order)
VALUES (
    'wiedereinsetzung',
    'Wiedereinsetzung in den vorigen Stand',
    'Re-establishment of Rights',
    'Antrag auf Wiedereinsetzung in den vorigen Stand bei unverschuldeter Versäumung einer gesetzlichen Frist. Die Frist beträgt zwei Monate ab Wegfall des Hindernisses (PatG §123, ZPO §233, EPÜ Art.122).',
    ARRAY['Wiedereinsetzung', 'Wiedereinsetzungsantrag', 'Re-establishment of Rights', 'Re-establishment', 'Antrag auf Wiedereinsetzung', 'Restitutio', 'restitutio in integrum'],
    'both',
    'submission',
    35
);

UPDATE paliad.trigger_events
   SET concept_id = 'wiedereinsetzung'
 WHERE id IN (200, 201, 202, 203)
   AND concept_id = 're-establishment-of-rights';

-- ============================================================================
-- 2. Materialised search view + indexes
-- ============================================================================
--
-- One row per (concept × context). Two contexts:
--   kind='rule'    — concept-linked deadline_rule under an active
--                    fristenrechner-category proceeding_type
--   kind='trigger' — concept-linked trigger_event (cross-cutting; no
--                    proceeding context, no rule_id, no duration)
--
-- Search ranks rows per concept_id, then per concept fans out to all its
-- rule + trigger pills. row_key is a synthetic UNIQUE column required for
-- REFRESH MATERIALIZED VIEW CONCURRENTLY.
CREATE MATERIALIZED VIEW paliad.deadline_search AS
SELECT
    'rule'::text                         AS kind,
    'r:' || dr.id::text                  AS row_key,
    dc.id                                AS concept_id,
    dc.slug                              AS concept_slug,
    dc.name_de                           AS concept_name_de,
    dc.name_en                           AS concept_name_en,
    dc.description                       AS concept_description,
    dc.aliases                           AS concept_aliases,
    dc.party                             AS concept_party,
    dc.category                          AS concept_category,
    dc.sort_order                        AS concept_sort_order,
    dr.id                                AS rule_id,
    NULL::bigint                         AS trigger_event_id,
    pt.code                              AS proceeding_code,
    pt.name                              AS proceeding_name_de,
    pt.name_en                           AS proceeding_name_en,
    pt.jurisdiction                      AS jurisdiction,
    dr.code                              AS rule_local_code,
    dr.name                              AS rule_name_de,
    dr.name_en                           AS rule_name_en,
    dr.legal_source                      AS legal_source,
    dr.rule_code                         AS rule_code,
    dr.duration_value,
    dr.duration_unit,
    dr.timing,
    COALESCE(dr.primary_party, dc.party) AS effective_party
  FROM paliad.deadline_rules dr
  JOIN paliad.proceeding_types pt  ON pt.id = dr.proceeding_type_id
  JOIN paliad.deadline_concepts dc ON dc.id = dr.concept_id
 WHERE dr.is_active
   AND pt.is_active
   AND pt.category = 'fristenrechner'

UNION ALL

SELECT
    'trigger'::text,
    't:' || te.id::text,
    dc.id,
    dc.slug,
    dc.name_de,
    dc.name_en,
    dc.description,
    dc.aliases,
    dc.party,
    dc.category,
    dc.sort_order,
    NULL::uuid,
    te.id,
    NULL::text,
    NULL::text,
    NULL::text,
    'cross-cutting'::text,
    te.code,
    te.name_de,
    te.name,
    NULL::text,
    NULL::text,
    NULL::int,
    NULL::text,
    NULL::text,
    dc.party
  FROM paliad.trigger_events te
  JOIN paliad.deadline_concepts dc ON dc.slug = te.concept_id
 WHERE te.is_active;

-- Required for REFRESH MATERIALIZED VIEW CONCURRENTLY.
CREATE UNIQUE INDEX deadline_search_row_key
    ON paliad.deadline_search (row_key);

-- Btree for filter narrowing.
CREATE INDEX deadline_search_concept_id
    ON paliad.deadline_search (concept_id);
CREATE INDEX deadline_search_proc_code
    ON paliad.deadline_search (proceeding_code);
CREATE INDEX deadline_search_legal_source
    ON paliad.deadline_search (legal_source);
CREATE INDEX deadline_search_effective_party
    ON paliad.deadline_search (effective_party);

-- Trigram GIN for the LIKE / similarity()-driven WHERE clause.
CREATE INDEX deadline_search_legal_source_trgm
    ON paliad.deadline_search USING gin (legal_source gin_trgm_ops);
CREATE INDEX deadline_search_concept_de_trgm
    ON paliad.deadline_search USING gin (concept_name_de gin_trgm_ops);
CREATE INDEX deadline_search_concept_en_trgm
    ON paliad.deadline_search USING gin (concept_name_en gin_trgm_ops);
CREATE INDEX deadline_search_rule_de_trgm
    ON paliad.deadline_search USING gin (rule_name_de gin_trgm_ops);
CREATE INDEX deadline_search_rule_en_trgm
    ON paliad.deadline_search USING gin (rule_name_en gin_trgm_ops);
CREATE INDEX deadline_search_rule_code_trgm
    ON paliad.deadline_search USING gin (rule_code gin_trgm_ops);

-- Array containment for `aliases @> ARRAY[…]`.
CREATE INDEX deadline_search_aliases
    ON paliad.deadline_search USING gin (concept_aliases);

COMMENT ON MATERIALIZED VIEW paliad.deadline_search IS
    'Phase C unified search backend. Refreshed CONCURRENTLY by main.go '
    'after migrations apply at server startup. Source data: '
    'deadline_rules ∪ trigger_events, joined to deadline_concepts. '
    'See docs/plans/unified-fristenrechner.md §4.6 + §6.';
