"use client";

import { useMemo, useRef, useState } from "react";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { toPng } from "html-to-image";
import {
  AlertTriangle,
  Archive,
  BellPlus,
  Bot,
  CalendarClock,
  CheckCircle2,
  ClipboardCheck,
  Copy,
  Download,
  Eye,
  FileCheck2,
  FileText,
  FolderOpen,
  GitCompareArrows,
  HeartPulse,
  History,
  KeyRound,
  LifeBuoy,
  LockKeyhole,
  ReceiptText,
  ScanLine,
  Search,
  Send,
  ShieldCheck,
  ShieldAlert,
  Sparkles,
  UploadCloud,
  WandSparkles,
} from "lucide-react";
import { FilePreviewModal } from "@/components/attachments/file-preview-modal";
import { FileThumbnail } from "@/components/attachments/file-thumbnail";
import { ShareToChatModal, type ChatSharePayload } from "@/components/chat/share-to-chat-modal";
import { Skeleton } from "@/components/ui/skeleton";
import { useDocuments, type DocumentItem } from "@/hooks/use-documents";
import { useNotes } from "@/hooks/use-notes";
import { useReminders } from "@/hooks/use-reminders";
import { useTasks } from "@/hooks/use-tasks";
import { formatFileSize, getFileKind, isPreviewableFile } from "@/lib/file-utils";
import { cn, formatRelativeDate } from "@/lib/utils";

type VaultArea =
  | "all"
  | "attention"
  | "contracts"
  | "finance"
  | "identity"
  | "tax"
  | "health"
  | "projects"
  | "safe";

type VaultTone = "amber" | "cyan" | "emerald" | "rose" | "violet";

interface VaultIntel {
  area: Exclude<VaultArea, "all" | "attention">;
  actionRequired: boolean;
  actionLabel: string;
  confidence: number;
  fields: Array<{ label: string; value: string }>;
  tone: VaultTone;
}

interface VaultObligation {
  id: string;
  document: DocumentItem;
  label: string;
  description: string;
  severity: "high" | "medium" | "low";
  suggestedDays: number;
  tone: VaultTone;
}

interface VaultChecklistItem {
  id: VaultArea;
  title: string;
  description: string;
  count: number;
  ready: boolean;
  icon: React.ComponentType<{ className?: string }>;
}

interface VaultVersionGroup {
  key: string;
  label: string;
  documents: DocumentItem[];
}

interface VaultTimelineItem {
  id: string;
  title: string;
  subtitle: string;
  timestamp: string;
  tone: VaultTone;
  icon: React.ComponentType<{ className?: string }>;
}

const AREAS: Array<{
  id: VaultArea;
  label: string;
  description: string;
  icon: React.ComponentType<{ className?: string }>;
}> = [
  { id: "all", label: "All", description: "Everything in the vault", icon: ShieldCheck },
  { id: "attention", label: "Needs Attention", description: "Deadlines, payments, renewals", icon: AlertTriangle },
  { id: "contracts", label: "Contracts", description: "Agreements and terms", icon: FileCheck2 },
  { id: "finance", label: "Finance", description: "Invoices and receipts", icon: ReceiptText },
  { id: "identity", label: "Identity", description: "IDs and certificates", icon: LockKeyhole },
  { id: "tax", label: "Tax", description: "Taxes and official docs", icon: CalendarClock },
  { id: "health", label: "Health", description: "Medical and insurance", icon: ShieldCheck },
  { id: "projects", label: "Projects", description: "Project evidence and assets", icon: FolderOpen },
  { id: "safe", label: "Emergency", description: "Critical life-admin files", icon: LifeBuoy },
];

const TONE_CLASSES: Record<VaultTone, string> = {
  amber: "border-white/[0.06] bg-amber-500/[0.07] text-amber-200",
  cyan: "border-white/[0.06] bg-sky-500/[0.07] text-sky-200",
  emerald: "border-white/[0.06] bg-emerald-500/[0.07] text-emerald-200",
  rose: "border-white/[0.06] bg-rose-500/[0.07] text-rose-200",
  violet: "border-white/[0.06] bg-violet-500/[0.07] text-violet-200",
};

function createVaultNoteContent(text: string) {
  return {
    type: "doc",
    content: [
      {
        type: "paragraph",
        content: [{ type: "text", text }],
      },
    ],
  };
}

function aiPromptHref(prompt: string) {
  return `/ai?prompt=${encodeURIComponent(prompt)}`;
}

function includesAny(value: string, words: string[]) {
  return words.some((word) => value.includes(word));
}

function classifyDocument(document: DocumentItem): VaultIntel {
  const haystack = `${document.file_name} ${document.entityTitle} ${document.entityLabel}`.toLowerCase();
  const kind = getFileKind(document.mime_type, document.file_name);

  let area: VaultIntel["area"] = "projects";
  let tone: VaultTone = "cyan";
  let confidence = 58;
  let actionLabel = "Review context";

  if (includesAny(haystack, ["vertrag", "contract", "agreement", "kündigung", "kuendigung", "lease", "miete"])) {
    area = "contracts";
    tone = "amber";
    confidence = 86;
    actionLabel = "Check term / deadline";
  } else if (includesAny(haystack, ["rechnung", "invoice", "receipt", "quittung", "beleg", "payment", "zahlung"])) {
    area = "finance";
    tone = "emerald";
    confidence = 84;
    actionLabel = "Check payment";
  } else if (includesAny(haystack, ["ausweis", "passport", "id", "zertifikat", "certificate", "license", "lizenz"])) {
    area = "identity";
    tone = "violet";
    confidence = 82;
    actionLabel = "Keep safe copy";
  } else if (includesAny(haystack, ["steuer", "tax", "finanzamt", "elster", "bescheid"])) {
    area = "tax";
    tone = "amber";
    confidence = 84;
    actionLabel = "Check filing date";
  } else if (includesAny(haystack, ["medical", "arzt", "health", "versicherung", "insurance", "krank", "patient"])) {
    area = "health";
    tone = "rose";
    confidence = 80;
    actionLabel = "Check follow-up";
  } else if (document.entity_type === "project") {
    area = "projects";
    confidence = 74;
    actionLabel = "Attach to project spine";
  } else if (kind === "pdf") {
    area = "contracts";
    tone = "amber";
    confidence = 62;
    actionLabel = "Extract key facts";
  }

  const actionRequired =
    area === "contracts" ||
    area === "finance" ||
    area === "tax" ||
    includesAny(haystack, ["deadline", "due", "fällig", "faellig", "renew", "läuft", "laeuft", "expires", "zahlung"]);

  return {
    area,
    actionRequired,
    actionLabel: actionRequired ? actionLabel : "Filed",
    confidence,
    fields: [
      { label: "Type", value: kind.toUpperCase() },
      { label: "Source", value: document.entityLabel },
      { label: "Size", value: formatFileSize(document.size_bytes) },
      { label: "Added", value: formatRelativeDate(document.created_at) },
    ],
    tone,
  };
}

function sortVaultDocuments(documents: DocumentItem[]) {
  return [...documents].sort((a, b) => {
    const ai = classifyDocument(a);
    const bi = classifyDocument(b);
    if (ai.actionRequired !== bi.actionRequired) return ai.actionRequired ? -1 : 1;
    return new Date(b.created_at).getTime() - new Date(a.created_at).getTime();
  });
}

function getDocumentHaystack(document: DocumentItem) {
  return `${document.file_name} ${document.entityTitle} ${document.entityLabel}`.toLowerCase();
}

function isEmergencyDocument(document: DocumentItem, intel = classifyDocument(document)) {
  const haystack = getDocumentHaystack(document);
  return (
    intel.area === "identity" ||
    intel.area === "health" ||
    includesAny(haystack, [
      "notfall",
      "emergency",
      "passport",
      "ausweis",
      "birth",
      "geburts",
      "insurance",
      "versicherung",
      "vollmacht",
      "power of attorney",
      "medical",
    ])
  );
}

