-- =====================================================================
-- DOGFATHER UNIVERSE — Interner Bereich: Datenbankschema
-- Setzt "Geschuetzter_Zugang_Rollen_Benutzerverwaltung.pdf" um.
-- =====================================================================

-- Rollen: frei erstellbar/umbenennbar durch den Hauptadministrator (Owner).
-- Die Owner-Rolle selbst ist NICHT in dieser Tabelle — sie ist fest an das
-- POSTFACH_CODE-Secret gebunden und kann nicht gelöscht/verändert werden.
CREATE TABLE IF NOT EXISTS roles (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  permissions TEXT NOT NULL DEFAULT '[]', -- JSON-Array erlaubter Permission-Keys
  created_at TEXT NOT NULL
);

-- Zugänge/Teammitglieder. Jede Person hat einen eigenen Code.
-- code_hash: SHA-256 für schnellen Login-Vergleich (nicht umkehrbar).
-- code_enc:  AES-GCM verschlüsselter Klartext-Code, NUR vom Owner nach
--            Re-Auth entschlüsselbar (siehe crypto.js). Wird niemals an
--            andere Personen oder über die API an Nicht-Owner ausgegeben.
CREATE TABLE IF NOT EXISTS users (
  id TEXT PRIMARY KEY,
  name TEXT NOT NULL,
  username TEXT NOT NULL UNIQUE,
  email TEXT,
  role_id TEXT REFERENCES roles(id),
  code_hash TEXT,
  code_enc TEXT,
  status TEXT NOT NULL DEFAULT 'pending', -- pending | active | locked
  note TEXT,
  expires_at TEXT,                        -- NULL = dauerhaft
  created_at TEXT NOT NULL,
  created_by TEXT NOT NULL,
  last_login_at TEXT
);

-- Individuelle Berechtigungs-Ausnahmen pro Person (haben Vorrang vor der Rolle).
CREATE TABLE IF NOT EXISTS user_permission_overrides (
  user_id TEXT NOT NULL REFERENCES users(id),
  permission TEXT NOT NULL,
  allowed INTEGER NOT NULL, -- 1 = zusätzlich erlaubt, 0 = entzogen
  PRIMARY KEY (user_id, permission)
);

-- Sessions: token wird gehasht gespeichert (wie ein Passwort), nie im Klartext.
CREATE TABLE IF NOT EXISTS sessions (
  token_hash TEXT PRIMARY KEY,
  user_id TEXT NOT NULL,      -- 'owner' oder users.id
  is_owner INTEGER NOT NULL DEFAULT 0,
  created_at TEXT NOT NULL,
  last_active_at TEXT NOT NULL,
  expires_at TEXT NOT NULL
);

-- Aktivitätsprotokoll — Codes erscheinen hier NIEMALS im Klartext.
CREATE TABLE IF NOT EXISTS audit_log (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  actor TEXT NOT NULL,
  action TEXT NOT NULL,
  target TEXT,
  detail TEXT,
  created_at TEXT NOT NULL
);

-- Login-Schutz: Fehlversuche pro Schlüssel (IP oder Benutzername) zählen,
-- nach zu vielen Versuchen vorübergehend sperren.
CREATE TABLE IF NOT EXISTS login_attempts (
  key TEXT PRIMARY KEY,
  count INTEGER NOT NULL DEFAULT 0,
  locked_until TEXT,
  updated_at TEXT NOT NULL
);

-- Bewerbungen (bisher in KV, jetzt in D1 für Status/Zuweisung/Notizen/Entwürfe).
CREATE TABLE IF NOT EXISTS applications (
  id TEXT PRIMARY KEY,
  type TEXT NOT NULL,                    -- creator | scout | kooperation
  data TEXT NOT NULL,                    -- JSON der Formularfelder
  status TEXT NOT NULL DEFAULT 'neu',    -- neu | in_bearbeitung | beantwortet
  assigned_to TEXT,                      -- users.id oder 'owner'
  archived INTEGER NOT NULL DEFAULT 0,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS application_notes (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  application_id TEXT NOT NULL REFERENCES applications(id),
  author TEXT NOT NULL,
  text TEXT NOT NULL,
  created_at TEXT NOT NULL
);

CREATE TABLE IF NOT EXISTS application_drafts (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  application_id TEXT NOT NULL REFERENCES applications(id),
  author TEXT NOT NULL,
  content TEXT NOT NULL,
  created_at TEXT NOT NULL,
  updated_at TEXT NOT NULL
);

CREATE INDEX IF NOT EXISTS idx_sessions_user ON sessions(user_id);
CREATE INDEX IF NOT EXISTS idx_audit_created ON audit_log(created_at);
CREATE INDEX IF NOT EXISTS idx_applications_status ON applications(status, archived);
CREATE INDEX IF NOT EXISTS idx_notes_app ON application_notes(application_id);
CREATE INDEX IF NOT EXISTS idx_drafts_app ON application_drafts(application_id);
