-- Migration 079: Capability-Registry + Rollen-Grants (M3 / CAPABILITY_CATALOG.v1.md C1)
-- Account-Gates und Enforcement in Python (account_lifecycle.py, capabilities.py).
-- Voraussetzung: Migration 078 (features.id TEXT). Kein FK auf features — vermeidet
-- Startup-Abbruch wenn 078 noch aussteht oder features-Schema driftet (001 vs v9c).

DO $migration$
BEGIN
    IF NOT EXISTS (
        SELECT 1 FROM information_schema.columns
        WHERE table_schema = 'public' AND table_name = 'features' AND column_name = 'limit_type'
    ) THEN
        RAISE EXCEPTION
            'Migration 079: features-Tabelle nicht v9c (limit_type fehlt). Zuerst 078_club_features_and_plans anwenden.';
    END IF;
END
$migration$;

CREATE TABLE IF NOT EXISTS capabilities (
    id                  TEXT PRIMARY KEY,
    name                TEXT NOT NULL,
    description         TEXT,
    domain              TEXT NOT NULL,
    min_account_state   TEXT NOT NULL DEFAULT 'active_member'
        CHECK (min_account_state IN (
            'unverified', 'verified_pending_club', 'active_member', 'platform_admin'
        )),
    linked_feature_id   TEXT,
    active              BOOLEAN NOT NULL DEFAULT true,
    created_at          TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    updated_at          TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_capabilities_domain ON capabilities(domain) WHERE active = true;

CREATE TABLE IF NOT EXISTS club_role_capability_grants (
    role_code       TEXT NOT NULL,
    capability_id   TEXT NOT NULL REFERENCES capabilities(id) ON DELETE CASCADE,
    PRIMARY KEY (role_code, capability_id)
);

CREATE INDEX IF NOT EXISTS idx_club_role_cap_grants_cap ON club_role_capability_grants(capability_id);

CREATE TABLE IF NOT EXISTS portal_role_capability_grants (
    portal_role     TEXT NOT NULL,
    capability_id   TEXT NOT NULL REFERENCES capabilities(id) ON DELETE CASCADE,
    PRIMARY KEY (portal_role, capability_id)
);

-- ── Seed: Capabilities (v1 Katalog §5) ───────────────────────────────────────
INSERT INTO capabilities (id, name, domain, min_account_state, linked_feature_id) VALUES
    ('account.settings.read', 'Einstellungen lesen', 'account', 'unverified', NULL),
    ('account.settings.update', 'Einstellungen ändern', 'account', 'unverified', NULL),
    ('account.password.change', 'Passwort ändern', 'account', 'unverified', NULL),
    ('account.resend_verification', 'Verifizierung erneut senden', 'account', 'unverified', NULL),
    ('club.directory.read', 'Vereinsverzeichnis', 'club', 'verified_pending_club', NULL),
    ('club.join_request.create', 'Vereinsbeitritt beantragen', 'club', 'verified_pending_club', NULL),
    ('club.join_request.withdraw', 'Beitrittsantrag zurückziehen', 'club', 'verified_pending_club', NULL),
    ('club.join_request.read_own', 'Eigene Beitrittsanträge', 'club', 'verified_pending_club', NULL),
    ('org.club.read', 'Vereine lesen', 'org', 'active_member', NULL),
    ('org.club.create', 'Verein anlegen', 'org', 'platform_admin', NULL),
    ('org.club.update', 'Verein bearbeiten', 'org', 'active_member', NULL),
    ('org.club.delete', 'Verein löschen', 'org', 'platform_admin', NULL),
    ('org.structure.manage', 'Vereinsstruktur verwalten', 'org', 'active_member', 'training_groups'),
    ('org.members.read', 'Mitgliederliste', 'org', 'active_member', NULL),
    ('org.members.manage', 'Mitglieder verwalten', 'org', 'active_member', 'active_members'),
    ('org.members.directory', 'Mitglieder-Verzeichnis', 'org', 'active_member', NULL),
    ('org.join_request.review', 'Beitrittsanträge prüfen', 'org', 'active_member', NULL),
    ('org.inbox.read', 'Posteingang', 'org', 'active_member', NULL),
    ('exercises.read', 'Übungen lesen', 'exercises', 'active_member', NULL),
    ('exercises.create', 'Übung anlegen', 'exercises', 'active_member', 'exercises'),
    ('exercises.update', 'Übung bearbeiten', 'exercises', 'active_member', NULL),
    ('exercises.delete', 'Übung löschen', 'exercises', 'active_member', NULL),
    ('exercises.bulk_metadata', 'Übungen Stapel-Metadaten', 'exercises', 'active_member', NULL),
    ('exercises.ai.suggest', 'KI-Vorschlag Übung', 'exercises', 'active_member', 'ai_calls'),
    ('exercises.ai.regenerate', 'KI neu generieren', 'exercises', 'active_member', 'ai_calls'),
    ('exercises.media.read', 'Übungsmedien lesen', 'exercises', 'active_member', NULL),
    ('exercises.media.upload', 'Übungsmedien hochladen', 'exercises', 'active_member', 'exercise_media'),
    ('exercises.variants.manage', 'Übungsvarianten', 'exercises', 'active_member', NULL),
    ('media.library.read', 'Medienbibliothek lesen', 'media', 'active_member', NULL),
    ('media.library.upload', 'Medienbibliothek Upload', 'media', 'active_member', 'exercise_media'),
    ('media.library.update', 'Medienbibliothek bearbeiten', 'media', 'active_member', NULL),
    ('media.library.lifecycle', 'Medien-Lifecycle', 'media', 'active_member', NULL),
    ('media.rights.declare', 'Medienrechte erklären', 'media', 'active_member', NULL),
    ('media.admin.rights_review', 'Medienrechte Review (Plattform)', 'media', 'platform_admin', NULL),
    ('modules.read', 'Trainingsmodule lesen', 'modules', 'active_member', NULL),
    ('modules.create', 'Trainingsmodul anlegen', 'modules', 'active_member', 'training_programs'),
    ('modules.update', 'Trainingsmodul bearbeiten', 'modules', 'active_member', NULL),
    ('modules.delete', 'Trainingsmodul löschen', 'modules', 'active_member', NULL),
    ('framework.read', 'Rahmenprogramme lesen', 'framework', 'active_member', NULL),
    ('framework.create', 'Rahmenprogramm anlegen', 'framework', 'active_member', 'training_programs'),
    ('framework.update', 'Rahmenprogramm bearbeiten', 'framework', 'active_member', NULL),
    ('framework.delete', 'Rahmenprogramm löschen', 'framework', 'active_member', NULL),
    ('plan_templates.read', 'Planungsvorlagen lesen', 'planning', 'active_member', NULL),
    ('plan_templates.manage', 'Planungsvorlagen verwalten', 'planning', 'active_member', NULL),
    ('progression.read', 'Progressionspfade lesen', 'progression', 'active_member', NULL),
    ('progression.manage', 'Progressionspfade verwalten', 'progression', 'active_member', NULL),
    ('planning.calendar.read', 'Planungskalender lesen', 'planning', 'active_member', NULL),
    ('planning.units.create', 'Trainingseinheit anlegen', 'planning', 'active_member', 'training_units'),
    ('planning.units.update', 'Trainingseinheit bearbeiten', 'planning', 'active_member', NULL),
    ('planning.units.delete', 'Trainingseinheit löschen', 'planning', 'active_member', NULL),
    ('planning.units.run', 'Training durchführen', 'planning', 'active_member', NULL),
    ('planning.coach.execute', 'Coach ausführen', 'planning', 'active_member', NULL),
    ('planning.ai.suggest', 'Planungs-KI Suggest', 'planning', 'active_member', 'ai_calls'),
    ('planning.ai.progression_path', 'Planungs-KI Progressionspfad', 'planning', 'active_member', 'ai_calls'),
    ('skills.catalog.read', 'Fähigkeitenkatalog', 'skills', 'active_member', NULL),
    ('skills.discovery.read', 'Fähigkeiten-Discovery', 'skills', 'active_member', NULL),
    ('skill_profiles.read', 'Skill-Profile lesen', 'skills', 'active_member', NULL),
    ('governance.content_report.create', 'Inhalt melden', 'governance', 'active_member', NULL),
    ('governance.content_report.review', 'Meldungen prüfen', 'governance', 'active_member', NULL),
    ('platform.admin.access', 'Plattform-Admin-Bereich', 'platform', 'platform_admin', NULL),
    ('platform.users.manage', 'Nutzer verwalten', 'platform', 'platform_admin', NULL),
    ('platform.catalogs.manage', 'Kataloge verwalten', 'platform', 'platform_admin', NULL),
    ('platform.maturity_models.manage', 'Reifegradmodelle', 'platform', 'platform_admin', NULL),
    ('platform.wiki_import.execute', 'Wiki-Import', 'platform', 'platform_admin', 'wiki_import'),
    ('platform.ai_prompts.manage', 'KI-Prompts verwalten', 'platform', 'platform_admin', NULL),
    ('platform.exercise_enrichment.execute', 'Übungs-Anreicherung KI', 'platform', 'platform_admin', 'ai_calls'),
    ('platform.user_content.moderate', 'Nutzer-Inhalte moderieren', 'platform', 'platform_admin', NULL),
    ('platform.legal_documents.manage', 'Rechtstexte verwalten', 'platform', 'platform_admin', NULL),
    ('platform.media_storage.manage', 'Medienspeicher verwalten', 'platform', 'platform_admin', NULL),
    ('platform.club_creation.approve', 'Vereinsgründung freigeben', 'platform', 'platform_admin', NULL)
ON CONFLICT (id) DO NOTHING;

-- ── Vereinsrollen-Grants (§6 — nur eingeschränkte Capabilities) ─────────────
-- Konvention: keine Grant-Zeile = alle aktiven Mitglieder (min_account_state reicht).

INSERT INTO club_role_capability_grants (role_code, capability_id)
SELECT r.role_code, c.cap_id
FROM (VALUES
    ('club_admin', 'org.structure.manage'),
    ('division_lead', 'org.structure.manage'),
    ('club_admin', 'org.members.manage'),
    ('club_admin', 'org.join_request.review'),
    ('club_admin', 'org.inbox.read'),
    ('club_admin', 'exercises.create'),
    ('trainer', 'exercises.create'),
    ('content_editor', 'exercises.create'),
    ('division_lead', 'exercises.create'),
    ('club_admin', 'exercises.update'),
    ('trainer', 'exercises.update'),
    ('content_editor', 'exercises.update'),
    ('division_lead', 'exercises.update'),
    ('club_admin', 'exercises.delete'),
    ('club_admin', 'exercises.bulk_metadata'),
    ('content_editor', 'exercises.bulk_metadata'),
    ('club_admin', 'exercises.ai.suggest'),
    ('trainer', 'exercises.ai.suggest'),
    ('content_editor', 'exercises.ai.suggest'),
    ('division_lead', 'exercises.ai.suggest'),
    ('club_admin', 'exercises.ai.regenerate'),
    ('trainer', 'exercises.ai.regenerate'),
    ('content_editor', 'exercises.ai.regenerate'),
    ('division_lead', 'exercises.ai.regenerate'),
    ('club_admin', 'exercises.media.upload'),
    ('trainer', 'exercises.media.upload'),
    ('content_editor', 'exercises.media.upload'),
    ('club_admin', 'exercises.variants.manage'),
    ('trainer', 'exercises.variants.manage'),
    ('content_editor', 'exercises.variants.manage'),
    ('club_admin', 'media.library.upload'),
    ('trainer', 'media.library.upload'),
    ('content_editor', 'media.library.upload'),
    ('club_admin', 'media.library.update'),
    ('trainer', 'media.library.update'),
    ('content_editor', 'media.library.update'),
    ('club_admin', 'media.library.lifecycle'),
    ('trainer', 'media.library.lifecycle'),
    ('club_admin', 'media.rights.declare'),
    ('trainer', 'media.rights.declare'),
    ('club_admin', 'modules.create'),
    ('trainer', 'modules.create'),
    ('content_editor', 'modules.create'),
    ('club_admin', 'modules.update'),
    ('trainer', 'modules.update'),
    ('content_editor', 'modules.update'),
    ('club_admin', 'modules.delete'),
    ('club_admin', 'framework.create'),
    ('trainer', 'framework.create'),
    ('club_admin', 'framework.update'),
    ('trainer', 'framework.update'),
    ('club_admin', 'framework.delete'),
    ('club_admin', 'plan_templates.manage'),
    ('trainer', 'plan_templates.manage'),
    ('club_admin', 'progression.manage'),
    ('trainer', 'progression.manage'),
    ('content_editor', 'progression.manage'),
    ('club_admin', 'planning.units.create'),
    ('trainer', 'planning.units.create'),
    ('division_lead', 'planning.units.create'),
    ('club_admin', 'planning.units.update'),
    ('trainer', 'planning.units.update'),
    ('division_lead', 'planning.units.update'),
    ('club_admin', 'planning.units.delete'),
    ('trainer', 'planning.units.delete'),
    ('club_admin', 'planning.units.run'),
    ('trainer', 'planning.units.run'),
    ('division_lead', 'planning.units.run'),
    ('club_admin', 'planning.coach.execute'),
    ('trainer', 'planning.coach.execute'),
    ('club_admin', 'planning.ai.suggest'),
    ('trainer', 'planning.ai.suggest'),
    ('division_lead', 'planning.ai.suggest'),
    ('club_admin', 'planning.ai.progression_path'),
    ('trainer', 'planning.ai.progression_path'),
    ('division_lead', 'planning.ai.progression_path'),
    ('club_admin', 'skills.discovery.read'),
    ('trainer', 'skills.discovery.read'),
    ('content_editor', 'skills.discovery.read'),
    ('club_admin', 'governance.content_report.review')
) AS r(role_code, cap_id)
JOIN capabilities c ON c.id = r.cap_id
ON CONFLICT DO NOTHING;

-- org.club.update: club_admin (zusätzlich zu platform_admin via Bypass)
INSERT INTO club_role_capability_grants (role_code, capability_id)
VALUES ('club_admin', 'org.club.update')
ON CONFLICT DO NOTHING;

-- ── Portal-Rollen ───────────────────────────────────────────────────────────
INSERT INTO portal_role_capability_grants (portal_role, capability_id)
SELECT 'admin', id FROM capabilities WHERE id = 'platform.admin.access'
ON CONFLICT DO NOTHING;

INSERT INTO portal_role_capability_grants (portal_role, capability_id)
SELECT 'superadmin', id FROM capabilities WHERE domain = 'platform'
ON CONFLICT DO NOTHING;