function buildObligation(document: DocumentItem, intel = classifyDocument(document)): VaultObligation | null {
  const haystack = getDocumentHaystack(document);
  const isExpiryLike = includesAny(haystack, [
    "expires",
    "ablauf",
    "läuft",
    "laeuft",
    "renew",
    "verlängerung",
    "verlaengerung",
    "kündigung",
    "kuendigung",
    "deadline",
    "fällig",
    "faellig",
    "due",
  ]);
  const isPaymentLike = includesAny(haystack, ["rechnung", "invoice", "payment", "zahlung", "beleg", "receipt"]);

  if (!intel.actionRequired && !isExpiryLike && !isPaymentLike && !isEmergencyDocument(document, intel)) {
    return null;
  }

  const suggestedDays =
    intel.area === "finance" || isPaymentLike
      ? 3
      : intel.area === "tax" || isExpiryLike
        ? 7
        : isEmergencyDocument(document, intel)
          ? 30
          : 14;

  const severity: VaultObligation["severity"] =
    suggestedDays <= 7 ? "high" : suggestedDays <= 14 ? "medium" : "low";

  const label =
    intel.area === "finance" || isPaymentLike
      ? "Zahlung / Beleg prüfen"
      : intel.area === "tax"
        ? "Steuerfrist prüfen"
        : isExpiryLike
          ? "Ablauf / Verlängerung prüfen"
          : isEmergencyDocument(document, intel)
            ? "Emergency Copy sichern"
            : intel.actionLabel;

  return {
    id: document.id,
    document,
    label,
    description: `${document.file_name} aus ${document.entityLabel} "${document.entityTitle}"`,
    severity,
    suggestedDays,
    tone: severity === "high" ? "amber" : severity === "medium" ? "violet" : "cyan",
  };
}

function buildVaultObligations(documents: DocumentItem[], intelligence: Map<string, VaultIntel>) {
  return documents
    .map((document) => buildObligation(document, intelligence.get(document.id)))
    .filter(Boolean)
    .sort((left, right) => {
      const severityRank = { high: 0, medium: 1, low: 2 };
      return severityRank[left!.severity] - severityRank[right!.severity];
    }) as VaultObligation[];
}

function buildLifeAdminChecklist(documents: DocumentItem[], intelligence: Map<string, VaultIntel>): VaultChecklistItem[] {
  const countArea = (area: VaultIntel["area"]) =>
    documents.filter((document) => intelligence.get(document.id)?.area === area).length;
  const emergencyCount = documents.filter((document) => isEmergencyDocument(document, intelligence.get(document.id))).length;

  return [
    {
      id: "identity",
      title: "Identity",
      description: "Ausweis, Passport, Zertifikate",
      count: countArea("identity"),
      ready: countArea("identity") > 0,
      icon: KeyRound,
    },
    {
      id: "finance",
      title: "Finance",
      description: "Rechnungen, Belege, Zahlungen",
      count: countArea("finance"),
      ready: countArea("finance") > 0,
      icon: ReceiptText,
    },
    {
      id: "tax",
      title: "Tax",
      description: "Finanzamt, Steuer, Bescheide",
      count: countArea("tax"),
      ready: countArea("tax") > 0,
      icon: CalendarClock,
    },
    {
      id: "contracts",
      title: "Contracts",
      description: "Verträge, Kündigung, Laufzeiten",
      count: countArea("contracts"),
      ready: countArea("contracts") > 0,
      icon: FileCheck2,
    },
    {
      id: "health",
      title: "Health",
      description: "Versicherung, Arzt, Medizinisches",
      count: countArea("health"),
      ready: countArea("health") > 0,
      icon: HeartPulse,
    },
    {
      id: "safe",
      title: "Emergency",
      description: "Notfall-Set mit wichtigsten Kopien",
      count: emergencyCount,
      ready: emergencyCount >= 2,
      icon: LifeBuoy,
    },
  ];
}

function normalizeVersionKey(fileName: string) {
  return fileName
    .replace(/\.[a-z0-9]+$/i, "")
    .toLowerCase()
    .replace(/\b(20\d{2}[-_. ]?\d{1,2}[-_. ]?\d{1,2}|\d{1,2}[-_. ]?\d{1,2}[-_. ]?20\d{2})\b/g, "")
    .replace(/\b(v|version|final|draft|copy|kopie|neu|old|alt)[-_. ]*\d*\b/g, "")
    .replace(/[-_.()[\]]+/g, " ")
    .replace(/\s+/g, " ")
    .trim();
}

function buildVersionGroups(documents: DocumentItem[]): VaultVersionGroup[] {
  const groups = new Map<string, DocumentItem[]>();
  documents.forEach((document) => {
    const key = normalizeVersionKey(document.file_name);
    if (!key) return;
    groups.set(key, [...(groups.get(key) || []), document]);
  });

  return Array.from(groups.entries())
    .map(([key, items]) => ({
      key,
      label: key.replace(/\b\w/g, (letter) => letter.toUpperCase()),
      documents: [...items].sort((left, right) => new Date(right.created_at).getTime() - new Date(left.created_at).getTime()),
    }))
    .filter((group) => group.documents.length > 1)
    .sort((left, right) => right.documents.length - left.documents.length);
}

function buildVaultTimeline(documents: DocumentItem[], intelligence: Map<string, VaultIntel>): VaultTimelineItem[] {
  return [...documents]
    .sort((left, right) => new Date(right.created_at).getTime() - new Date(left.created_at).getTime())
    .slice(0, 8)
    .map((document) => {
      const intel = intelligence.get(document.id) || classifyDocument(document);
      return {
        id: document.id,
        title: document.file_name,
        subtitle: `${document.entityLabel} · ${document.entityTitle} · ${intel.area}`,
        timestamp: document.created_at,
        tone: intel.tone,
        icon: intel.actionRequired ? ShieldAlert : Archive,
      };
    });
}

function buildVaultContext(documents: DocumentItem[], intelligence: Map<string, VaultIntel>, limit = 12) {
  if (documents.length === 0) return "Vault is empty.";

  return sortVaultDocuments(documents)
    .slice(0, limit)
    .map((document, index) => {
      const intel = intelligence.get(document.id) || classifyDocument(document);
      return `${index + 1}. ${document.file_name} | area=${intel.area} | action=${intel.actionLabel} | source=${document.entityLabel}: ${document.entityTitle}`;
    })
    .join("\n");
}

function buildPrivateShareCapsule(document: DocumentItem, intel: VaultIntel) {
  return [
    "Mindavio Vault Capsule",
    `Document: ${document.file_name}`,
    `Category: ${intel.area}`,
    `Status: ${intel.actionLabel}`,
    `Source: ${document.entityLabel} - ${document.entityTitle}`,
    `Size: ${formatFileSize(document.size_bytes)}`,
    `Added: ${formatRelativeDate(document.created_at)}`,
    `File: ${document.public_url}`,
  ].join("\n");
}

function dataUrlToFile(dataUrl: string, fileName: string) {
  const [header, base64] = dataUrl.split(",");
  const mime = header.match(/:(.*?);/)?.[1] || "image/png";
  const binary = window.atob(base64);
  const bytes = new Uint8Array(binary.length);
  for (let index = 0; index < binary.length; index += 1) {
    bytes[index] = binary.charCodeAt(index);
  }
  return new File([bytes], fileName, { type: mime });
}

function downloadFile(file: File) {
  const url = URL.createObjectURL(file);
  const link = document.createElement("a");
  link.href = url;
  link.download = file.name;
  link.click();
  URL.revokeObjectURL(url);
}

