-- Migration 053: Issues rework
-- 1. Fix update trigger bug (uses wrong column name)
-- 2. Dynamic issue types table (issue_typen)
-- 3. Migrate issues.typ → issues.typ_id
-- 4. Permission rework: replace issues:manage with granular permissions

-- ═══════════════════════════════════════════════════════════════════════════
-- 1. Fix update trigger
-- The old trigger calls update_aktualisiert_am() which sets NEW.aktualisiert_am,
-- but issues table uses updated_at → crashes every UPDATE.
-- ═══════════════════════════════════════════════════════════════════════════

DROP TRIGGER IF EXISTS trg_issues_updated ON issues;

CREATE OR REPLACE FUNCTION update_issues_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER trg_issues_updated BEFORE UPDATE ON issues
  FOR EACH ROW EXECUTE FUNCTION update_issues_updated_at();

-- ═══════════════════════════════════════════════════════════════════════════
-- 2. Dynamic types table
-- ═══════════════════════════════════════════════════════════════════════════

CREATE TABLE IF NOT EXISTS issue_typen (
  id              SERIAL       PRIMARY KEY,
  name            VARCHAR(100) NOT NULL,
  parent_id       INT          REFERENCES issue_typen(id) ON DELETE CASCADE,
  icon            VARCHAR(50)  DEFAULT NULL,
  farbe           VARCHAR(20)  DEFAULT NULL,
  erlaubt_abgelehnt BOOLEAN   NOT NULL DEFAULT true,
  sort_order      INT          NOT NULL DEFAULT 0,
  aktiv           BOOLEAN      NOT NULL DEFAULT true,
  created_at      TIMESTAMPTZ  NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_issue_typen_parent ON issue_typen(parent_id);

-- Seed default types
INSERT INTO issue_typen (id, name, parent_id, icon, farbe, erlaubt_abgelehnt, sort_order) VALUES
  (1, 'Bug',                NULL, 'BugReport',    'error',  false, 1),
  (2, 'Funktionsanfrage',   NULL, 'FiberNew',     'info',   true,  2),
  (3, 'Sonstiges',          NULL, 'HelpOutline',  'action', true,  3)
ON CONFLICT (id) DO NOTHING;

-- Ensure sequence is past seeded IDs
SELECT setval('issue_typen_id_seq', GREATEST((SELECT MAX(id) FROM issue_typen), 3));

-- ═══════════════════════════════════════════════════════════════════════════
-- 3. Migrate issues.typ column → typ_id FK
-- ═══════════════════════════════════════════════════════════════════════════

ALTER TABLE issues ADD COLUMN IF NOT EXISTS typ_id INT REFERENCES issue_typen(id) ON DELETE SET NULL;

-- Migrate existing data
UPDATE issues SET typ_id = 1 WHERE typ = 'bug'       AND typ_id IS NULL;
UPDATE issues SET typ_id = 2 WHERE typ = 'feature'    AND typ_id IS NULL;
UPDATE issues SET typ_id = 3 WHERE typ = 'sonstiges'  AND typ_id IS NULL;
-- Fallback: anything unmapped → Sonstiges
UPDATE issues SET typ_id = 3 WHERE typ_id IS NULL;

-- Drop old constraint and column
ALTER TABLE issues DROP CONSTRAINT IF EXISTS issues_typ_check;
ALTER TABLE issues DROP COLUMN IF EXISTS typ;

CREATE INDEX IF NOT EXISTS idx_issues_typ_id ON issues(typ_id);
CREATE INDEX IF NOT EXISTS idx_issues_zugewiesen_an ON issues(zugewiesen_an);

-- ═══════════════════════════════════════════════════════════════════════════
-- 4. Permission rework
-- Replace issues:manage with granular permissions
-- ═══════════════════════════════════════════════════════════════════════════

-- 4a. Find all groups that had issues:manage and give them the new permissions
-- We use a temp table to store the groups that had manage
CREATE TEMP TABLE IF NOT EXISTS _issues_manage_groups AS
  SELECT authentik_group FROM group_permissions WHERE permission_id = 'issues:manage';

-- 4b. Insert new permissions
INSERT INTO permissions (id, feature_group_id, label, description, sort_order) VALUES
  ('issues:change_status', 'issues', 'Status ändern',    'Status ändern und kommentieren',                               4),
  ('issues:edit',          'issues', 'Bearbeiten',       'Issues bearbeiten (Titel, Beschreibung, Typ, Priorität, Zuweisung)', 5),
  ('issues:edit_settings', 'issues', 'Einstellungen',    'Issue-Kategorien verwalten',                                    6),
  ('issues:delete',        'issues', 'Löschen',          'Issues löschen',                                                7)
ON CONFLICT (id) DO NOTHING;

-- 4c. Grant all new permissions to groups that had manage
INSERT INTO group_permissions (authentik_group, permission_id)
  SELECT g.authentik_group, p.id
  FROM _issues_manage_groups g
  CROSS JOIN (VALUES
    ('issues:view_all'),
    ('issues:change_status'),
    ('issues:edit'),
    ('issues:edit_settings'),
    ('issues:delete')
  ) AS p(id)
ON CONFLICT DO NOTHING;

-- 4d. Remove old manage permission
DELETE FROM group_permissions WHERE permission_id = 'issues:manage';
DELETE FROM permissions WHERE id = 'issues:manage';

DROP TABLE IF EXISTS _issues_manage_groups;

-- 4e. Update permission_deps in app_settings JSON
-- Remove old issues entries and add new ones
UPDATE app_settings
SET value = jsonb_strip_nulls(
  (value - 'issues:view_own' - 'issues:view_all' - 'issues:manage')
  || '{
    "issues:create": ["issues:view_own"],
    "issues:view_all": ["issues:view_own"],
    "issues:change_status": ["issues:view_all"],
    "issues:edit": ["issues:view_all"],
    "issues:delete": ["issues:view_all"],
    "issues:edit_settings": ["issues:view_all"]
  }'::jsonb
)
WHERE key = 'permission_deps';
