-- OPENBUREAU CMS — posts-Tabelle. In den Supabase-Stack einspielen
-- (SQL-Editor oder psql). Spalten bilden das Hugo-Frontmatter ab.

create extension if not exists "pgcrypto";

create table if not exists public.posts (
  id           uuid primary key default gen_random_uuid(),
  section      text not null,            -- buerofuehrung | software | theorie
  slug         text not null,            -- a-z0-9- (Dateiname ohne .md)
  title        text not null,
  date         date not null default current_date,
  weight       int,
  tags         text[] default '{}',
  summary      text,
  cover_image  text,
  layout       text,                     -- z.B. "image" | "text"
  external     text,                     -- externer Link (wie RAPPORT)
  color        text,                     -- z.B. "kusa" | "yuyake"
  body         text default '',          -- Markdown-Inhalt
  status       text not null default 'draft',  -- draft | published
  author       text,
  created_at   timestamptz not null default now(),
  updated_at   timestamptz not null default now(),
  published_at timestamptz,
  unique (section, slug)
);

create index if not exists posts_status_idx on public.posts (status);
create index if not exists posts_section_idx on public.posts (section);

-- RLS aktivieren; die api nutzt den Service-Key (umgeht RLS). Wenn das
-- Frontend später direkt liest, hier gezielte Policies ergänzen.
alter table public.posts enable row level security;
revoke all on public.posts from anon, authenticated;

-- ── Dialog / Diskussionen ───────────────────────────────────────────────
-- Thread = Pfad des Beitrags (z.B. /library/software/stack/). Flache Wortmeldungen
-- mit optionalem Bezug (parent_id). Idempotent — auf bestehende DB anwendbar.
create table if not exists public.comments (
  id            uuid primary key default gen_random_uuid(),
  thread        text not null,
  parent_id     uuid references public.comments(id) on delete cascade,
  user_id       uuid,
  author_name   text,
  author_avatar text,
  body          text not null,
  created_at    timestamptz not null default now(),
  deleted       boolean not null default false
);
-- Position/Rolle bei OPENBUREAU (optional, neben dem Namen angezeigt).
alter table public.comments add column if not exists author_role text;
create index if not exists comments_thread_idx on public.comments (thread, created_at);
alter table public.comments enable row level security;
-- Nur die Node-API (service_role) greift auf die Tabellen zu; der Browser geht
-- ausschliesslich über /api/*. anon/authenticated bekommen KEINE Tabellenrechte,
-- damit das öffentlich erreichbare /rest/v1 auch bei künftigen RLS-Policies dicht
-- bleibt (Defense-in-Depth, nicht nur "RLS ohne Policy").
grant all on public.comments to service_role;
revoke all on public.comments from anon, authenticated;

-- Aggregat je Thread (Anzahl + letzte Aktivität). Spart der API den Full-Table-
-- Scan + JS-Aggregation bei jedem Forum-Aufruf; Postgres zählt direkt.
create or replace view public.comment_stats as
  select thread, count(*)::int as count, max(created_at) as last
  from public.comments
  where not deleted
  group by thread;
grant select on public.comment_stats to service_role;

-- ── Foren / Subforen ────────────────────────────────────────────────────
-- Kategorien, in denen Threads leben. Admin-verwaltet. `kind=library` ist die
-- Sonder-Kategorie, in der die Library-Beiträge automatisch als Threads landen.
create table if not exists public.forums (
  id          uuid primary key default gen_random_uuid(),
  slug        text not null unique,
  name        text not null,
  description text default '',
  color       text,                       -- optionale Akzentfarbe
  sort        int  not null default 0,
  kind        text not null default 'forum',  -- forum | library
  created_at  timestamptz not null default now()
);
alter table public.forums enable row level security;
grant all on public.forums to service_role;
revoke all on public.forums from anon, authenticated;

-- ── Threads (Diskussionen) ──────────────────────────────────────────────
-- key = stabiler Bezeichner, den comments.thread referenziert:
--   Forum-Thread     → 't/<uuid>'
--   Library-Beitrag  → Beitragspfad (z.B. /library/software/stack/)
create table if not exists public.threads (
  id          uuid primary key default gen_random_uuid(),
  forum_id    uuid references public.forums(id) on delete cascade,
  key         text not null unique,
  title       text not null,
  url         text,                       -- Ziel-Link (Library: Beitragspfad)
  kind        text not null default 'forum',  -- forum | library
  author_name text,
  user_id     uuid,
  locked      boolean not null default false,
  deleted     boolean not null default false,
  created_at  timestamptz not null default now()
);
create index if not exists threads_forum_idx on public.threads (forum_id);
alter table public.threads enable row level security;
grant all on public.threads to service_role;
revoke all on public.threads from anon, authenticated;

-- Seed-Kategorien (idempotent; im Admin umbenenn-/erweiterbar).
insert into public.forums (slug, name, sort, kind) values
  ('allgemein', 'Allgemein', 10, 'forum'),
  ('projekte',  'Projekte',  20, 'forum'),
  ('technik',   'Technik',   30, 'forum'),
  ('off-topic', 'Off-Topic', 40, 'forum')
on conflict (slug) do nothing;
-- Sonder-Kategorie für die Library-Beiträge.
insert into public.forums (slug, name, sort, kind) values
  ('beitraege', 'Beiträge', 0, 'library')
on conflict (slug) do nothing;