export default function VaultPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const inputRef = useRef<HTMLInputElement>(null);
  const reviewCardRef = useRef<HTMLDivElement>(null);
  const [now] = useState(() => Date.now());
  const { documents, loading, refetch } = useDocuments();
  const { createNote, updateNote } = useNotes();
  const { createReminder } = useReminders();
  const { createTask } = useTasks();
  const [activeArea, setActiveArea] = useState<VaultArea>("attention");
  const [query, setQuery] = useState("");
  const [askQuery, setAskQuery] = useState("");
  const [taskTitle, setTaskTitle] = useState(searchParams.get("title") || "");
  const [taskDescription, setTaskDescription] = useState(searchParams.get("url") || "");
  const [noteTitle, setNoteTitle] = useState(searchParams.get("title") || "Vault capture");
  const [noteBody, setNoteBody] = useState(searchParams.get("url") || "");
  const [scanFiles, setScanFiles] = useState<File[]>([]);
  const [uploading, setUploading] = useState(false);
  const [capturing, setCapturing] = useState<"task" | "note" | null>(null);
  const [feedback, setFeedback] = useState<string | null>(null);
  const [actioning, setActioning] = useState<"task" | "reminder" | "capsule" | "review" | null>(null);
  const [shareToChatOpen, setShareToChatOpen] = useState(false);
  const [selectedId, setSelectedId] = useState<string | null>(null);
  const [previewing, setPreviewing] = useState<DocumentItem | null>(null);

  const intelligence = useMemo(
    () => new Map(documents.map((document) => [document.id, classifyDocument(document)])),
    [documents],
  );

  const attentionDocs = useMemo(
    () => documents.filter((document) => intelligence.get(document.id)?.actionRequired),
    [documents, intelligence],
  );

  const obligations = useMemo(
    () => buildVaultObligations(documents, intelligence),
    [documents, intelligence],
  );

  const emergencyDocs = useMemo(
    () => documents.filter((document) => isEmergencyDocument(document, intelligence.get(document.id))),
    [documents, intelligence],
  );

  const checklist = useMemo(
    () => buildLifeAdminChecklist(documents, intelligence),
    [documents, intelligence],
  );

  const versionGroups = useMemo(() => buildVersionGroups(documents), [documents]);

  const timeline = useMemo(
    () => buildVaultTimeline(documents, intelligence),
    [documents, intelligence],
  );

  const filteredDocuments = useMemo(() => {
    const normalized = query.trim().toLowerCase();
    return sortVaultDocuments(documents).filter((document) => {
      const intel = intelligence.get(document.id);
      if (!intel) return false;
      if (activeArea === "attention" && !intel.actionRequired) return false;
      if (activeArea === "safe" && !isEmergencyDocument(document, intel)) return false;
      if (activeArea !== "all" && activeArea !== "attention" && activeArea !== "safe" && intel.area !== activeArea) return false;

      if (!normalized) return true;
      return [document.file_name, document.entityTitle, document.entityLabel, intel.area]
        .join(" ")
        .toLowerCase()
        .includes(normalized);
    });
  }, [activeArea, documents, intelligence, query]);

  const selectedDocument =
    filteredDocuments.find((document) => document.id === selectedId) ||
    attentionDocs[0] ||
    filteredDocuments[0] ||
    documents[0] ||
    null;
  const selectedIntel = selectedDocument ? intelligence.get(selectedDocument.id) || classifyDocument(selectedDocument) : null;
  const selectedObligation = selectedDocument && selectedIntel ? buildObligation(selectedDocument, selectedIntel) : null;
  const selectedVersionGroup = selectedDocument
    ? versionGroups.find((group) => group.documents.some((document) => document.id === selectedDocument.id)) || null
    : null;
  const vaultReadiness = checklist.length
    ? Math.round((checklist.filter((item) => item.ready).length / checklist.length) * 100)
    : 0;

  const stats = useMemo(() => {
    const pdfs = documents.filter((document) => getFileKind(document.mime_type, document.file_name) === "pdf").length;
    const recent = documents.filter((document) => new Date(document.created_at).getTime() >= now - 7 * 24 * 60 * 60 * 1000).length;
    return {
      total: documents.length,
      attention: attentionDocs.length,
      obligations: obligations.length,
      pdfs,
      recent,
      safe: emergencyDocs.length,
    };
  }, [attentionDocs.length, documents, emergencyDocs.length, now, obligations.length]);

  async function handleImportScans() {
    if (scanFiles.length === 0 || uploading) return;
    setUploading(true);
    setFeedback(null);
    try {
      const title =
        scanFiles.length === 1
          ? `Vault Scan · ${scanFiles[0].name}`
          : `Vault Scan Bundle · ${new Date().toLocaleString("de-DE")}`;
      const note = await createNote({ title });
      await updateNote(note.id, {
        content: createVaultNoteContent("Imported through Vault Center. Use AI Sort to extract deadlines, payments, parties, and next actions."),
      });

      for (const file of scanFiles) {
        const formData = new FormData();
        formData.append("file", file, file.name);
        formData.append("entityType", "note");
        formData.append("entityId", note.id);
        const res = await fetch("/api/attachments", {
          method: "POST",
          body: formData,
        });

        if (!res.ok) {
          const data = await res.json().catch(() => ({}));
          throw new Error(typeof data.error === "string" ? data.error : "Vault scan upload failed.");
        }
      }

      setScanFiles([]);
      setFeedback("Scan imported as a vault note with attachments.");
      await refetch();
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Vault scan failed.");
    } finally {
      setUploading(false);
    }
  }

  async function handleCreateTask() {
    if (!taskTitle.trim() || capturing) return;
    setCapturing("task");
    setFeedback(null);
    try {
      const task = await createTask({
        title: taskTitle.trim(),
        description: taskDescription.trim() || undefined,
        priority: "none",
        status: "todo",
      });
      setTaskTitle("");
      setTaskDescription("");
      setFeedback("Captured as task.");
      router.push(`/tasks?task=${task.id}`);
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Task capture failed.");
    } finally {
      setCapturing(null);
    }
  }

  async function handleCreateNote() {
    if (!noteTitle.trim() || capturing) return;
    setCapturing("note");
    setFeedback(null);
    try {
      const note = await createNote({ title: noteTitle.trim() });
      if (noteBody.trim()) {
        await updateNote(note.id, {
          content: createVaultNoteContent(noteBody),
        });
      }
      setNoteTitle("Vault capture");
      setNoteBody("");
      setFeedback("Captured as note.");
      router.push(`/notes/${note.id}`);
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Note capture failed.");
    } finally {
      setCapturing(null);
    }
  }

  function handleAskAi() {
    const prompt = selectedDocument
      ? `Analyze this vault document: "${selectedDocument.file_name}" from ${selectedDocument.entityLabel} "${selectedDocument.entityTitle}". Classify it, extract possible deadlines, payments, parties, renewal dates, risks, and suggest tasks/reminders. Ask for Go before changing anything.`
      : "Act as my Mindavio Document Brain. Review my Vault Center and tell me which documents need attention, which are missing metadata, and what reminders/tasks should be created. Ask for Go before changing anything.";
    router.push(aiPromptHref(prompt));
  }

  function handleAskVault(question?: string) {
    const resolvedQuestion = question || askQuery.trim() || "Welche Dokumente brauchen gerade meine Aufmerksamkeit?";
    const prompt = [
      "Act as my Mindavio Vault Brain.",
      "Use this Vault snapshot and answer with practical next actions. If you suggest creating tasks/reminders, ask for Go before changing anything.",
      "",
      `Question: ${resolvedQuestion}`,
      "",
      "Vault snapshot:",
      buildVaultContext(documents, intelligence),
    ].join("\n");

    router.push(aiPromptHref(prompt));
  }

  async function handleCreateDocumentTask(document = selectedDocument, intel = selectedIntel) {
    if (!document || !intel || actioning) return;
    setActioning("task");
    setFeedback(null);
    try {
      const task = await createTask({
        title: `Vault: ${intel.actionLabel} · ${document.file_name}`,
        description: [
          `Document: ${document.file_name}`,
          `Source: ${document.entityLabel} · ${document.entityTitle}`,
          `Category: ${intel.area}`,
          `File: ${document.public_url}`,
        ].join("\n"),
        priority: intel.actionRequired ? "high" : "medium",
        status: "todo",
      });
      setFeedback("Document-to-Action: Task created.");
      router.push(`/tasks?task=${task.id}`);
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Could not create task.");
    } finally {
      setActioning(null);
    }
  }

  async function handleCreateDocumentReminder(days?: number, document = selectedDocument, intel = selectedIntel) {
    if (!document || !intel || actioning) return;
    const resolvedDays = days || buildObligation(document, intel)?.suggestedDays || 7;
    setActioning("reminder");
    setFeedback(null);
    try {
      await createReminder({
        title: `Vault prüfen: ${document.file_name}`,
        body: [
          intel.actionLabel,
          `Source: ${document.entityLabel} · ${document.entityTitle}`,
          `File: ${document.public_url}`,
        ].join("\n"),
        remind_at: new Date(Date.now() + resolvedDays * 24 * 60 * 60 * 1000).toISOString(),
        source_id: document.entity_id,
        source_title: document.file_name,
        source_type: document.entity_type,
        source_url: document.public_url,
      });
      setFeedback(`Reminder set for ${resolvedDays} day${resolvedDays === 1 ? "" : "s"}.`);
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Could not create reminder.");
    } finally {
      setActioning(null);
    }
  }

  async function handleCopyCapsule() {
    if (!selectedDocument || !selectedIntel || actioning) return;
    setActioning("capsule");
    setFeedback(null);
    try {
      await navigator.clipboard.writeText(buildPrivateShareCapsule(selectedDocument, selectedIntel));
      setFeedback("Private share capsule copied.");
    } catch {
      setFeedback("Could not copy capsule.");
    } finally {
      setActioning(null);
    }
  }

  async function buildVaultReviewFile(): Promise<File> {
    if (!reviewCardRef.current) {
      throw new Error("Vault review card is not ready yet.");
    }

    const dataUrl = await toPng(reviewCardRef.current, {
      cacheBust: true,
      pixelRatio: 2,
      backgroundColor: "#0a0a0d",
    });
    return dataUrlToFile(dataUrl, `mindavio-vault-review-${new Date().toISOString().slice(0, 10)}.png`);
  }

  async function handleExportVaultReview() {
    if (actioning) return;
    setActioning("review");
    setFeedback(null);
    try {
      downloadFile(await buildVaultReviewFile());
      setFeedback("Vault review card exported.");
    } catch (error) {
      setFeedback(error instanceof Error ? error.message : "Could not export review card.");
    } finally {
      setActioning(null);
    }
  }

  async function buildVaultSharePayload(): Promise<ChatSharePayload> {
    const file = await buildVaultReviewFile();
    return {
      files: [file],
      message: "Mein Mindavio Vault Review.",
    };
  }

  return (
    <div className="min-h-full bg-[#0a0a0d] text-white">
      <input
        ref={inputRef}
        type="file"
        multiple
        accept="image/*,.pdf,.png,.jpg,.jpeg,.webp,.heic"
        className="hidden"
        onChange={(event) => setScanFiles(Array.from(event.target.files || []))}
      />

      <div className="mx-auto max-w-[1280px] px-6 pt-8">
        <div className="relative overflow-hidden rounded-[28px] border border-white/[0.07] bg-[#0e0c15]">
          <div className="pointer-events-none absolute inset-0">
            <div
              className="absolute -left-[10%] -top-[40%] h-[500px] w-[500px] rounded-full opacity-[0.18] blur-3xl"
              style={{ background: "radial-gradient(circle, #0ea5e9, transparent 70%)" }}
            />
            <div
              className="absolute right-[10%] top-[18%] h-[320px] w-[320px] rounded-full opacity-12 blur-3xl"
              style={{ background: "radial-gradient(circle, #7c3aed, transparent 70%)" }}
            />
          </div>

          <div className="relative px-6 py-10 sm:px-8">
          <div className="flex flex-col gap-8 lg:flex-row lg:items-start lg:justify-between">
            <div className="max-w-2xl">
              <div className="mb-5 flex items-center gap-3">
                <div className="flex h-11 w-11 items-center justify-center rounded-[16px] bg-sky-500/15 ring-1 ring-sky-500/20">
                  <ShieldCheck className="h-5 w-5 text-sky-300" />
                </div>
                <div>
                  <p className="text-[10px] font-bold uppercase tracking-[0.22em] text-sky-300/60">
                    Vault Center
                  </p>
                </div>
              </div>

              <h1 className="text-[34px] font-bold leading-tight tracking-tight text-white">
                Dokumente nicht nur speichern.
                <span className="block text-white/40">Verantwortung daraus machen.</span>
              </h1>
              <p className="mt-4 max-w-2xl text-[14px] leading-relaxed text-white/45">
                Scan, sortiere, öffne und prüfe deine wichtigsten Dokumente. Vault Center bündelt Dateien,
                Fristen, Zahlungen, Safe Copies und nächste Aktionen in einer ruhigen Kommandoansicht.
              </p>

              <div className="mt-6 flex flex-wrap gap-2">
                <VaultPill>Ask My Vault</VaultPill>
                <VaultPill>Expiry Radar</VaultPill>
                <VaultPill>Document-to-Action</VaultPill>
                <VaultPill>Emergency Folder</VaultPill>
              </div>
            </div>

            <div className="w-full rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5 shadow-[0_24px_80px_rgba(0,0,0,0.30)] lg:max-w-[460px]">
              <div className="flex items-center justify-between gap-3">
                <div>
                  <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-sky-300/55">Scan Intake</p>
                  <h2 className="mt-1 text-[18px] font-bold tracking-tight text-white">Capture, Scan & Sort</h2>
                </div>
                <ScanLine className="h-5 w-5 text-sky-300/70" />
              </div>

              <div className="mt-5 grid gap-3">
                <div className="grid gap-3 sm:grid-cols-2">
                  <div className="rounded-2xl border border-white/[0.06] bg-white/[0.025] p-3">
                    <p className="text-[10px] font-bold uppercase tracking-[0.15em] text-white/25">Quick Task</p>
                    <input
                      value={taskTitle}
                      onChange={(event) => setTaskTitle(event.target.value)}
                      placeholder="Task title..."
                      className="mt-2 h-9 w-full rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 text-[12px] text-white outline-none placeholder:text-white/20 focus:border-sky-500/30"
                    />
                    <textarea
                      value={taskDescription}
                      onChange={(event) => setTaskDescription(event.target.value)}
                      placeholder="Optional context..."
                      rows={2}
                      className="mt-2 w-full resize-none rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 py-2 text-[12px] text-white outline-none placeholder:text-white/20 focus:border-sky-500/30"
                    />
                    <button
                      type="button"
                      onClick={() => void handleCreateTask()}
                      disabled={!taskTitle.trim() || capturing === "task"}
                      className="mt-2 w-full rounded-xl border border-sky-500/15 bg-sky-500/[0.08] px-3 py-2 text-[12px] font-bold text-sky-100/75 transition hover:bg-sky-500/[0.12] disabled:opacity-40"
                    >
                      {capturing === "task" ? "Capturing..." : "Als Task speichern"}
                    </button>
                  </div>

                  <div className="rounded-2xl border border-white/[0.06] bg-white/[0.025] p-3">
                    <p className="text-[10px] font-bold uppercase tracking-[0.15em] text-white/25">Quick Note / Link</p>
                    <input
                      value={noteTitle}
                      onChange={(event) => setNoteTitle(event.target.value)}
                      placeholder="Note title..."
                      className="mt-2 h-9 w-full rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 text-[12px] text-white outline-none placeholder:text-white/20 focus:border-violet-500/30"
                    />
                    <textarea
                      value={noteBody}
                      onChange={(event) => setNoteBody(event.target.value)}
                      placeholder="Paste note, link, thought..."
                      rows={2}
                      className="mt-2 w-full resize-none rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 py-2 text-[12px] text-white outline-none placeholder:text-white/20 focus:border-violet-500/30"
                    />
                    <button
                      type="button"
                      onClick={() => void handleCreateNote()}
                      disabled={!noteTitle.trim() || capturing === "note"}
                      className="mt-2 w-full rounded-xl border border-violet-500/18 bg-violet-500/[0.08] px-3 py-2 text-[12px] font-bold text-violet-100/75 transition hover:bg-violet-500/[0.12] disabled:opacity-40"
                    >
                      {capturing === "note" ? "Capturing..." : "Als Note speichern"}
                    </button>
                  </div>
                </div>

                <button
                  type="button"
                  onClick={() => inputRef.current?.click()}
                  className="flex items-center justify-center gap-2 rounded-2xl border border-sky-500/18 bg-sky-500/[0.08] px-4 py-4 text-[13px] font-bold text-sky-100 transition hover:bg-sky-500/[0.13]"
                >
                  <UploadCloud className="h-4 w-4" />
                  Dateien scannen / hochladen
                </button>

                {scanFiles.length > 0 && (
                  <div className="rounded-2xl border border-violet-500/16 bg-violet-500/[0.045] p-3">
                    <p className="text-[11px] font-bold uppercase tracking-[0.14em] text-violet-200/60">
                      Scan Queue
                    </p>
                    <div className="mt-2 space-y-1.5">
                      {scanFiles.map((file) => (
                        <div key={`${file.name}-${file.size}`} className="flex items-center justify-between gap-3 text-[12px] text-white/55">
                          <span className="truncate">{file.name}</span>
                          <span className="shrink-0 text-white/28">{formatFileSize(file.size)}</span>
                        </div>
                      ))}
                    </div>
                    <button
                      type="button"
                      onClick={() => void handleImportScans()}
                      disabled={uploading}
                      className="mt-3 w-full rounded-xl bg-white px-3 py-2 text-[12px] font-black text-black transition hover:bg-sky-100 disabled:opacity-45"
                    >
                      {uploading ? "Import läuft..." : "In Vault importieren"}
                    </button>
                  </div>
                )}

                {feedback && (
                  <p className="rounded-xl border border-emerald-500/16 bg-emerald-500/[0.045] px-3 py-2 text-[12px] text-emerald-200/75">
                    {feedback}
                  </p>
                )}

                <button
                  type="button"
                  onClick={handleAskAi}
                  className="flex items-center justify-center gap-2 rounded-2xl border border-violet-500/18 bg-violet-500/[0.06] px-4 py-3 text-[12px] font-bold text-violet-100/80 transition hover:bg-violet-500/[0.10]"
                >
                  <Bot className="h-4 w-4" />
                  AI Document Brain fragen
                </button>
              </div>
            </div>
          </div>

          <div className="mt-8 grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
            <VaultStat label="Total docs" value={String(stats.total)} tone="cyan" />
            <VaultStat label="Obligations" value={String(stats.obligations)} tone={stats.obligations > 0 ? "amber" : "emerald"} />
            <VaultStat label="Versions" value={String(versionGroups.length)} tone="violet" />
            <VaultStat label="Readiness" value={`${vaultReadiness}%`} tone="emerald" />
            <VaultStat label="Emergency" value={String(stats.safe)} tone="rose" />
          </div>
        </div>
        </div>
      </div>

      <div className="mx-auto grid max-w-[1280px] gap-6 px-6 py-8 xl:grid-cols-[260px_minmax(0,1fr)_360px]">
        <aside className="space-y-3">
          <div className="rounded-[24px] border border-white/[0.07] bg-[#0e0c15] p-3">
            <p className="px-2 pb-2 text-[10px] font-bold uppercase tracking-[0.18em] text-sky-200/45">
              Smart Folders
            </p>
            <div className="space-y-1">
              {AREAS.map((area) => {
                const Icon = area.icon;
                const count =
                  area.id === "all"
                    ? documents.length
                    : area.id === "attention"
                      ? attentionDocs.length
                      : area.id === "safe"
                        ? emergencyDocs.length
                      : documents.filter((document) => intelligence.get(document.id)?.area === area.id).length;
                return (
                  <button
                    key={area.id}
                    type="button"
                    onClick={() => setActiveArea(area.id)}
                    className={cn(
                      "flex w-full items-center gap-3 rounded-2xl px-3 py-3 text-left transition-all",
                      activeArea === area.id
                        ? "bg-sky-500/[0.10] text-sky-100"
                        : "text-white/42 hover:bg-white/[0.04] hover:text-white/68",
                    )}
                  >
                    <Icon className="h-4 w-4 shrink-0" />
                    <div className="min-w-0 flex-1">
                      <p className="truncate text-[13px] font-bold">{area.label}</p>
                      <p className="truncate text-[11px] opacity-55">{area.description}</p>
                    </div>
                    <span className="rounded-full border border-white/[0.06] bg-white/[0.03] px-2 py-0.5 text-[10px] font-bold">
                      {count}
                    </span>
                  </button>
                );
              })}
            </div>
          </div>

          <LifeAdminChecklist checklist={checklist} readiness={vaultReadiness} onSelectArea={setActiveArea} />

          <EmergencyFolder documents={emergencyDocs} onSelect={setSelectedId} />
        </aside>

        <main className="space-y-5">
          <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
            <div className="flex flex-col gap-4 lg:flex-row lg:items-end lg:justify-between">
              <div>
                <div className="mb-3 flex items-center gap-2">
                  <div className="flex h-9 w-9 items-center justify-center rounded-2xl bg-violet-500/12">
                    <WandSparkles className="h-4 w-4 text-violet-300" />
                  </div>
                  <div>
                    <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-violet-300/55">Ask My Vault</p>
                    <h2 className="text-[18px] font-bold tracking-tight text-white">Frag deine Dokumente direkt</h2>
                  </div>
                </div>
                <p className="max-w-xl text-[13px] leading-relaxed text-white/38">
                  Stelle Fragen zu Verträgen, Rechnungen, Fristen, fehlenden Unterlagen oder Risiken. Mindavio übergibt den Vault-Kontext sauber an AI.
                </p>
              </div>
              <div className="flex min-w-0 flex-1 flex-col gap-2 lg:max-w-md">
                <div className="flex rounded-2xl border border-white/[0.06] bg-white/[0.025] p-1">
                  <input
                    value={askQuery}
                    onChange={(event) => setAskQuery(event.target.value)}
                    onKeyDown={(event) => {
                      if (event.key === "Enter") handleAskVault();
                    }}
                    placeholder="z.B. Welche Fristen sind kritisch?"
                    className="min-w-0 flex-1 bg-transparent px-3 text-[13px] text-white outline-none placeholder:text-white/22"
                  />
                  <button
                    type="button"
                    onClick={() => handleAskVault()}
                    className="flex items-center gap-2 rounded-xl bg-violet-600 px-3 py-2 text-[12px] font-bold text-white transition hover:bg-violet-500"
                  >
                    <Send className="h-3.5 w-3.5" />
                    Ask
                  </button>
                </div>
                <div className="flex flex-wrap gap-2">
                  <QuickVaultPrompt onClick={() => handleAskVault("Welche Dokumente brauchen diese Woche Aufmerksamkeit?")}>
                    Diese Woche
                  </QuickVaultPrompt>
                  <QuickVaultPrompt onClick={() => handleAskVault("Welche Dokumente fehlen mir noch für ein solides Life-Admin-Setup?")}>
                    Was fehlt?
                  </QuickVaultPrompt>
                  <QuickVaultPrompt onClick={() => handleAskVault("Welche Tasks und Reminder sollte ich aus meinem Vault erstellen?")}>
                    Actions
                  </QuickVaultPrompt>
                </div>
              </div>
            </div>
          </section>

          <ExpiryObligationRadar
            obligations={obligations}
            onCreateReminder={(obligation) => void handleCreateDocumentReminder(obligation.suggestedDays, obligation.document, intelligence.get(obligation.document.id) || classifyDocument(obligation.document))}
            onCreateTask={(obligation) => void handleCreateDocumentTask(obligation.document, intelligence.get(obligation.document.id) || classifyDocument(obligation.document))}
            onSelect={(documentId) => setSelectedId(documentId)}
          />

          <div className="rounded-[24px] border border-white/[0.07] bg-[#0e0c15] p-4">
            <div className="relative">
              <Search className="absolute left-3 top-1/2 h-4 w-4 -translate-y-1/2 text-sky-200/35" />
              <input
                value={query}
                onChange={(event) => setQuery(event.target.value)}
                placeholder="Search document, source, category..."
                className="h-11 w-full rounded-2xl border border-white/[0.06] bg-white/[0.025] pl-10 pr-4 text-[13px] text-white outline-none placeholder:text-white/22 focus:border-sky-400/30"
              />
            </div>
          </div>

          {loading ? (
            <div className="grid gap-4 lg:grid-cols-2">
              {Array.from({ length: 6 }).map((_, index) => (
                <Skeleton key={index} className="h-44 rounded-[24px] bg-white/[0.03]" />
              ))}
            </div>
          ) : filteredDocuments.length === 0 ? (
            <div className="rounded-[28px] border border-dashed border-white/[0.07] bg-white/[0.015] p-10 text-center">
              <FileText className="mx-auto h-10 w-10 text-sky-200/30" />
              <h2 className="mt-4 text-[18px] font-bold text-white/70">No vault documents here</h2>
              <p className="mt-2 text-[13px] text-white/32">
                Scan a document or switch folders. Attachments from notes, tasks and projects appear here automatically.
              </p>
            </div>
          ) : (
            <div className="grid gap-4 lg:grid-cols-2">
              {filteredDocuments.map((document) => {
                const intel = intelligence.get(document.id) || classifyDocument(document);
                const active = selectedDocument?.id === document.id;
                const obligation = buildObligation(document, intel);
                const versionCount = versionGroups.find((group) => group.documents.some((item) => item.id === document.id))?.documents.length || 0;
                return (
                  <button
                    key={document.id}
                    type="button"
                    onClick={() => setSelectedId(document.id)}
                    className={cn(
                      "group overflow-hidden rounded-[24px] border bg-[#0e0c15] p-4 text-left transition-all hover:-translate-y-0.5",
                      active ? "border-sky-400/24 shadow-[0_18px_50px_rgba(14,165,233,0.08)]" : "border-white/[0.06] hover:border-white/[0.10]",
                    )}
                  >
                    <div className="flex gap-4">
                      <div className="w-24 shrink-0">
                        {isPreviewableFile(document.mime_type, document.file_name) ? (
                          <FileThumbnail
                            fileName={document.file_name}
                            publicUrl={document.public_url}
                            mimeType={document.mime_type}
                            className="h-24 w-full border-white/[0.06] bg-white/[0.025]"
                          />
                        ) : (
                          <div className="flex h-24 w-full items-center justify-center rounded-xl border border-white/[0.06] bg-white/[0.025]">
                            <FileText className="h-5 w-5 text-sky-200/35" />
                          </div>
                        )}
                      </div>
                      <div className="min-w-0 flex-1">
                        <div className="flex items-start justify-between gap-3">
                          <div className="min-w-0">
                            <p className="truncate text-[14px] font-bold text-white/82">{document.file_name}</p>
                            <p className="mt-1 truncate text-[12px] text-white/32">
                              {document.entityLabel} · {document.entityTitle}
                            </p>
                          </div>
                          <span className={cn("shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.12em]", TONE_CLASSES[intel.tone])}>
                            {intel.actionRequired ? "Action" : intel.area}
                          </span>
                        </div>
                        <div className="mt-4 grid grid-cols-2 gap-2">
                          <MiniFact label="Area" value={intel.area} />
                          <MiniFact label="Next" value={obligation ? `${obligation.suggestedDays}d` : "filed"} />
                        </div>
                        <div className="mt-3 flex flex-wrap gap-1.5">
                          <SmartBadge>{intel.confidence}% confidence</SmartBadge>
                          {versionCount > 1 && <SmartBadge>{versionCount} versions</SmartBadge>}
                          {isEmergencyDocument(document, intel) && <SmartBadge>Emergency</SmartBadge>}
                        </div>
                      </div>
                    </div>
                  </button>
                );
              })}
            </div>
          )}

          <DocumentTimeline timeline={timeline} onSelect={setSelectedId} />

          <VaultReviewCard
            actioning={actioning}
            checklist={checklist}
            documents={documents}
            obligations={obligations}
            onExport={() => void handleExportVaultReview()}
            onShare={() => setShareToChatOpen(true)}
            readiness={vaultReadiness}
            cardRef={reviewCardRef}
            stats={stats}
            versionCount={versionGroups.length}
          />
        </main>

        <aside className="space-y-5">
          <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
            <div className="flex items-center justify-between gap-3">
              <div>
                <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-amber-200/48">
                  Document Inspector
                </p>
                <h2 className="mt-1 text-[18px] font-bold tracking-tight text-white">Kerninfos</h2>
              </div>
              <Sparkles className="h-5 w-5 text-amber-200/55" />
            </div>

            {selectedDocument && selectedIntel ? (
              <div className="mt-5 space-y-4">
                <div>
                  <p className="text-[15px] font-bold leading-snug text-white/84">{selectedDocument.file_name}</p>
                  <p className="mt-1 text-[12px] text-white/34">
                    {selectedDocument.entityLabel} · {selectedDocument.entityTitle}
                  </p>
                </div>

                <div className={cn("rounded-2xl border p-3", TONE_CLASSES[selectedIntel.tone])}>
                  <p className="text-[10px] font-bold uppercase tracking-[0.14em] opacity-65">Status</p>
                  <p className="mt-1 text-[14px] font-bold text-white/82">{selectedIntel.actionLabel}</p>
                </div>

                <div className="grid gap-2">
                  {selectedIntel.fields.map((field) => (
                    <div key={field.label} className="flex items-center justify-between gap-3 rounded-2xl border border-white/[0.06] bg-white/[0.025] px-3 py-2">
                      <span className="text-[11px] uppercase tracking-[0.13em] text-white/25">{field.label}</span>
                      <span className="truncate text-[12px] font-semibold text-white/62">{field.value}</span>
                    </div>
                  ))}
                </div>

                <div className="grid gap-2">
                  <button
                    type="button"
                    onClick={() => void handleCreateDocumentTask()}
                    disabled={actioning === "task"}
                    className="flex items-center justify-center gap-2 rounded-xl border border-sky-500/18 bg-sky-500/[0.06] px-3 py-2 text-[12px] font-bold text-sky-100/75 transition hover:bg-sky-500/[0.10] disabled:opacity-40"
                  >
                    <ClipboardCheck className="h-4 w-4" />
                    {actioning === "task" ? "Creating..." : "Task daraus machen"}
                  </button>
                  <button
                    type="button"
                    onClick={() => void handleCreateDocumentReminder(selectedObligation?.suggestedDays || 7)}
                    disabled={actioning === "reminder"}
                    className="flex items-center justify-center gap-2 rounded-xl border border-amber-500/18 bg-amber-500/[0.06] px-3 py-2 text-[12px] font-bold text-amber-100/75 transition hover:bg-amber-500/[0.10] disabled:opacity-40"
                  >
                    <BellPlus className="h-4 w-4" />
                    {actioning === "reminder" ? "Setting..." : `Reminder ${selectedObligation?.suggestedDays || 7}d`}
                  </button>
                  {isPreviewableFile(selectedDocument.mime_type, selectedDocument.file_name) && (
                    <button
                      type="button"
                      onClick={() => setPreviewing(selectedDocument)}
                      className="flex items-center justify-center gap-2 rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 py-2 text-[12px] font-bold text-white/60 transition hover:bg-white/[0.05]"
                    >
                      <Eye className="h-4 w-4" />
                      Preview
                    </button>
                  )}
                  <a
                    href={selectedDocument.public_url}
                    target="_blank"
                    rel="noreferrer"
                    className="flex items-center justify-center gap-2 rounded-xl border border-emerald-500/18 bg-emerald-500/[0.06] px-3 py-2 text-[12px] font-bold text-emerald-100/75 transition hover:bg-emerald-500/[0.10]"
                  >
                    <Download className="h-4 w-4" />
                    Open file
                  </a>
                  <Link
                    href={selectedDocument.entityHref}
                    className="flex items-center justify-center gap-2 rounded-xl border border-violet-500/18 bg-violet-500/[0.06] px-3 py-2 text-[12px] font-bold text-violet-100/75 transition hover:bg-violet-500/[0.10]"
                  >
                    <FolderOpen className="h-4 w-4" />
                    Open source
                  </Link>
                  <button
                    type="button"
                    onClick={() => void handleCopyCapsule()}
                    disabled={actioning === "capsule"}
                    className="flex items-center justify-center gap-2 rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 py-2 text-[12px] font-bold text-white/58 transition hover:bg-white/[0.05] disabled:opacity-40"
                  >
                    <Copy className="h-4 w-4" />
                    {actioning === "capsule" ? "Copying..." : "Private Capsule kopieren"}
                  </button>
                </div>
              </div>
            ) : (
              <div className="mt-5 rounded-2xl border border-dashed border-amber-500/14 bg-amber-500/[0.025] p-5 text-center">
                <p className="text-[13px] text-white/35">Select a document to inspect it.</p>
              </div>
            )}
          </section>

          <VersionCompare group={selectedVersionGroup || versionGroups[0] || null} onAskAi={handleAskVault} onSelect={setSelectedId} />

          <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
            <div className="flex items-center gap-3">
              <AlertTriangle className="h-4 w-4 text-rose-300/70" />
              <div>
                <h2 className="text-[15px] font-bold text-white/78">Needs Attention</h2>
                <p className="text-[12px] text-white/30">Likely deadlines, payments, renewals.</p>
              </div>
            </div>
            <div className="mt-4 space-y-2">
              {attentionDocs.slice(0, 5).map((document) => (
                <button
                  key={document.id}
                  type="button"
                  onClick={() => setSelectedId(document.id)}
                  className="flex w-full items-center gap-3 rounded-2xl border border-rose-500/10 bg-rose-500/[0.035] p-3 text-left transition hover:bg-rose-500/[0.06]"
                >
                  <AlertTriangle className="h-4 w-4 shrink-0 text-rose-200/60" />
                  <div className="min-w-0">
                    <p className="truncate text-[12px] font-bold text-white/70">{document.file_name}</p>
                    <p className="truncate text-[11px] text-white/28">{document.entityTitle}</p>
                  </div>
                </button>
              ))}
              {attentionDocs.length === 0 && (
                <div className="rounded-2xl border border-dashed border-emerald-500/14 bg-emerald-500/[0.035] p-4 text-center">
                  <CheckCircle2 className="mx-auto h-5 w-5 text-emerald-300/60" />
                  <p className="mt-2 text-[12px] text-white/38">No obvious document pressure.</p>
                </div>
              )}
            </div>
          </section>
        </aside>
      </div>

      {previewing && (
        <FilePreviewModal
          open={Boolean(previewing)}
          onClose={() => setPreviewing(null)}
          fileName={previewing.file_name}
          publicUrl={previewing.public_url}
          mimeType={previewing.mime_type}
        />
      )}

      {shareToChatOpen && (
        <ShareToChatModal
          open={shareToChatOpen}
          onClose={() => setShareToChatOpen(false)}
          buildPayload={buildVaultSharePayload}
          title="Vault Review an Chat senden"
          description="Sendet deine aktuelle Vault Review Card als Mindavio-Share-Bild."
          defaultMessage="Mein aktueller Vault Review."
        />
      )}
    </div>
  );
}

