-- Migration: add_mail_classification_sample
-- Neue Tabelle für ML-Phase 3: Klassifikations-Samples pro Mail-Analyse.
-- Speichert Features + Outcomes für zukünftiges Fine-Tuning und Modell-Evaluation.
--
-- DSGVO-Compliance:
--   - KEIN Mail-Body (Art. 9 Datenminimierung).
--   - subject + sender_name: kurzlebige Detection-Signale, kein narrativer Inhalt.
--     Werden mit Mail-Flush nach 24h in mail_blocked bereinigt — Samples bleiben
--     länger erhalten (Forschungszweck), sind aber auf Domain/Score-Features reduziert.
--   - Cascade-Delete bei User-Löschung: user_id referenziert profiles.id (Art. 17).
--     Da profiles kein FOREIGN KEY auf mail_classification_samples hat (userId als
--     losgelöste UUID), wird Cascade via RLS-Trigger oder bei Account-Lösch-Routine
--     sichergestellt (deleteAllMailConnections-Äquivalent für Samples).
--     Alternativ: manuelle DELETE in Account-Lösch-Endpoint (backend/server/api/...).
--     TODO: Account-Lösch-Flow prüfen ob Samples mitgelöscht werden.
--
-- Breaking-change status: NONE.
-- Neue Tabelle, kein Impact auf bestehende Queries.
--
-- Deploy: automatisch via GitHub Actions (pnpm prisma migrate deploy)

CREATE TABLE "rebreak"."mail_classification_samples" (
  "id"                   TEXT         NOT NULL,
  "user_id"              UUID         NOT NULL,
  "connection_id"        UUID,

  -- Raw features (Detection-Signale, keine PII über Inhalt)
  "sender_name"          VARCHAR(255),
  "sender_domain"        VARCHAR(255),
  "relay_decoded_domain" VARCHAR(255),
  "subject"              VARCHAR(998),  -- RFC 5322 max subject length

  -- Computed features (Score-Komponenten als JSON)
  "features"             JSONB        NOT NULL DEFAULT '{}',

  -- Outcome
  "final_action"         TEXT         NOT NULL,  -- "blocked" | "passed"
  "trigger_source"       TEXT         NOT NULL,  -- "domain" | "brand+random" | "score:NN" | "llm:0.XX" | "whitelist" | "no-signal"

  -- Groq verdict (NULL wenn Layer 4 nicht lief)
  "groq_is_gambling"     BOOLEAN,
  "groq_confidence"      DOUBLE PRECISION,
  "groq_reason"          TEXT,

  -- User-Feedback für späteres Active Learning (initiell NULL)
  "user_feedback"        TEXT,   -- NULL | "correct" | "false-positive" | "false-negative"
  "feedback_at"          TIMESTAMPTZ,

  "created_at"           TIMESTAMPTZ  NOT NULL DEFAULT NOW(),

  CONSTRAINT "mail_classification_samples_pkey" PRIMARY KEY ("id")
);

-- Kern-Indizes
CREATE INDEX "mail_classification_samples_user_idx"
  ON "rebreak"."mail_classification_samples" ("user_id");

CREATE INDEX "mail_classification_samples_created_idx"
  ON "rebreak"."mail_classification_samples" ("created_at");

-- Compound-Index für spätere Analyse-Queries
-- z.B. "alle false-positives der letzten 30 Tage" oder "LLM-Block-Rate"
CREATE INDEX "mail_classification_samples_action_trigger_idx"
  ON "rebreak"."mail_classification_samples" ("final_action", "trigger_source");

-- CHECK constraints für Datenqualität
ALTER TABLE "rebreak"."mail_classification_samples"
  ADD CONSTRAINT "mail_classification_samples_action_check"
    CHECK ("final_action" IN ('blocked', 'passed'));

-- Note: connection_id hat keinen FOREIGN KEY auf mail_connections, da die Connection
-- vor dem Sample gelöscht werden kann (z.B. User disconnect). Nullable + orphan-safe.