function VaultPill({ children }: { children: React.ReactNode }) {
  return (
    <span className="rounded-full border border-white/[0.07] bg-white/[0.03] px-3 py-1 text-[11px] font-medium text-white/45">
      {children}
    </span>
  );
}

function VaultStat({ label, tone, value }: { label: string; tone: VaultTone; value: string }) {
  return (
    <div className={cn("rounded-2xl border px-4 py-3", TONE_CLASSES[tone])}>
      <p className="text-[10px] font-bold uppercase tracking-[0.16em] text-white/26">{label}</p>
      <p className="mt-1 text-[26px] font-black text-white">{value}</p>
    </div>
  );
}

function MiniFact({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-xl border border-white/[0.06] bg-white/[0.025] px-3 py-2">
      <p className="text-[9px] font-bold uppercase tracking-[0.13em] text-white/22">{label}</p>
      <p className="mt-0.5 truncate text-[12px] font-bold capitalize text-white/64">{value}</p>
    </div>
  );
}

function QuickVaultPrompt({ children, onClick }: { children: React.ReactNode; onClick: () => void }) {
  return (
    <button
      type="button"
      onClick={onClick}
      className="rounded-full border border-white/[0.07] bg-white/[0.025] px-3 py-1 text-[11px] font-semibold text-white/42 transition hover:bg-white/[0.05] hover:text-white/65"
    >
      {children}
    </button>
  );
}

function SmartBadge({ children }: { children: React.ReactNode }) {
  return (
    <span className="rounded-full border border-white/[0.06] bg-white/[0.025] px-2 py-0.5 text-[10px] font-semibold text-white/32">
      {children}
    </span>
  );
}

function LifeAdminChecklist({
  checklist,
  onSelectArea,
  readiness,
}: {
  checklist: VaultChecklistItem[];
  onSelectArea: (area: VaultArea) => void;
  readiness: number;
}) {
  return (
    <section className="rounded-[24px] border border-white/[0.07] bg-[#0e0c15] p-4">
      <div className="mb-4 flex items-center justify-between gap-3">
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-emerald-300/50">Life Admin</p>
          <h3 className="mt-1 text-[15px] font-bold text-white/82">Checklist</h3>
        </div>
        <div className="rounded-full border border-emerald-500/14 bg-emerald-500/[0.06] px-2 py-1 text-[11px] font-bold text-emerald-200/75">
          {readiness}%
        </div>
      </div>

      <div className="space-y-2">
        {checklist.map((item) => {
          const Icon = item.icon;
          return (
            <button
              key={item.id}
              type="button"
              onClick={() => onSelectArea(item.id)}
              className="flex w-full items-center gap-3 rounded-2xl border border-white/[0.055] bg-white/[0.02] p-3 text-left transition hover:bg-white/[0.04]"
            >
              <div
                className={cn(
                  "flex h-8 w-8 shrink-0 items-center justify-center rounded-xl",
                  item.ready ? "bg-emerald-500/12 text-emerald-300" : "bg-amber-500/12 text-amber-300",
                )}
              >
                <Icon className="h-4 w-4" />
              </div>
              <div className="min-w-0 flex-1">
                <div className="flex items-center justify-between gap-2">
                  <p className="truncate text-[12px] font-bold text-white/70">{item.title}</p>
                  <span className="text-[11px] font-bold text-white/32">{item.count}</span>
                </div>
                <p className="truncate text-[11px] text-white/28">{item.description}</p>
              </div>
            </button>
          );
        })}
      </div>
    </section>
  );
}

function EmergencyFolder({ documents, onSelect }: { documents: DocumentItem[]; onSelect: (id: string) => void }) {
  return (
    <section className="rounded-[24px] border border-white/[0.07] bg-[#0e0c15] p-4">
      <div className="mb-4 flex items-center gap-3">
        <div className="flex h-9 w-9 items-center justify-center rounded-2xl bg-rose-500/12">
          <LifeBuoy className="h-4 w-4 text-rose-300" />
        </div>
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-rose-300/50">Emergency Folder</p>
          <h3 className="text-[15px] font-bold text-white/82">Schnell griffbereit</h3>
        </div>
      </div>

      <div className="space-y-2">
        {documents.slice(0, 4).map((document) => (
          <button
            key={document.id}
            type="button"
            onClick={() => onSelect(document.id)}
            className="flex w-full items-center gap-3 rounded-2xl border border-white/[0.055] bg-white/[0.02] p-3 text-left transition hover:bg-white/[0.04]"
          >
            <LockKeyhole className="h-4 w-4 shrink-0 text-rose-200/60" />
            <div className="min-w-0">
              <p className="truncate text-[12px] font-bold text-white/68">{document.file_name}</p>
              <p className="truncate text-[11px] text-white/28">{document.entityTitle}</p>
            </div>
          </button>
        ))}
        {documents.length === 0 && (
          <p className="rounded-2xl border border-dashed border-white/[0.06] bg-white/[0.015] p-4 text-[12px] leading-relaxed text-white/32">
            Noch kein Emergency Set. IDs, Versicherungen und medizinische Dokumente werden hier automatisch gesammelt.
          </p>
        )}
      </div>
    </section>
  );
}

function ExpiryObligationRadar({
  obligations,
  onCreateReminder,
  onCreateTask,
  onSelect,
}: {
  obligations: VaultObligation[];
  onCreateReminder: (obligation: VaultObligation) => void;
  onCreateTask: (obligation: VaultObligation) => void;
  onSelect: (documentId: string) => void;
}) {
  return (
    <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
      <div className="mb-4 flex flex-col gap-2 sm:flex-row sm:items-end sm:justify-between">
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-amber-300/55">Expiry & Obligation Radar</p>
          <h2 className="mt-1 text-[18px] font-bold tracking-tight text-white">Fristen, Zahlungen, Pflichten</h2>
        </div>
        <p className="text-[12px] text-white/28">{obligations.length} active signal{obligations.length === 1 ? "" : "s"}</p>
      </div>

      {obligations.length === 0 ? (
        <div className="rounded-2xl border border-dashed border-white/[0.06] bg-white/[0.015] p-5 text-center">
          <CheckCircle2 className="mx-auto h-5 w-5 text-emerald-300/60" />
          <p className="mt-2 text-[13px] font-semibold text-white/55">Kein offensichtlicher Dokument-Druck.</p>
          <p className="mt-1 text-[12px] text-white/28">Neue Rechnungen, Verträge oder Ablaufdaten landen hier automatisch.</p>
        </div>
      ) : (
        <div className="grid gap-3 lg:grid-cols-2">
          {obligations.slice(0, 6).map((obligation) => (
            <div key={obligation.id} className="rounded-2xl border border-white/[0.06] bg-white/[0.025] p-4">
              <button type="button" onClick={() => onSelect(obligation.document.id)} className="block w-full text-left">
                <div className="flex items-start justify-between gap-3">
                  <div className="min-w-0">
                    <p className="truncate text-[13px] font-bold text-white/76">{obligation.label}</p>
                    <p className="mt-1 truncate text-[11px] text-white/30">{obligation.description}</p>
                  </div>
                  <span className={cn("shrink-0 rounded-full border px-2 py-0.5 text-[10px] font-bold uppercase tracking-[0.12em]", TONE_CLASSES[obligation.tone])}>
                    {obligation.severity}
                  </span>
                </div>
              </button>
              <div className="mt-3 flex flex-wrap gap-2">
                <button
                  type="button"
                  onClick={() => onCreateReminder(obligation)}
                  className="rounded-xl border border-amber-500/16 bg-amber-500/[0.06] px-3 py-1.5 text-[11px] font-bold text-amber-100/75 transition hover:bg-amber-500/[0.10]"
                >
                  Reminder {obligation.suggestedDays}d
                </button>
                <button
                  type="button"
                  onClick={() => onCreateTask(obligation)}
                  className="rounded-xl border border-sky-500/16 bg-sky-500/[0.06] px-3 py-1.5 text-[11px] font-bold text-sky-100/75 transition hover:bg-sky-500/[0.10]"
                >
                  Task erstellen
                </button>
              </div>
            </div>
          ))}
        </div>
      )}
    </section>
  );
}

function DocumentTimeline({ timeline, onSelect }: { timeline: VaultTimelineItem[]; onSelect: (documentId: string) => void }) {
  return (
    <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
      <div className="mb-4 flex items-center gap-3">
        <div className="flex h-9 w-9 items-center justify-center rounded-2xl bg-sky-500/12">
          <History className="h-4 w-4 text-sky-300" />
        </div>
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-sky-300/55">Document Timeline</p>
          <h2 className="text-[18px] font-bold tracking-tight text-white">Was im Vault passiert ist</h2>
        </div>
      </div>

      <div className="space-y-2">
        {timeline.map((item) => {
          const Icon = item.icon;
          return (
            <button
              key={item.id}
              type="button"
              onClick={() => onSelect(item.id)}
              className="flex w-full items-center gap-3 rounded-2xl border border-white/[0.055] bg-white/[0.02] p-3 text-left transition hover:bg-white/[0.04]"
            >
              <div className={cn("flex h-9 w-9 shrink-0 items-center justify-center rounded-2xl", TONE_CLASSES[item.tone])}>
                <Icon className="h-4 w-4" />
              </div>
              <div className="min-w-0 flex-1">
                <p className="truncate text-[13px] font-bold text-white/72">{item.title}</p>
                <p className="truncate text-[11px] text-white/30">{item.subtitle}</p>
              </div>
              <span className="shrink-0 text-[11px] font-semibold text-white/25">{formatRelativeDate(item.timestamp)}</span>
            </button>
          );
        })}
        {timeline.length === 0 && (
          <p className="rounded-2xl border border-dashed border-white/[0.06] bg-white/[0.015] p-5 text-center text-[12px] text-white/32">
            Sobald Dokumente im Vault sind, entsteht hier deine Dokumenten-Timeline.
          </p>
        )}
      </div>
    </section>
  );
}

function VersionCompare({
  group,
  onAskAi,
  onSelect,
}: {
  group: VaultVersionGroup | null;
  onAskAi: (question: string) => void;
  onSelect: (documentId: string) => void;
}) {
  return (
    <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
      <div className="flex items-center gap-3">
        <GitCompareArrows className="h-4 w-4 text-violet-300/70" />
        <div>
          <h2 className="text-[15px] font-bold text-white/78">Version Compare</h2>
          <p className="text-[12px] text-white/30">Ähnliche Dateien und alte Stände.</p>
        </div>
      </div>

      {group ? (
        <div className="mt-4 space-y-2">
          <p className="truncate text-[13px] font-bold text-white/65">{group.label}</p>
          {group.documents.slice(0, 4).map((document, index) => (
            <button
              key={document.id}
              type="button"
              onClick={() => onSelect(document.id)}
              className="flex w-full items-center justify-between gap-3 rounded-2xl border border-white/[0.055] bg-white/[0.02] p-3 text-left transition hover:bg-white/[0.04]"
            >
              <div className="min-w-0">
                <p className="truncate text-[12px] font-bold text-white/65">{document.file_name}</p>
                <p className="text-[11px] text-white/28">{formatRelativeDate(document.created_at)}</p>
              </div>
              <span className="shrink-0 rounded-full border border-white/[0.06] bg-white/[0.025] px-2 py-0.5 text-[10px] font-bold text-white/35">
                {index === 0 ? "newest" : `v-${index}`}
              </span>
            </button>
          ))}
          <button
            type="button"
            onClick={() => onAskAi(`Vergleiche die Versionen dieser Dokumentgruppe und sage mir, was wahrscheinlich geändert wurde: ${group.documents.map((doc) => doc.file_name).join(", ")}`)}
            className="mt-2 flex w-full items-center justify-center gap-2 rounded-xl border border-violet-500/16 bg-violet-500/[0.06] px-3 py-2 text-[12px] font-bold text-violet-100/75 transition hover:bg-violet-500/[0.10]"
          >
            <Bot className="h-4 w-4" />
            AI Compare
          </button>
        </div>
      ) : (
        <p className="mt-4 rounded-2xl border border-dashed border-white/[0.06] bg-white/[0.015] p-4 text-[12px] leading-relaxed text-white/32">
          Noch keine klaren Versionsgruppen. Wenn du v1, v2, final oder ähnliche Dateien hast, erscheinen sie hier.
        </p>
      )}
    </section>
  );
}

function VaultReviewCard({
  actioning,
  cardRef,
  checklist,
  documents,
  obligations,
  onExport,
  onShare,
  readiness,
  stats,
  versionCount,
}: {
  actioning: string | null;
  cardRef: React.RefObject<HTMLDivElement | null>;
  checklist: VaultChecklistItem[];
  documents: DocumentItem[];
  obligations: VaultObligation[];
  onExport: () => void;
  onShare: () => void;
  readiness: number;
  stats: { total: number; attention: number; obligations: number; pdfs: number; recent: number; safe: number };
  versionCount: number;
}) {
  const missing = checklist.filter((item) => !item.ready);
  const topObligation = obligations[0];

  return (
    <section className="rounded-[28px] border border-white/[0.07] bg-[#0e0c15] p-5">
      <div className="mb-4 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
        <div>
          <p className="text-[10px] font-bold uppercase tracking-[0.18em] text-emerald-300/55">Vault Review Card</p>
          <h2 className="mt-1 text-[18px] font-bold tracking-tight text-white">Dein Dokumenten-Status als Bild</h2>
        </div>
        <div className="flex gap-2">
          <button
            type="button"
            onClick={onExport}
            disabled={actioning === "review"}
            className="flex items-center gap-2 rounded-xl border border-emerald-500/16 bg-emerald-500/[0.06] px-3 py-2 text-[12px] font-bold text-emerald-100/75 transition hover:bg-emerald-500/[0.10] disabled:opacity-40"
          >
            <Download className="h-4 w-4" />
            Export
          </button>
          <button
            type="button"
            onClick={onShare}
            className="flex items-center gap-2 rounded-xl border border-violet-500/16 bg-violet-500/[0.06] px-3 py-2 text-[12px] font-bold text-violet-100/75 transition hover:bg-violet-500/[0.10]"
          >
            <Send className="h-4 w-4" />
            Chat
          </button>
        </div>
      </div>

      <div
        ref={cardRef}
        className="overflow-hidden rounded-[24px] border border-white/[0.07] bg-[radial-gradient(circle_at_top_left,rgba(124,58,237,0.18),rgba(14,165,233,0.06)_38%,#0a0a0d_100%)] p-6"
      >
        <div className="flex items-start justify-between gap-4">
          <div>
            <div className="mb-4 flex items-center gap-2">
              <div className="flex h-8 w-8 items-center justify-center rounded-xl bg-violet-500/15 text-violet-200">
                <ShieldCheck className="h-4 w-4" />
              </div>
              <span className="text-[11px] font-bold uppercase tracking-[0.16em] text-white/35">Mindavio Vault</span>
            </div>
            <h3 className="text-[24px] font-bold tracking-tight text-white">Vault Review</h3>
            <p className="mt-1 text-[12px] text-white/38">
              Generiert am {new Date().toLocaleDateString("de-DE", { day: "2-digit", month: "short", year: "numeric" })}
            </p>
          </div>
          <div className="text-right">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-emerald-300/60">Readiness</p>
            <p className="text-[34px] font-black text-white">{readiness}%</p>
          </div>
        </div>

        <div className="mt-6 grid gap-3 sm:grid-cols-4">
          <ReviewMetric label="Docs" value={String(stats.total)} />
          <ReviewMetric label="Radar" value={String(stats.obligations)} />
          <ReviewMetric label="Emergency" value={String(stats.safe)} />
          <ReviewMetric label="Versions" value={String(versionCount)} />
        </div>

        <div className="mt-5 grid gap-3 sm:grid-cols-2">
          <div className="rounded-2xl border border-white/[0.06] bg-black/15 p-4">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-amber-300/55">Top Obligation</p>
            <p className="mt-2 line-clamp-2 text-[13px] font-bold text-white/75">
              {topObligation ? topObligation.label : "Kein akuter Dokument-Druck"}
            </p>
            <p className="mt-1 line-clamp-1 text-[11px] text-white/30">
              {topObligation ? topObligation.document.file_name : "Vault wirkt gerade ruhig."}
            </p>
          </div>
          <div className="rounded-2xl border border-white/[0.06] bg-black/15 p-4">
            <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-rose-300/55">Missing Set</p>
            <p className="mt-2 line-clamp-2 text-[13px] font-bold text-white/75">
              {missing.length > 0 ? missing.map((item) => item.title).slice(0, 3).join(", ") : "Life Admin Set komplett genug"}
            </p>
            <p className="mt-1 text-[11px] text-white/30">{documents.length} Dateien in deinem Vault-Kontext</p>
          </div>
        </div>
      </div>
    </section>
  );
}

function ReviewMetric({ label, value }: { label: string; value: string }) {
  return (
    <div className="rounded-2xl border border-white/[0.06] bg-white/[0.035] px-4 py-3">
      <p className="text-[10px] font-bold uppercase tracking-[0.14em] text-white/28">{label}</p>
      <p className="mt-1 text-[22px] font-black text-white">{value}</p>
    </div>
  );
}
