"use client";

import { memo, useCallback, useMemo, useRef, useState } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import {
  AlertCircle,
  ArrowLeft,
  CalendarDays,
  CheckCircle2,
  ChevronRight,
  Code2,
  Clock,
  Download,
  Edit3,
  FileText,
  FolderPlus,
  Inbox,
  Mail,
  Plus,
  Receipt,
  Trash2,
  Upload,
  Users,
} from "lucide-react";
import { Modal } from "@/components/ui/modal";
import { useAttachments } from "@/hooks/use-attachments";
import {
  useInvoices,
  type InvoiceCustomerUpsertInput,
  type InvoiceFolderUpsertInput,
  type InvoiceItemDraft,
  type InvoiceUpsertInput,
} from "@/hooks/use-invoices";
import {
  buildInvoicePackPdfBlob,
  buildInvoicePdfBlob,
  formatInvoiceDate,
  formatInvoiceMoney,
  getInvoiceDocumentLabel,
  resolveInvoiceStatus,
  sanitizeInvoiceFileSegment,
} from "@/lib/invoices";
import { formatFileSize } from "@/lib/file-utils";
import { formatRelativeDate } from "@/lib/utils";
import type {
  Invoice as InvoiceRecord,
  InvoiceCustomer,
  InvoiceDirection,
  InvoiceDocumentType,
  InvoiceFolder,
  InvoiceStatus,
} from "@/types";

type Section = "outgoing" | "incoming" | "quotes" | "customers";
type View = "list" | "invoice-editor" | "customer-editor" | "detail";
type InvoiceFilter = "all" | "active" | "paid" | "overdue" | "cancelled";
type InvoiceDraft = InvoiceUpsertInput & {
  customer_id: string;
  folder_id: string;
};

const PAGE_BG = "min-h-screen bg-background px-4 py-8 text-white md:px-8";
const CARD_SHELL =
  "rounded-[28px] border border-white/[0.08] bg-[radial-gradient(ellipse_at_top_left,rgba(255,255,255,0.03),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)]";
const INPUT_CLS =
  "w-full rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-sm text-white outline-none placeholder:text-white/30 transition-colors focus:border-sky-500/[0.30]";

const STATUS_CONFIG: Record<
  InvoiceStatus,
  { accent: string; badgeCls: string; label: string }
> = {
  draft: {
    accent: "text-white/45",
    badgeCls: "border border-white/[0.08] bg-white/[0.05] text-white/50",
    label: "Entwurf",
  },
  ready: {
    accent: "text-violet-300",
    badgeCls: "border border-violet-500/[0.16] bg-violet-500/[0.08] text-violet-300",
    label: "Bereit",
  },
  sent: {
    accent: "text-sky-300",
    badgeCls: "border border-sky-500/[0.16] bg-sky-500/[0.08] text-sky-300",
    label: "Versendet",
  },
  received: {
    accent: "text-amber-300",
    badgeCls: "border border-amber-500/[0.16] bg-amber-500/[0.08] text-amber-300",
    label: "Erhalten",
  },
  paid: {
    accent: "text-emerald-300",
    badgeCls: "border border-emerald-500/[0.16] bg-emerald-500/[0.08] text-emerald-300",
    label: "Bezahlt",
  },
  overdue: {
    accent: "text-rose-300",
    badgeCls: "border border-rose-500/[0.16] bg-rose-500/[0.08] text-rose-300",
    label: "Überfällig",
  },
  cancelled: {
    accent: "text-white/30",
    badgeCls: "border border-white/[0.08] bg-white/[0.04] text-white/35",
    label: "Storniert",
  },
};

function downloadBlob(blob: Blob, fileName: string) {
  const objectUrl = URL.createObjectURL(blob);
  const link = document.createElement("a");
  link.href = objectUrl;
  link.download = fileName;
  link.click();
  window.setTimeout(() => URL.revokeObjectURL(objectUrl), 1000);
}

function nextInvoiceNumber(
  invoices: InvoiceRecord[],
  direction: InvoiceDirection,
  documentType: InvoiceDocumentType = "invoice",
) {
  const prefix = documentType === "quote" ? "ANG" : direction === "incoming" ? "REC" : "INV";
  const scoped = invoices.filter(
    (invoice) => invoice.direction === direction && (invoice.document_type || "invoice") === documentType,
  );
  const numbers = scoped
    .map((invoice) => {
      const match = invoice.invoice_number.match(/(\d+)$/);
      return match ? Number.parseInt(match[1], 10) : 0;
    })
    .filter((value) => Number.isFinite(value));
  const next = numbers.length > 0 ? Math.max(...numbers) + 1 : 1;
  return `${prefix}-${String(next).padStart(3, "0")}`;
}

function todayStr() {
  return new Date().toISOString().split("T")[0];
}

function addDays(value: string, days: number) {
  const date = new Date(`${value}T00:00:00`);
  date.setDate(date.getDate() + days);
  return date.toISOString().split("T")[0];
}

function getInvoiceTitle(invoice: InvoiceRecord) {
  if (invoice.title?.trim()) return invoice.title.trim();
  return getInvoiceDocumentLabel(invoice);
}

function getCounterpartyLabel(direction: InvoiceDirection, documentType: InvoiceDocumentType = "invoice") {
  if (documentType === "quote") return "Firma / Kunde";
  return direction === "incoming" ? "Anbieter" : "Kunde";
}

function getDirectionLabel(direction: InvoiceDirection, documentType: InvoiceDocumentType = "invoice") {
  if (documentType === "quote") return "Angebot";
  return direction === "incoming" ? "Eingehend" : "Ausgehend";
}

function toInvoiceDraft(invoice: InvoiceRecord): InvoiceDraft {
  return {
    accent_color: invoice.accent_color || "#7dd3fc",
    company_address: invoice.company_address || "",
    company_email: invoice.company_email || "",
    company_name: invoice.company_name || "Mindavio",
    company_phone: invoice.company_phone || "",
    company_vat_id: invoice.company_vat_id || "",
    company_website: invoice.company_website || "",
    counterparty_address: invoice.counterparty_address,
    counterparty_email: invoice.counterparty_email,
    counterparty_name: invoice.counterparty_name,
    customer_id: invoice.customer_id || "",
    document_type: invoice.document_type || "invoice",
    direction: invoice.direction,
    due_date: invoice.due_date,
    folder_id: invoice.folder_id || "",
    inbox_at: invoice.inbox_at,
    inbox_note: invoice.inbox_note,
    invoice_number: invoice.invoice_number,
    issue_date: invoice.issue_date,
    logo_url: invoice.logo_url || "",
    items:
      invoice.items?.map((item) => ({
        description: item.description,
        id: item.id,
        quantity: Number(item.quantity),
        unit_price_cents: item.unit_price_cents,
    })) || [],
    notes: invoice.notes,
    source: invoice.source,
    status: invoice.status,
    tax_enabled: invoice.tax_enabled ?? Number(invoice.tax_rate) > 0,
    tax_rate: Number(invoice.tax_rate),
    title: invoice.title,
  };
}

function buildEmptyDraft(
  direction: InvoiceDirection,
  invoices: InvoiceRecord[],
  documentType: InvoiceDocumentType = "invoice",
): InvoiceDraft {
  const issueDate = todayStr();
  return {
    accent_color: "#7dd3fc",
    company_address: "",
    company_email: "",
    company_name: "Mindavio",
    company_phone: "",
    company_vat_id: "",
    company_website: "",
    counterparty_address: "",
    counterparty_email: "",
    counterparty_name: "",
    customer_id: "",
    document_type: documentType,
    direction,
    due_date: addDays(issueDate, 30),
    folder_id: "",
    inbox_at: null,
    inbox_note: "",
    invoice_number: nextInvoiceNumber(invoices, direction, documentType),
    issue_date: issueDate,
    logo_url: "",
    items: [
      {
        id: crypto.randomUUID(),
        description: "",
        quantity: 1,
        unit_price_cents: 0,
      },
    ],
    notes: "",
    source: "manual" as const,
    status: direction === "incoming" ? ("received" as InvoiceStatus) : ("draft" as InvoiceStatus),
    tax_enabled: true,
    tax_rate: 19,
    title: "",
  };
}

function slugifyFolderName(value: string) {
  return value
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9äöüß_-]+/gi, "-")
    .replace(/-+/g, "-")
    .replace(/^-|-$/g, "");
}

function getStatusTransitions(invoice: InvoiceRecord): InvoiceStatus[] {
  const effectiveStatus = resolveInvoiceStatus(invoice);

  if (invoice.document_type === "quote") {
    if (effectiveStatus === "draft") return ["ready", "sent", "cancelled"];
    if (effectiveStatus === "ready") return ["sent", "cancelled"];
    if (effectiveStatus === "sent") return ["cancelled"];
    return [];
  }

  if (invoice.direction === "incoming") {
    if (effectiveStatus === "received") return ["paid", "overdue", "cancelled"];
    if (effectiveStatus === "overdue") return ["paid", "cancelled"];
    return [];
  }

  if (effectiveStatus === "draft") return ["ready", "sent", "cancelled"];
  if (effectiveStatus === "ready") return ["sent", "paid", "cancelled"];
  if (effectiveStatus === "sent") return ["paid", "overdue", "cancelled"];
  if (effectiveStatus === "overdue") return ["paid", "cancelled"];
  return [];
}

function StatusBadge({ status }: { status: InvoiceStatus }) {
  const cfg = STATUS_CONFIG[status];
  return <span className={`inline-flex rounded-full px-2.5 py-1 text-[11px] font-semibold ${cfg.badgeCls}`}>{cfg.label}</span>;
}

function SectionChip({
  active,
  icon,
  label,
  onClick,
}: {
  active: boolean;
  icon: React.ReactNode;
  label: string;
  onClick: () => void;
}) {
  return (
    <button
      onClick={onClick}
      className={`inline-flex items-center gap-2 rounded-2xl px-4 py-2 text-sm font-semibold transition-all ${
        active
          ? "border border-sky-500/[0.22] bg-sky-500/12 text-sky-300"
          : "border border-white/[0.08] bg-white/[0.03] text-white/45 hover:text-white/70"
      }`}
    >
      {icon}
      {label}
    </button>
  );
}

function InvoiceCard({
  invoice,
  onClick,
}: {
  invoice: InvoiceRecord;
  onClick: () => void;
}) {
  const status = resolveInvoiceStatus(invoice);
  return (
    <button
      onClick={onClick}
      className="group w-full rounded-2xl border border-white/[0.06] bg-white/[0.02] p-4 text-left transition-all hover:border-sky-500/[0.16] hover:bg-sky-500/[0.03]"
    >
      <div className="flex items-center justify-between gap-4">
        <div className="min-w-0 space-y-1">
          <div className="flex flex-wrap items-center gap-2">
            <span className="text-xs font-bold text-white/40">{invoice.invoice_number}</span>
            <StatusBadge status={status} />
            {invoice.folder ? (
              <span
                className="rounded-full border px-2 py-0.5 text-[10px] font-semibold"
                style={{
                  backgroundColor: `${invoice.folder.color}18`,
                  borderColor: `${invoice.folder.color}44`,
                  color: invoice.folder.color,
                }}
              >
                {invoice.folder.name}
              </span>
            ) : null}
          </div>
          <p className="truncate font-semibold text-white">
            {invoice.counterparty_name || getInvoiceTitle(invoice)}
          </p>
          <p className="text-xs text-white/32">
            {invoice.document_type === "quote"
              ? "Gültig bis"
              : invoice.direction === "incoming"
                ? "Erhalten"
                : "Fällig"}{" "}
            {formatInvoiceDate(invoice.due_date)}
          </p>
        </div>

        <div className="flex shrink-0 items-center gap-3">
          <p className={`text-xl font-black tabular-nums ${STATUS_CONFIG[status].accent}`}>
            {formatInvoiceMoney(invoice.total_cents, invoice.currency)}
          </p>
          <ChevronRight size={16} className="text-white/20 transition-transform group-hover:translate-x-0.5 group-hover:text-sky-400" />
        </div>
      </div>
    </button>
  );
}

function CustomerCard({
  customer,
  invoices,
  onEdit,
  onDelete,
}: {
  customer: InvoiceCustomer;
  invoices: InvoiceRecord[];
  onDelete: () => void;
  onEdit: () => void;
}) {
  // Only real, outgoing invoices count toward a customer's stats — quotes,
  // incoming bills, and cancelled invoices aren't actual invoiced revenue.
  const linked = invoices.filter(
    (invoice) =>
      invoice.customer_id === customer.id &&
      invoice.direction === "outgoing" &&
      (invoice.document_type || "invoice") === "invoice" &&
      invoice.status !== "cancelled",
  );
  const volume = linked.reduce((sum, invoice) => sum + invoice.total_cents, 0);

  return (
    <div className="rounded-[24px] border border-white/[0.08] bg-white/[0.025] p-5">
      <div className="flex items-start justify-between gap-3">
        <div>
          <p className="text-sm font-semibold text-white">{customer.name}</p>
          <p className="mt-1 text-xs text-white/32">{customer.email || "Keine E-Mail hinterlegt"}</p>
        </div>
        <div className="flex items-center gap-2">
          <button
            onClick={onEdit}
            className="rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-1.5 text-xs text-white/55 transition-colors hover:text-white"
          >
            Bearbeiten
          </button>
          <button
            onClick={onDelete}
            className="rounded-xl border border-rose-500/[0.14] bg-rose-500/[0.06] px-3 py-1.5 text-xs text-rose-300 transition-colors hover:bg-rose-500/[0.12]"
          >
            Löschen
          </button>
        </div>
      </div>

      <div className="mt-4 grid gap-3 sm:grid-cols-3">
        <div className="rounded-2xl border border-white/[0.06] bg-white/[0.02] p-3">
          <p className="text-[11px] uppercase tracking-widest text-white/28">Rechnungen</p>
          <p className="mt-2 text-xl font-black text-white">{linked.length}</p>
        </div>
        <div className="rounded-2xl border border-white/[0.06] bg-white/[0.02] p-3">
          <p className="text-[11px] uppercase tracking-widest text-white/28">Volumen</p>
          <p className="mt-2 text-xl font-black text-sky-300">{formatInvoiceMoney(volume)}</p>
        </div>
        <div className="rounded-2xl border border-white/[0.06] bg-white/[0.02] p-3">
          <p className="text-[11px] uppercase tracking-widest text-white/28">Zahlungsziel</p>
          <p className="mt-2 text-xl font-black text-violet-300">{customer.payment_terms_days} Tage</p>
        </div>
      </div>

      {(customer.address || customer.contact_person || customer.vat_id) && (
        <div className="mt-4 rounded-2xl border border-white/[0.06] bg-white/[0.02] p-3 text-sm text-white/45">
          {customer.contact_person ? <p>{customer.contact_person}</p> : null}
          {customer.vat_id ? <p>{customer.vat_id}</p> : null}
          {customer.address ? <p className="whitespace-pre-line">{customer.address}</p> : null}
        </div>
      )}
    </div>
  );
}

function CustomerEditor({
  initial,
  onCancel,
  onSave,
}: {
  initial: InvoiceCustomerUpsertInput;
  onCancel: () => void;
  onSave: (input: InvoiceCustomerUpsertInput) => Promise<void>;
}) {
  const [form, setForm] = useState<InvoiceCustomerUpsertInput>(initial);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  // Raw typed text for Zahlungsziel, so parsing/clamping doesn't snap the
  // field back to a number mid-edit (e.g. clearing it to retype).
  const [paymentTermsText, setPaymentTermsText] = useState(() => String(initial.payment_terms_days ?? 30));

  return (
    <div className={PAGE_BG}>
      <div className="mx-auto max-w-3xl space-y-6">
        <div className="flex items-center justify-between">
          <div className="flex items-center gap-3">
            <button
              onClick={onCancel}
              className="flex items-center gap-1.5 rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-sm text-white/60 transition-colors hover:text-white"
            >
              <ArrowLeft size={14} />
              Zurück
            </button>
            <h1 className="text-lg font-bold text-white">
              {initial.name ? "Kunde bearbeiten" : "Neuen Kunden anlegen"}
            </h1>
          </div>

          <button
            onClick={async () => {
              setSaving(true);
              setError("");
              try {
                await onSave(form);
              } catch (saveError) {
                setError(saveError instanceof Error ? saveError.message : "Kunde konnte nicht gespeichert werden.");
              } finally {
                setSaving(false);
              }
            }}
            className="rounded-xl border border-sky-500/[0.20] bg-sky-500/10 px-5 py-2 text-sm font-semibold text-sky-300 transition-colors hover:bg-sky-500/20"
          >
            {saving ? "Speichert..." : "Speichern"}
          </button>
        </div>

        {error ? <p className="text-sm text-rose-300">{error}</p> : null}

        <div className={`${CARD_SHELL} p-6`}>
          <div className="grid gap-4 md:grid-cols-2">
            <div>
              <label className="mb-1 block text-xs text-white/40">Name</label>
              <input
                className={INPUT_CLS}
                value={form.name}
                onChange={(event) => setForm((current) => ({ ...current, name: event.target.value }))}
              />
            </div>
            <div>
              <label className="mb-1 block text-xs text-white/40">E-Mail</label>
              <input
                className={INPUT_CLS}
                value={form.email || ""}
                onChange={(event) => setForm((current) => ({ ...current, email: event.target.value }))}
              />
            </div>
            <div>
              <label className="mb-1 block text-xs text-white/40">Kontaktperson</label>
              <input
                className={INPUT_CLS}
                value={form.contact_person || ""}
                onChange={(event) => setForm((current) => ({ ...current, contact_person: event.target.value }))}
              />
            </div>
            <div>
              <label className="mb-1 block text-xs text-white/40">USt-ID</label>
              <input
                className={INPUT_CLS}
                value={form.vat_id || ""}
                onChange={(event) => setForm((current) => ({ ...current, vat_id: event.target.value }))}
              />
            </div>
            <div>
              <label className="mb-1 block text-xs text-white/40">Zahlungsziel</label>
              <input
                type="text"
                inputMode="numeric"
                className={INPUT_CLS}
                value={paymentTermsText}
                onChange={(event) => {
                  const raw = event.target.value;
                  if (!/^[0-9]*$/.test(raw)) return;
                  setPaymentTermsText(raw);
                  setForm((current) => ({
                    ...current,
                    payment_terms_days: Number.parseInt(raw, 10) || 0,
                  }));
                }}
                onBlur={() => setPaymentTermsText(String(form.payment_terms_days || 30))}
              />
            </div>
            <div className="md:col-span-2">
              <label className="mb-1 block text-xs text-white/40">Adresse</label>
              <textarea
                rows={4}
                className={`${INPUT_CLS} resize-none`}
                value={form.address || ""}
                onChange={(event) => setForm((current) => ({ ...current, address: event.target.value }))}
              />
            </div>
            <div className="md:col-span-2">
              <label className="mb-1 block text-xs text-white/40">Notizen</label>
              <textarea
                rows={4}
                className={`${INPUT_CLS} resize-none`}
                value={form.notes || ""}
                onChange={(event) => setForm((current) => ({ ...current, notes: event.target.value }))}
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

/**
 * Its own component (rather than inline in a .map) so typing in one row's
 * Menge/Preis field doesn't force the whole ~500-line invoice form to
 * re-render on every keystroke, and each field tracks its own raw typed
 * text instead of snapping to a reformatted value (e.g. "1." -> "1",
 * "" -> "0.00") mid-entry — that reformat-on-every-keystroke was what
 * made the rows feel like they were jumping around while editing.
 */
const LineItemRow = memo(function LineItemRow({
  item,
  removable,
  onUpdate,
  onRemove,
}: {
  item: InvoiceItemDraft;
  removable: boolean;
  onUpdate: (id: string, patch: Partial<InvoiceItemDraft>) => void;
  onRemove: (id: string) => void;
}) {
  const id = item.id as string;
  const [quantityText, setQuantityText] = useState(() => String(item.quantity));
  const [priceText, setPriceText] = useState(() =>
    item.unit_price_cents === 0 ? "" : (item.unit_price_cents / 100).toFixed(2),
  );

  return (
    <div className="grid grid-cols-[1fr_1fr_36px] gap-2 items-center sm:grid-cols-[1fr_70px_110px_36px]">
      <input
        className={`${INPUT_CLS} col-span-3 sm:col-span-1`}
        placeholder="Leistung oder Position"
        value={item.description}
        onChange={(event) => onUpdate(id, { description: event.target.value })}
      />
      <input
        type="text"
        inputMode="decimal"
        placeholder="0"
        className={`${INPUT_CLS} text-right`}
        value={quantityText}
        onChange={(event) => {
          const raw = event.target.value;
          if (!/^[0-9]*[.,]?[0-9]*$/.test(raw)) return;
          setQuantityText(raw);
          onUpdate(id, { quantity: Number.parseFloat(raw.replace(",", ".")) || 0 });
        }}
        onBlur={() => setQuantityText(String(item.quantity))}
      />
      <input
        type="text"
        inputMode="decimal"
        placeholder="0,00"
        className={`${INPUT_CLS} text-right`}
        value={priceText}
        onChange={(event) => {
          const raw = event.target.value;
          if (!/^[0-9]*[.,]?[0-9]*$/.test(raw)) return;
          setPriceText(raw);
          onUpdate(id, {
            unit_price_cents: Math.round((Number.parseFloat(raw.replace(",", ".")) || 0) * 100),
          });
        }}
        onBlur={() =>
          setPriceText(item.unit_price_cents === 0 ? "" : (item.unit_price_cents / 100).toFixed(2))
        }
      />
      <button
        onClick={() => onRemove(id)}
        disabled={!removable}
        className="flex items-center justify-center rounded-lg p-1.5 text-white/30 transition-colors hover:bg-rose-500/10 hover:text-rose-400 disabled:cursor-default disabled:opacity-20 disabled:hover:bg-transparent disabled:hover:text-white/30"
      >
        <Trash2 size={13} />
      </button>
    </div>
  );
});

function InvoiceEditor({
  customers,
  folders,
  initial,
  invoices,
  isNew,
  onCancel,
  onSave,
}: {
  customers: InvoiceCustomer[];
  folders: InvoiceFolder[];
  initial: InvoiceDraft;
  invoices: InvoiceRecord[];
  isNew: boolean;
  onCancel: () => void;
  onSave: (input: InvoiceUpsertInput) => Promise<void>;
}) {
  const [draft, setDraft] = useState(initial);
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");
  // Raw typed text for the MwSt. rate, so parsing doesn't snap the field
  // back to a whole number mid-edit (e.g. typing "19." for "19,5").
  const [taxRateText, setTaxRateText] = useState(() => String(initial.tax_rate));

  const updateItem = useCallback((id: string, patch: Partial<InvoiceItemDraft>) => {
    setDraft((current) => ({
      ...current,
      items: current.items.map((entry) => (entry.id === id ? { ...entry, ...patch } : entry)),
    }));
  }, []);

  const removeItem = useCallback((id: string) => {
    setDraft((current) => ({
      ...current,
      items: current.items.length > 1 ? current.items.filter((entry) => entry.id !== id) : current.items,
    }));
  }, []);

  const selectedCustomer = customers.find((customer) => customer.id === draft.customer_id) || null;
  const subtotal = draft.items.reduce((sum, item) => sum + Math.round(item.quantity * item.unit_price_cents), 0);
  const taxEnabled = draft.tax_enabled ?? draft.tax_rate > 0;
  const taxAmount = taxEnabled ? Math.round((subtotal * draft.tax_rate) / 100) : 0;
  const total = subtotal + taxAmount;
  const documentType = draft.document_type || "invoice";
  const documentLabel = getDirectionLabel(draft.direction, documentType);
  const counterpartLabel = getCounterpartyLabel(draft.direction, documentType);

  const applyCustomer = useCallback(
    (customerId: string) => {
      const customer = customers.find((entry) => entry.id === customerId) || null;
      if (!customer) {
        setDraft((current) => ({ ...current, customer_id: "" }));
        return;
      }

      setDraft((current) => ({
        ...current,
        counterparty_address: customer.address,
        counterparty_email: customer.email,
        counterparty_name: customer.name,
        customer_id: customer.id,
        due_date: addDays(current.issue_date, customer.payment_terms_days),
      }));
    },
    [customers],
  );

  return (
    <div className={PAGE_BG}>
      <div className="mx-auto max-w-5xl space-y-6">
        <div className="flex items-center justify-between gap-4">
          <div className="flex items-center gap-3">
            <button
              onClick={onCancel}
              className="flex items-center gap-1.5 rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-sm text-white/60 transition-colors hover:text-white"
            >
              <ArrowLeft size={14} />
              Zurück
            </button>
            <div>
              <p className="text-xs uppercase tracking-widest text-white/26">{documentLabel}</p>
              <h1 className="text-lg font-bold text-white">
                {isNew ? `Neues ${documentLabel}` : `${documentLabel} bearbeiten`}
              </h1>
            </div>
          </div>

          <button
            onClick={async () => {
              setSaving(true);
              setError("");
              try {
                await onSave({
                  accent_color: draft.accent_color || "#7dd3fc",
                  company_address: draft.company_address || "",
                  company_email: draft.company_email || "",
                  company_name: draft.company_name || "Mindavio",
                  company_phone: draft.company_phone || "",
                  company_vat_id: draft.company_vat_id || "",
                  company_website: draft.company_website || "",
                  counterparty_address: draft.counterparty_address,
                  counterparty_email: draft.counterparty_email,
                  counterparty_name: draft.counterparty_name,
                  customer_id: draft.customer_id || null,
                  document_type: documentType,
                  direction: draft.direction,
                  due_date: draft.due_date,
                  folder_id: draft.folder_id || null,
                  inbox_at: draft.inbox_at || null,
                  inbox_note: draft.inbox_note || "",
                  invoice_number: draft.invoice_number,
                  issue_date: draft.issue_date,
                  logo_url: draft.logo_url || "",
                  items: draft.items.map((item, index) => ({
                    description: item.description,
                    quantity: item.quantity,
                    sort_order: index,
                    unit_price_cents: item.unit_price_cents,
                  })),
                  notes: draft.notes,
                  source: draft.source,
                  status: draft.status,
                  tax_enabled: taxEnabled,
                  tax_rate: draft.tax_rate,
                  title: draft.title,
                });
              } catch (saveError) {
                setError(saveError instanceof Error ? saveError.message : "Rechnung konnte nicht gespeichert werden.");
              } finally {
                setSaving(false);
              }
            }}
            className="rounded-xl border border-sky-500/[0.20] bg-sky-500/10 px-5 py-2 text-sm font-semibold text-sky-300 transition-colors hover:bg-sky-500/20"
          >
            {saving ? "Speichert..." : "Speichern"}
          </button>
        </div>

        {error ? <p className="text-sm text-rose-300">{error}</p> : null}

        <div className="grid gap-5 lg:grid-cols-2">
          <div className="space-y-5">
            <div className="rounded-[28px] border border-sky-500/[0.14] bg-[radial-gradient(ellipse_at_top_left,rgba(14,165,233,0.07),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] p-6">
              <h2 className="text-xs font-semibold uppercase tracking-widest text-white/30">Design & Absender</h2>
              <div className="mt-4 grid gap-3 sm:grid-cols-2">
                <div>
                  <label className="mb-1 block text-xs text-white/40">Firmenname</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.company_name || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_name: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Logo URL</label>
                  <input
                    className={INPUT_CLS}
                    placeholder="https://.../logo.png oder Data-URL"
                    value={draft.logo_url || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, logo_url: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">E-Mail</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.company_email || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_email: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Telefon</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.company_phone || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_phone: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Website</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.company_website || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_website: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">USt-ID / Steuerhinweis</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.company_vat_id || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_vat_id: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Akzentfarbe</label>
                  <input
                    type="color"
                    className="h-11 w-full rounded-xl border border-white/[0.08] bg-white/[0.03] px-2 py-2"
                    value={draft.accent_color || "#7dd3fc"}
                    onChange={(event) => setDraft((current) => ({ ...current, accent_color: event.target.value }))}
                  />
                </div>
                <div className="sm:col-span-2">
                  <label className="mb-1 block text-xs text-white/40">Absenderadresse</label>
                  <textarea
                    rows={3}
                    className={`${INPUT_CLS} resize-none`}
                    value={draft.company_address || ""}
                    onChange={(event) => setDraft((current) => ({ ...current, company_address: event.target.value }))}
                  />
                </div>
              </div>
            </div>

            <div className="rounded-[28px] border border-sky-500/[0.14] bg-[radial-gradient(ellipse_at_top_left,rgba(14,165,233,0.08),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] p-6">
              <h2 className="text-xs font-semibold uppercase tracking-widest text-white/30">{documentLabel}details</h2>
              <div className="mt-4 grid gap-3 sm:grid-cols-2">
                <div>
                  <label className="mb-1 block text-xs text-white/40">Dokument</label>
                  <select
                    value={documentType}
                    onChange={(event) => {
                      const nextDocumentType = event.target.value as InvoiceDocumentType;
                      const nextDirection = nextDocumentType === "quote" ? "outgoing" : draft.direction;
                      setDraft((current) => ({
                        ...current,
                        document_type: nextDocumentType,
                        direction: nextDirection,
                        invoice_number: nextInvoiceNumber(invoices, nextDirection, nextDocumentType),
                        status: nextDocumentType === "quote" ? "draft" : nextDirection === "incoming" ? "received" : "draft",
                      }));
                    }}
                    className={INPUT_CLS}
                  >
                    <option value="invoice" className="bg-[#0a0a0d]">Rechnung</option>
                    <option value="quote" className="bg-[#0a0a0d]">Angebot</option>
                  </select>
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Richtung</label>
                  <select
                    value={draft.direction}
                    disabled={documentType === "quote"}
                    onChange={(event) =>
                      setDraft((current) => ({
                        ...current,
                        direction: event.target.value as InvoiceDirection,
                        invoice_number: nextInvoiceNumber(
                          invoices,
                          event.target.value as InvoiceDirection,
                          current.document_type || "invoice",
                        ),
                        status: event.target.value === "incoming" ? "received" : "draft",
                      }))
                    }
                    className={INPUT_CLS}
                  >
                    <option value="outgoing" className="bg-[#0a0a0d]">Ausgehend</option>
                    <option value="incoming" className="bg-[#0a0a0d]">Eingehend</option>
                  </select>
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Status</label>
                  <select
                    value={draft.status}
                    onChange={(event) => setDraft((current) => ({ ...current, status: event.target.value as InvoiceStatus }))}
                    className={INPUT_CLS}
                  >
                    {Object.entries(STATUS_CONFIG).map(([value, cfg]) => (
                      <option key={value} value={value} className="bg-[#0a0a0d]">
                        {cfg.label}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">{documentLabel}nummer</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.invoice_number}
                    onChange={(event) => setDraft((current) => ({ ...current, invoice_number: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Ordner</label>
                  <select
                    value={draft.folder_id}
                    onChange={(event) => setDraft((current) => ({ ...current, folder_id: event.target.value }))}
                    className={INPUT_CLS}
                  >
                    <option value="" className="bg-[#0a0a0d]">Kein Ordner</option>
                    {folders.map((folder) => (
                      <option key={folder.id} value={folder.id} className="bg-[#0a0a0d]">
                        {folder.name}
                      </option>
                    ))}
                  </select>
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Titel</label>
                  <input
                    className={INPUT_CLS}
                    placeholder={
                      documentType === "quote"
                        ? "Website Relaunch"
                        : draft.direction === "incoming"
                          ? "Hosting März"
                          : "Beratung April"
                    }
                    value={draft.title}
                    onChange={(event) => setDraft((current) => ({ ...current, title: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">
                    {documentType === "quote" ? "Angebotsdatum" : "Ausgestellt / erhalten"}
                  </label>
                  <input
                    type="date"
                    className={INPUT_CLS}
                    value={draft.issue_date}
                    onChange={(event) => setDraft((current) => ({ ...current, issue_date: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">
                    {documentType === "quote" ? "Gültig bis" : "Fälligkeitsdatum"}
                  </label>
                  <input
                    type="date"
                    className={INPUT_CLS}
                    value={draft.due_date}
                    onChange={(event) => setDraft((current) => ({ ...current, due_date: event.target.value }))}
                  />
                </div>
              </div>
            </div>

            <div className="rounded-[28px] border border-violet-500/[0.14] bg-[radial-gradient(ellipse_at_top_left,rgba(139,92,246,0.07),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] p-6">
              <div className="flex items-center justify-between gap-3">
                <h2 className="text-xs font-semibold uppercase tracking-widest text-white/30">{counterpartLabel}</h2>
                <select
                  value={draft.customer_id}
                  onChange={(event) => applyCustomer(event.target.value)}
                  className="rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-xs text-white/65 outline-none transition-colors focus:border-violet-500/[0.30]"
                >
                  <option value="" className="bg-[#0a0a0d]">{counterpartLabel} frei eingeben</option>
                  {customers.map((customer) => (
                    <option key={customer.id} value={customer.id} className="bg-[#0a0a0d]">
                      {customer.name}
                    </option>
                  ))}
                </select>
              </div>

              <div className="mt-4 space-y-3">
                <div>
                  <label className="mb-1 block text-xs text-white/40">Name</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.counterparty_name}
                    onChange={(event) => setDraft((current) => ({ ...current, counterparty_name: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">E-Mail</label>
                  <input
                    className={INPUT_CLS}
                    value={draft.counterparty_email}
                    onChange={(event) => setDraft((current) => ({ ...current, counterparty_email: event.target.value }))}
                  />
                </div>
                <div>
                  <label className="mb-1 block text-xs text-white/40">Adresse</label>
                  <textarea
                    rows={3}
                    className={`${INPUT_CLS} resize-none`}
                    value={draft.counterparty_address}
                    onChange={(event) => setDraft((current) => ({ ...current, counterparty_address: event.target.value }))}
                  />
                </div>
              </div>

              {selectedCustomer ? (
                <div className="mt-4 rounded-2xl border border-violet-500/[0.14] bg-violet-500/[0.05] p-4 text-sm text-violet-100/75">
                  <p className="font-semibold text-violet-200">{selectedCustomer.name}</p>
                  <p className="mt-1 text-violet-100/60">
                    Standard-Ziel: {selectedCustomer.payment_terms_days} Tage · {selectedCustomer.contact_person || "kein Kontakt hinterlegt"}
                  </p>
                </div>
              ) : null}
            </div>
          </div>

          <div className="space-y-5">
            <div className="rounded-[28px] border border-amber-500/[0.14] bg-[radial-gradient(ellipse_at_top_left,rgba(245,158,11,0.07),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] p-6">
              <h2 className="text-xs font-semibold uppercase tracking-widest text-white/30">Positionen</h2>

              <div className="mt-4 hidden gap-2 px-1 text-[10px] uppercase tracking-wider text-white/30 sm:grid sm:grid-cols-[1fr_70px_110px_36px]">
                <span>Beschreibung</span>
                <span className="text-right">Menge</span>
                <span className="text-right">Preis</span>
                <span />
              </div>

              <div className="mt-2 space-y-2">
                {draft.items.map((item) => (
                  <LineItemRow
                    key={item.id}
                    item={item}
                    removable={draft.items.length > 1}
                    onUpdate={updateItem}
                    onRemove={removeItem}
                  />
                ))}
              </div>

              <button
                onClick={() =>
                  setDraft((current) => ({
                    ...current,
                    items: [
                      ...current.items,
                      {
                        id: crypto.randomUUID(),
                        description: "",
                        quantity: 1,
                        unit_price_cents: 0,
                      },
                    ],
                  }))
                }
                className="mt-3 inline-flex items-center gap-1.5 text-xs text-amber-400/75 transition-colors hover:text-amber-300"
              >
                <Plus size={13} />
                Position hinzufügen
              </button>

              <div className="mt-6 space-y-2 border-t border-white/[0.08] pt-4">
                <div className="flex items-center justify-between text-sm text-white/60">
                  <span>Netto</span>
                  <span>{formatInvoiceMoney(subtotal)}</span>
                </div>
                <div className="flex items-center justify-between text-sm text-white/60">
                  <div className="flex items-center gap-2">
                    <label className="flex items-center gap-2">
                      <input
                        type="checkbox"
                        checked={taxEnabled}
                        onChange={(event) => {
                          const checked = event.target.checked;
                          const nextRate = checked && draft.tax_rate === 0 ? 19 : draft.tax_rate;
                          setTaxRateText(String(nextRate));
                          setDraft((current) => ({ ...current, tax_enabled: checked, tax_rate: nextRate }));
                        }}
                        className="h-4 w-4 accent-sky-400"
                      />
                      <span>MwSt.</span>
                    </label>
                    <input
                      type="text"
                      inputMode="decimal"
                      disabled={!taxEnabled}
                      value={taxRateText}
                      onChange={(event) => {
                        const raw = event.target.value;
                        if (!/^[0-9]*[.,]?[0-9]*$/.test(raw)) return;
                        setTaxRateText(raw);
                        const parsed = Number.parseFloat(raw.replace(",", "."));
                        setDraft((current) => ({
                          ...current,
                          tax_rate: Number.isFinite(parsed) ? Math.min(100, Math.max(0, parsed)) : 0,
                        }));
                      }}
                      onBlur={() => setTaxRateText(String(draft.tax_rate))}
                      className="w-16 rounded-lg border border-white/[0.08] bg-white/[0.04] px-2 py-1 text-center text-xs text-white outline-none disabled:opacity-40"
                    />
                    <span className="text-xs">%</span>
                  </div>
                  <span>{formatInvoiceMoney(taxAmount)}</span>
                </div>
                <div className="flex items-center justify-between border-t border-white/[0.08] pt-2 text-base font-bold">
                  <span className="text-white">Gesamt</span>
                  <span className="text-amber-300">{formatInvoiceMoney(total)}</span>
                </div>
              </div>
            </div>

            <div className="rounded-[28px] border border-white/[0.08] bg-white/[0.02] p-6">
              <h2 className="text-xs font-semibold uppercase tracking-widest text-white/30">Notizen</h2>
              <textarea
                rows={5}
                className={`${INPUT_CLS} mt-4 resize-none`}
                value={draft.notes}
                onChange={(event) => setDraft((current) => ({ ...current, notes: event.target.value }))}
                placeholder={
                  documentType === "quote"
                    ? "z. B. Gültigkeit, Leistungsumfang, nächste Schritte"
                    : draft.direction === "incoming"
                    ? "z. B. Vertragsreferenz, Freigabehinweis, Zahlungsnotiz"
                    : "z. B. Leistungszeitraum, Zahlungsziel, Projektreferenz"
                }
              />
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function InvoiceFilesCard({
  invoice,
  logInvoiceEvent,
}: {
  invoice: InvoiceRecord;
  logInvoiceEvent: (invoiceId: string, eventType: "attachment_added" | "attachment_removed", title: string, details?: Record<string, unknown>) => Promise<void>;
}) {
  const inputRef = useRef<HTMLInputElement>(null);
  const { attachments, deleteAttachment, error, loading, uploadFiles, uploading } = useAttachments({
    entityId: invoice.id,
    entityType: "invoice",
  });

  return (
    <div className={`${CARD_SHELL} p-6`}>
      <div className="flex items-center justify-between gap-3">
        <div>
          <p className="text-xs font-semibold uppercase tracking-widest text-white/30">Dateien</p>
          <p className="mt-1 text-sm text-white/38">
            {invoice.direction === "incoming"
              ? "PDFs, Scans und Belege direkt an diese Eingangsrechnung hängen."
              : "Angebote, signierte PDFs oder Freigaben an dieser Rechnung sammeln."}
          </p>
        </div>
        <div>
          <input
            ref={inputRef}
            type="file"
            multiple
            className="hidden"
            onChange={async (event) => {
              const files = event.target.files;
              if (!files || files.length === 0) return;
              const uploaded = await uploadFiles(files);
              if (uploaded.length > 0) {
                await logInvoiceEvent(invoice.id, "attachment_added", `${uploaded.length} Datei(en) hinzugefügt`, {
                  count: uploaded.length,
                });
              }
              event.target.value = "";
            }}
          />
          <button
            onClick={() => inputRef.current?.click()}
            className="inline-flex items-center gap-2 rounded-2xl border border-violet-500/[0.18] bg-violet-500/10 px-4 py-2 text-sm font-semibold text-violet-300 transition-colors hover:bg-violet-500/18"
          >
            <Upload size={14} />
            {uploading ? "Lädt..." : "Datei hochladen"}
          </button>
        </div>
      </div>

      {error ? <p className="mt-4 text-sm text-rose-300">{error}</p> : null}

      {loading ? (
        <div className="mt-4 rounded-2xl border border-white/[0.06] bg-white/[0.02] p-4 text-sm text-white/32">
          Dateien werden geladen...
        </div>
      ) : attachments.length === 0 ? (
        <div className="mt-4 rounded-2xl border border-dashed border-white/[0.08] bg-white/[0.02] p-4 text-sm text-white/32">
          Noch keine Dateien an dieser Rechnung.
        </div>
      ) : (
        <div className="mt-4 space-y-2">
          {attachments.map((attachment) => (
            <div
              key={attachment.id}
              className="flex flex-wrap items-center justify-between gap-3 rounded-2xl border border-white/[0.06] bg-white/[0.02] p-3"
            >
              <div className="min-w-0">
                <p className="truncate text-sm font-medium text-white">{attachment.file_name}</p>
                <p className="mt-1 text-xs text-white/32">
                  {formatFileSize(attachment.size_bytes)} · hinzugefügt {formatRelativeDate(attachment.created_at)}
                </p>
              </div>

              <div className="flex items-center gap-2">
                <a
                  href={attachment.public_url}
                  target="_blank"
                  rel="noreferrer"
                  className="inline-flex items-center gap-1.5 rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-xs text-white/55 transition-colors hover:text-white"
                >
                  <FileText size={13} />
                  Öffnen
                </a>
                <button
                  onClick={async () => {
                    await deleteAttachment(attachment);
                    await logInvoiceEvent(invoice.id, "attachment_removed", "Datei entfernt", {
                      file_name: attachment.file_name,
                    });
                  }}
                  className="inline-flex items-center gap-1.5 rounded-xl border border-rose-500/[0.12] bg-rose-500/[0.05] px-3 py-2 text-xs text-rose-300 transition-colors hover:bg-rose-500/[0.12]"
                >
                  <Trash2 size={13} />
                  Entfernen
                </button>
              </div>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function InvoiceDetail({
  invoice,
  logInvoiceEvent,
  onBack,
  onDelete,
  onEdit,
  onExport,
  onMoveToInbox,
  onOpenSend,
  onStatusChange,
}: {
  invoice: InvoiceRecord;
  logInvoiceEvent: (invoiceId: string, eventType: "attachment_added" | "attachment_removed", title: string, details?: Record<string, unknown>) => Promise<void>;
  onBack: () => void;
  onDelete: () => void;
  onEdit: () => void;
  onExport: () => Promise<void>;
  onMoveToInbox: () => Promise<void>;
  onOpenSend: () => void;
  onStatusChange: (status: InvoiceStatus) => Promise<void>;
}) {
  const status = resolveInvoiceStatus(invoice);
  const transitions = getStatusTransitions(invoice);
  const documentLabel = getInvoiceDocumentLabel(invoice);
  const isOutgoing = invoice.direction === "outgoing";

  return (
    <div className={PAGE_BG}>
      <div className="mx-auto max-w-5xl space-y-5">
        <div className="flex flex-wrap items-start justify-between gap-3">
          <button
            onClick={onBack}
            className="flex items-center gap-1.5 rounded-xl border border-white/[0.08] bg-white/[0.03] px-3 py-2 text-sm text-white/60 transition-colors hover:text-white"
          >
            <ArrowLeft size={14} />
            Übersicht
          </button>

          <div className="flex flex-wrap items-center justify-end gap-2">
            <button
              onClick={() => void onExport()}
              className="flex items-center gap-1.5 rounded-xl border border-violet-500/[0.18] bg-violet-500/10 px-3 py-2 text-sm font-medium text-violet-300 transition-colors hover:bg-violet-500/20"
            >
              <Download size={14} />
              Als PDF exportieren
            </button>
            {isOutgoing ? (
              <button
                onClick={onOpenSend}
                className="flex items-center gap-1.5 rounded-xl border border-sky-500/[0.18] bg-sky-500/10 px-3 py-2 text-sm font-medium text-sky-300 transition-colors hover:bg-sky-500/20"
              >
                <Mail size={14} />
                {documentLabel} versenden
              </button>
            ) : null}
            <button
              onClick={() => void onMoveToInbox()}
              disabled={Boolean(invoice.inbox_at)}
              className="flex items-center gap-1.5 rounded-xl border border-amber-500/[0.18] bg-amber-500/10 px-3 py-2 text-sm font-medium text-amber-300 transition-colors hover:bg-amber-500/20 disabled:cursor-not-allowed disabled:opacity-45"
            >
              <Inbox size={14} />
              {invoice.inbox_at ? "In Inbox" : "In Inbox legen"}
            </button>
            {transitions.map((next) => (
              <button
                key={next}
                onClick={() => void onStatusChange(next)}
                className={`rounded-xl px-3 py-2 text-sm font-medium transition-colors ${STATUS_CONFIG[next].badgeCls}`}
              >
                Als {STATUS_CONFIG[next].label} markieren
              </button>
            ))}
            <button
              onClick={onEdit}
              className="flex items-center gap-1.5 rounded-xl border border-white/[0.10] bg-white/[0.03] px-3 py-2 text-sm text-white/60 transition-colors hover:text-white"
            >
              <Edit3 size={14} />
              Bearbeiten
            </button>
            <button
              onClick={onDelete}
              className="flex items-center gap-1.5 rounded-xl border border-rose-500/[0.14] bg-rose-500/[0.06] px-3 py-2 text-sm text-rose-300 transition-colors hover:bg-rose-500/[0.12]"
            >
              <Trash2 size={14} />
              Löschen
            </button>
          </div>
        </div>

        <div className="rounded-[28px] border border-white/[0.08] p-8" style={{ background: "radial-gradient(ellipse at top left, rgba(14,165,233,0.08), rgba(10,8,18,0.98) 55%, rgba(9,8,15,1) 100%)" }}>
          <div className="flex items-start justify-between border-b border-white/[0.08] pb-6">
            <div>
              <div className="mb-4 flex items-center gap-3">
                {invoice.logo_url ? (
                  // eslint-disable-next-line @next/next/no-img-element
                  <img
                    src={invoice.logo_url}
                    alt={`${invoice.company_name || "Firma"} Logo`}
                    className="h-12 w-12 rounded-2xl border border-white/[0.08] bg-white object-contain p-1"
                  />
                ) : (
                  <div
                    className="flex h-12 w-12 items-center justify-center rounded-2xl border border-white/[0.08] text-sm font-black text-black"
                    style={{ backgroundColor: invoice.accent_color || "#7dd3fc" }}
                  >
                    {(invoice.company_name || "M").slice(0, 1).toUpperCase()}
                  </div>
                )}
                <div>
                  <p className="font-bold text-white">{invoice.company_name || "Mindavio"}</p>
                  <p className="text-xs text-white/35">{invoice.company_website || invoice.company_email || ""}</p>
                </div>
              </div>
              <p className="text-[10px] font-bold uppercase tracking-[0.2em] text-white/30">
                {documentLabel}
              </p>
              <p className={`mt-1 text-3xl font-black tabular-nums ${STATUS_CONFIG[status].accent}`}>{invoice.invoice_number}</p>
              <p className="mt-2 text-sm text-white/50">{getInvoiceTitle(invoice)}</p>
            </div>
            <div className="space-y-2 text-right">
              <StatusBadge status={status} />
              <p className="text-xs text-white/40">
                {invoice.document_type === "quote" ? "Angeboten" : invoice.direction === "incoming" ? "Erhalten" : "Ausgestellt"}:{" "}
                {formatInvoiceDate(invoice.issue_date)}
              </p>
              <p className="text-xs text-white/40">
                {invoice.document_type === "quote" ? "Gültig bis" : "Fällig"}: {formatInvoiceDate(invoice.due_date)}
              </p>
              {(invoice.company_address || invoice.company_phone || invoice.company_vat_id) ? (
                <div className="mt-4 max-w-[260px] whitespace-pre-line text-xs leading-relaxed text-white/35">
                  {invoice.company_address ? <p>{invoice.company_address}</p> : null}
                  {invoice.company_phone ? <p>{invoice.company_phone}</p> : null}
                  {invoice.company_vat_id ? <p>{invoice.company_vat_id}</p> : null}
                </div>
              ) : null}
            </div>
          </div>

          <div className="border-b border-white/[0.08] py-5">
            <p className="mb-2 text-[10px] font-semibold uppercase tracking-widest text-white/30">
              {invoice.document_type === "quote"
                ? "Angebotsempfänger"
                : invoice.direction === "incoming"
                  ? "Anbieter"
                  : "Rechnungsempfänger"}
            </p>
            <p className="font-semibold text-white">{invoice.counterparty_name || "—"}</p>
            {invoice.counterparty_email ? <p className="text-sm text-white/50">{invoice.counterparty_email}</p> : null}
            {invoice.counterparty_address ? (
              <p className="mt-1 whitespace-pre-line text-sm text-white/40">{invoice.counterparty_address}</p>
            ) : null}
          </div>

          <div className="border-b border-white/[0.08] py-5 overflow-x-auto">
            <table className="w-full min-w-[480px] text-sm">
              <thead>
                <tr className="text-[10px] uppercase tracking-widest text-white/30">
                  <th className="pb-3 text-left">Beschreibung</th>
                  <th className="pb-3 text-right">Menge</th>
                  <th className="pb-3 text-right">Einzelpreis</th>
                  <th className="pb-3 text-right">Gesamt</th>
                </tr>
              </thead>
              <tbody className="divide-y divide-white/[0.05]">
                {(invoice.items || []).map((item) => (
                  <tr key={item.id}>
                    <td className="py-2.5 text-white/70">{item.description || "—"}</td>
                    <td className="py-2.5 text-right text-white/50">{item.quantity}</td>
                    <td className="py-2.5 text-right text-white/50">{formatInvoiceMoney(item.unit_price_cents, invoice.currency)}</td>
                    <td className="py-2.5 text-right font-medium text-white/80">
                      {formatInvoiceMoney(Math.round(item.quantity * item.unit_price_cents), invoice.currency)}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="pt-5 space-y-2">
            <div className="flex justify-between text-sm text-white/50">
              <span>Nettobetrag</span>
              <span>{formatInvoiceMoney(invoice.subtotal_cents, invoice.currency)}</span>
            </div>
            <div className="flex justify-between text-sm text-white/50">
              <span>{invoice.tax_enabled === false ? "MwSt. nicht berechnet" : `MwSt. ${invoice.tax_rate}%`}</span>
              <span>{formatInvoiceMoney(invoice.tax_cents, invoice.currency)}</span>
            </div>
            <div className="flex justify-between border-t border-white/[0.08] pt-3 text-lg font-black">
              <span className="text-white">{invoice.document_type === "quote" ? "Angebotssumme" : "Gesamtbetrag"}</span>
              <span className={STATUS_CONFIG[status].accent}>{formatInvoiceMoney(invoice.total_cents, invoice.currency)}</span>
            </div>
          </div>

          {invoice.notes ? (
            <div className="mt-5 rounded-xl border border-white/[0.06] bg-white/[0.02] p-4">
              <p className="mb-1 text-[10px] font-semibold uppercase tracking-widest text-white/30">Anmerkungen</p>
              <p className="text-sm text-white/50">{invoice.notes}</p>
            </div>
          ) : null}
        </div>

        <div className="grid gap-5 xl:grid-cols-[1.05fr_0.95fr]">
          <InvoiceFilesCard invoice={invoice} logInvoiceEvent={logInvoiceEvent} />

          <div className={`${CARD_SHELL} p-6`}>
            <div className="flex items-center justify-between gap-3">
              <div>
                <p className="text-xs font-semibold uppercase tracking-widest text-white/30">Timeline</p>
                <p className="mt-1 text-sm text-white/38">Erstellung, Exporte, Versandvorbereitung und Statuswechsel auf einen Blick.</p>
              </div>
            </div>

            {(invoice.events || []).length === 0 ? (
              <div className="mt-4 rounded-2xl border border-dashed border-white/[0.08] bg-white/[0.02] p-4 text-sm text-white/32">
                Noch keine Timeline-Einträge.
              </div>
            ) : (
              <div className="mt-4 space-y-3">
                {(invoice.events || []).map((event) => (
                  <div key={event.id} className="rounded-2xl border border-white/[0.06] bg-white/[0.02] p-4">
                    <div className="flex items-center justify-between gap-3">
                      <p className="text-sm font-semibold text-white">{event.title}</p>
                      <p className="text-xs text-white/30">{formatRelativeDate(event.created_at)}</p>
                    </div>
                    {Object.keys(event.details || {}).length > 0 ? (
                      <div className="mt-2 flex flex-wrap gap-2">
                        {Object.entries(event.details || {}).map(([key, value]) => (
                          <span key={key} className="rounded-full border border-white/[0.06] bg-white/[0.03] px-2.5 py-1 text-[11px] text-white/42">
                            {key}: {String(value)}
                          </span>
                        ))}
                      </div>
                    ) : null}
                  </div>
                ))}
              </div>
            )}
          </div>
        </div>
      </div>
    </div>
  );
}

function SendInvoiceModal({
  invoice,
  onClose,
  onSend,
}: {
  invoice: InvoiceRecord;
  onClose: () => void;
  onSend: (payload: { body: string; subject: string; to: string }) => Promise<void>;
}) {
  const [to, setTo] = useState(invoice.counterparty_email || "");
  const documentLabel = getInvoiceDocumentLabel(invoice);
  const [subject, setSubject] = useState(`${documentLabel} ${invoice.invoice_number}`);
  const [body, setBody] = useState(
    `Hallo,\n\nanbei sende ich dir ${documentLabel === "Angebot" ? "das Angebot" : "die Rechnung"} ${invoice.invoice_number} über ${formatInvoiceMoney(
      invoice.total_cents,
      invoice.currency,
    )}.\n\nViele Grüße`,
  );
  const [sending, setSending] = useState(false);
  const [error, setError] = useState("");

  return (
    <Modal
      open
      onClose={onClose}
      title={`${documentLabel} versenden`}
      className="max-w-2xl border-white/[0.08] bg-[radial-gradient(ellipse_at_top_left,rgba(14,165,233,0.08),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] text-white"
    >
      <div className="space-y-4">
        <p className="text-sm text-white/45">
          Mindavio erstellt einen Gmail-Entwurf mit personalisierter PDF als Anhang. Dafür muss Gmail in Integrationen verbunden sein.
        </p>

        <div>
          <label className="mb-1 block text-xs text-white/40">Empfänger</label>
          <input className={INPUT_CLS} value={to} onChange={(event) => setTo(event.target.value)} />
        </div>
        <div>
          <label className="mb-1 block text-xs text-white/40">Betreff</label>
          <input className={INPUT_CLS} value={subject} onChange={(event) => setSubject(event.target.value)} />
        </div>
        <div>
          <label className="mb-1 block text-xs text-white/40">Nachricht</label>
          <textarea
            rows={6}
            className={`${INPUT_CLS} resize-none`}
            value={body}
            onChange={(event) => setBody(event.target.value)}
          />
        </div>

        {error ? <p className="text-sm text-rose-300">{error}</p> : null}

        <div className="flex items-center justify-end gap-2">
          <button
            onClick={onClose}
            className="rounded-xl border border-white/[0.08] bg-white/[0.03] px-4 py-2 text-sm text-white/55 transition-colors hover:text-white"
          >
            Abbrechen
          </button>
          <button
            onClick={async () => {
              setSending(true);
              setError("");
              try {
                await onSend({ body, subject, to });
              } catch (sendError) {
                setError(sendError instanceof Error ? sendError.message : "Versand konnte nicht vorbereitet werden.");
              } finally {
                setSending(false);
              }
            }}
            className="rounded-xl border border-sky-500/[0.20] bg-sky-500/10 px-4 py-2 text-sm font-semibold text-sky-300 transition-colors hover:bg-sky-500/20"
          >
            {sending ? "Bereitet vor..." : "Gmail-Entwurf erstellen"}
          </button>
        </div>
      </div>
    </Modal>
  );
}

function FolderModal({
  onClose,
  onSave,
}: {
  onClose: () => void;
  onSave: (input: InvoiceFolderUpsertInput) => Promise<void>;
}) {
  const [form, setForm] = useState<InvoiceFolderUpsertInput>({
    color: "#8b5cf6",
    icon: "folder",
    name: "",
    slug: "",
    sort_order: 0,
  });
  const [saving, setSaving] = useState(false);
  const [error, setError] = useState("");

  return (
    <Modal
      open
      onClose={onClose}
      title="Ordner anlegen"
      className="max-w-xl border-white/[0.08] bg-[radial-gradient(ellipse_at_top_left,rgba(139,92,246,0.08),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] text-white"
    >
      <div className="space-y-4">
        <div>
          <label className="mb-1 block text-xs text-white/40">Name</label>
          <input
            className={INPUT_CLS}
            value={form.name}
            onChange={(event) =>
              setForm((current) => ({
                ...current,
                name: event.target.value,
                slug: current.slug || slugifyFolderName(event.target.value),
              }))
            }
          />
        </div>
        <div>
          <label className="mb-1 block text-xs text-white/40">Slug</label>
          <input
            className={INPUT_CLS}
            value={form.slug}
            onChange={(event) =>
              setForm((current) => ({ ...current, slug: slugifyFolderName(event.target.value) }))
            }
          />
        </div>
        <div>
          <label className="mb-1 block text-xs text-white/40">Farbe</label>
          <input
            type="color"
            className="h-11 w-full rounded-xl border border-white/[0.08] bg-white/[0.03] px-2 py-2"
            value={form.color}
            onChange={(event) => setForm((current) => ({ ...current, color: event.target.value }))}
          />
        </div>
        {error ? <p className="text-sm text-rose-300">{error}</p> : null}
        <div className="flex items-center justify-end gap-2">
          <button
            onClick={onClose}
            className="rounded-xl border border-white/[0.08] bg-white/[0.03] px-4 py-2 text-sm text-white/55 transition-colors hover:text-white"
          >
            Abbrechen
          </button>
          <button
            onClick={async () => {
              setSaving(true);
              setError("");
              try {
                await onSave(form);
              } catch (saveError) {
                setError(saveError instanceof Error ? saveError.message : "Ordner konnte nicht gespeichert werden.");
              } finally {
                setSaving(false);
              }
            }}
            className="rounded-xl border border-violet-500/[0.20] bg-violet-500/10 px-4 py-2 text-sm font-semibold text-violet-300 transition-colors hover:bg-violet-500/20"
          >
            {saving ? "Speichert..." : "Ordner anlegen"}
          </button>
        </div>
      </div>
    </Modal>
  );
}

export default function InvoicingPage() {
  const router = useRouter();
  const searchParams = useSearchParams();
  const {
    createCustomer,
    createFolder,
    customers,
    deleteCustomer,
    deleteInvoice,
    error,
    folders,
    invoices,
    loading,
    logInvoiceEvent,
    moveInvoiceToInbox,
    refetch,
    saveInvoice,
    updateCustomer,
    updateInvoiceStatus,
  } = useInvoices();

  const [section, setSection] = useState<Section>("outgoing");
  const [view, setView] = useState<View>("list");
  const [selectedInvoiceId, setSelectedInvoiceId] = useState<string | null>(null);
  const [editingInvoiceId, setEditingInvoiceId] = useState<string | null>(null);
  const [editingCustomerId, setEditingCustomerId] = useState<string | null>(null);
  const [newInvoiceDirection, setNewInvoiceDirection] = useState<InvoiceDirection>("outgoing");
  const [newDocumentType, setNewDocumentType] = useState<InvoiceDocumentType>("invoice");
  const [filter, setFilter] = useState<InvoiceFilter>("all");
  const [activeFolderId, setActiveFolderId] = useState<string>("all");
  const [folderModalOpen, setFolderModalOpen] = useState(false);
  const [importing, setImporting] = useState(false);
  const [sendInvoiceId, setSendInvoiceId] = useState<string | null>(null);
  const importInputRef = useRef<HTMLInputElement>(null);

  const selectedInvoice = invoices.find((invoice) => invoice.id === selectedInvoiceId) || null;
  const editingInvoice = invoices.find((invoice) => invoice.id === editingInvoiceId) || null;
  const editingCustomer = customers.find((customer) => customer.id === editingCustomerId) || null;
  const sendInvoice = invoices.find((invoice) => invoice.id === sendInvoiceId) || null;
  const visibleFolders = folders.filter((folder) => {
    if (section === "customers") return false;
    if (section === "quotes") return folder.slug !== "incoming" && folder.slug !== "shopify";
    if (section === "incoming") return folder.slug !== "outgoing";
    return folder.slug !== "incoming" && folder.slug !== "shopify";
  });

  const deepLinkedInvoiceId = searchParams.get("invoice");
  const effectiveSelectedInvoiceId =
    selectedInvoiceId ||
    (deepLinkedInvoiceId && invoices.some((invoice) => invoice.id === deepLinkedInvoiceId)
      ? deepLinkedInvoiceId
      : null);

  const sectionInvoices = useMemo(() => {
    if (section === "customers") return [];

    const sectionDocumentType: InvoiceDocumentType = section === "quotes" ? "quote" : "invoice";
    const sectionDirection: InvoiceDirection = section === "incoming" ? "incoming" : "outgoing";

    return invoices
      .filter((invoice) => (invoice.document_type || "invoice") === sectionDocumentType)
      .filter((invoice) => invoice.direction === sectionDirection)
      .filter((invoice) => {
        if (activeFolderId === "all") return true;
        if (activeFolderId === "unfiled") return !invoice.folder_id;
        return invoice.folder_id === activeFolderId;
      })
      .filter((invoice) => {
        const status = resolveInvoiceStatus(invoice);
        if (filter === "all") return true;
        if (filter === "active") return status !== "paid" && status !== "cancelled";
        return status === filter;
      })
      .sort((left, right) => {
        const leftStatus = resolveInvoiceStatus(left);
        const rightStatus = resolveInvoiceStatus(right);
        const leftWeight = leftStatus === "overdue" ? 0 : leftStatus === "paid" ? 3 : 1;
        const rightWeight = rightStatus === "overdue" ? 0 : rightStatus === "paid" ? 3 : 1;
        if (leftWeight !== rightWeight) return leftWeight - rightWeight;
        return new Date(right.created_at).getTime() - new Date(left.created_at).getTime();
      });
  }, [activeFolderId, filter, invoices, section]);

  const sectionStats = useMemo(() => {
    const sectionDocumentType: InvoiceDocumentType = section === "quotes" ? "quote" : "invoice";
    const sectionDirection: InvoiceDirection = section === "incoming" ? "incoming" : "outgoing";
    const scoped = invoices.filter(
      (invoice) => (invoice.document_type || "invoice") === sectionDocumentType && invoice.direction === sectionDirection,
    );
    const paid = scoped.filter((invoice) => resolveInvoiceStatus(invoice) === "paid");
    const overdue = scoped.filter((invoice) => resolveInvoiceStatus(invoice) === "overdue");
    const active = scoped.filter((invoice) => {
      const status = resolveInvoiceStatus(invoice);
      return status !== "paid" && status !== "cancelled";
    });

    return {
      activeVolume: active.reduce((sum, invoice) => sum + invoice.total_cents, 0),
      count: scoped.length,
      overdueCount: overdue.length,
      overdueVolume: overdue.reduce((sum, invoice) => sum + invoice.total_cents, 0),
      paidVolume: paid.reduce((sum, invoice) => sum + invoice.total_cents, 0),
      totalVolume: scoped.reduce((sum, invoice) => sum + invoice.total_cents, 0),
    };
  }, [invoices, section]);

  const filters: Array<{ label: string; value: InvoiceFilter }> = [
    { label: "Alle", value: "all" },
    { label: "Aktiv", value: "active" },
    { label: "Bezahlt", value: "paid" },
    { label: "Überfällig", value: "overdue" },
    { label: "Storniert", value: "cancelled" },
  ];

  const handleOpenInvoice = useCallback(
    (invoiceId: string) => {
      setSelectedInvoiceId(invoiceId);
      setView("detail");
      router.replace(`/invoicing?invoice=${invoiceId}`);
    },
    [router],
  );

  const handleCloseInvoice = useCallback(() => {
    setSelectedInvoiceId(null);
    setView("list");
    router.replace("/invoicing");
  }, [router]);

  const handleInvoiceExport = useCallback(
    async (invoice: InvoiceRecord) => {
      const blob = await buildInvoicePdfBlob(invoice);
      const documentLabel = getInvoiceDocumentLabel(invoice);
      const fileName = [
        sanitizeInvoiceFileSegment(invoice.invoice_number || documentLabel),
        sanitizeInvoiceFileSegment(invoice.counterparty_name || ""),
      ]
        .filter(Boolean)
        .join("-");
      downloadBlob(blob, `${fileName || sanitizeInvoiceFileSegment(documentLabel)}.pdf`);
      await logInvoiceEvent(invoice.id, "exported", `${documentLabel} exportiert`, {
        file_name: `${fileName || sanitizeInvoiceFileSegment(documentLabel)}.pdf`,
      });
      await refetch();
    },
    [logInvoiceEvent, refetch],
  );

  const handleBulkExport = useCallback(async () => {
    if (section === "customers" || sectionInvoices.length === 0) return;
    const blob = await buildInvoicePackPdfBlob(sectionInvoices);
    downloadBlob(blob, `mindavio-${section === "quotes" ? "angebote" : section}-dokumente.pdf`);
    await Promise.all(
      sectionInvoices.map((invoice) =>
        logInvoiceEvent(invoice.id, "exported", "Im Sammel-Export enthalten", { batch: section }),
      ),
    );
    await refetch();
  }, [logInvoiceEvent, refetch, section, sectionInvoices]);

  const handleImportFiles = useCallback(
    async (files: FileList | File[]) => {
      const list = Array.from(files);
      if (list.length === 0) return;
      setImporting(true);
      try {
        const selectedFolder =
          activeFolderId !== "all" && activeFolderId !== "unfiled"
            ? visibleFolders.find((folder) => folder.id === activeFolderId) || null
            : visibleFolders.find((folder) => folder.slug === "shopify") || null;

        for (const file of list) {
          const invoiceId = await saveInvoice({
            counterparty_address: "",
            counterparty_email: "",
            counterparty_name: file.name.replace(/\.[^.]+$/, ""),
            document_type: "invoice",
            direction: "incoming",
            due_date: todayStr(),
            folder_id: selectedFolder?.id || null,
            invoice_number: nextInvoiceNumber(invoices, "incoming", "invoice"),
            issue_date: todayStr(),
            items: [
              {
                description: file.name,
                quantity: 1,
                unit_price_cents: 0,
              },
            ],
            notes: "Importierte PDF / Datei",
            source: selectedFolder?.slug === "shopify" ? "shopify_pdf" : "upload",
            status: "received",
            tax_rate: 19,
            title: file.name.replace(/\.[^.]+$/, ""),
          });

          const formData = new FormData();
          formData.append("file", file, file.name);
          formData.append("entityType", "invoice");
          formData.append("entityId", invoiceId);

          const response = await fetch("/api/attachments", {
            method: "POST",
            body: formData,
          });
          const payload = await response.json();
          if (!response.ok) {
            throw new Error(typeof payload?.error === "string" ? payload.error : "Datei-Upload fehlgeschlagen.");
          }

          await logInvoiceEvent(invoiceId, "attachment_added", "Importierte Datei angehängt", {
            file_name: file.name,
            folder: selectedFolder?.name || null,
          });
        }

        await refetch();
      } finally {
        setImporting(false);
      }
    },
    [activeFolderId, invoices, logInvoiceEvent, refetch, saveInvoice, visibleFolders],
  );

  if (view === "customer-editor") {
    return (
      <CustomerEditor
        initial={
          editingCustomer
            ? {
                address: editingCustomer.address,
                contact_person: editingCustomer.contact_person,
                email: editingCustomer.email,
                name: editingCustomer.name,
                notes: editingCustomer.notes,
                payment_terms_days: editingCustomer.payment_terms_days,
                vat_id: editingCustomer.vat_id,
              }
            : {
                address: "",
                contact_person: "",
                email: "",
                name: "",
                notes: "",
                payment_terms_days: 30,
                vat_id: "",
              }
        }
        onCancel={() => {
          setEditingCustomerId(null);
          setView("list");
        }}
        onSave={async (input) => {
          if (editingCustomer) {
            await updateCustomer(editingCustomer.id, input);
          } else {
            await createCustomer(input);
          }
          setEditingCustomerId(null);
          setView("list");
        }}
      />
    );
  }

  if (view === "invoice-editor") {
    return (
      <InvoiceEditor
        customers={customers}
        folders={folders}
        initial={
          editingInvoice
            ? toInvoiceDraft(editingInvoice)
            : buildEmptyDraft(newInvoiceDirection, invoices, newDocumentType)
        }
        invoices={invoices}
        isNew={!editingInvoice}
        onCancel={() => {
          setEditingInvoiceId(null);
          setView(selectedInvoiceId ? "detail" : "list");
        }}
        onSave={async (input) => {
          const invoiceId = await saveInvoice(input, editingInvoice?.id);
          setEditingInvoiceId(null);
          setSelectedInvoiceId(invoiceId);
          setView("detail");
          router.replace(`/invoicing?invoice=${invoiceId}`);
        }}
      />
    );
  }

  const resolvedSelectedInvoice =
    invoices.find((invoice) => invoice.id === effectiveSelectedInvoiceId) || selectedInvoice;

  if ((view === "detail" || (view === "list" && resolvedSelectedInvoice)) && resolvedSelectedInvoice) {
    return (
      <>
        <InvoiceDetail
          invoice={resolvedSelectedInvoice}
          logInvoiceEvent={logInvoiceEvent}
          onBack={handleCloseInvoice}
          onDelete={async () => {
            if (!confirm(`${getInvoiceDocumentLabel(resolvedSelectedInvoice)} ${resolvedSelectedInvoice.invoice_number} wirklich löschen?`)) return;
            await deleteInvoice(resolvedSelectedInvoice.id);
            handleCloseInvoice();
          }}
          onEdit={() => {
            setEditingInvoiceId(resolvedSelectedInvoice.id);
            setView("invoice-editor");
          }}
          onExport={() => handleInvoiceExport(resolvedSelectedInvoice)}
          onMoveToInbox={() => moveInvoiceToInbox(resolvedSelectedInvoice.id)}
          onOpenSend={() => setSendInvoiceId(resolvedSelectedInvoice.id)}
          onStatusChange={async (status) => {
            await updateInvoiceStatus(resolvedSelectedInvoice.id, status);
          }}
        />
        {sendInvoice ? (
          <SendInvoiceModal
            invoice={sendInvoice}
            onClose={() => setSendInvoiceId(null)}
            onSend={async ({ body, subject, to }) => {
              const response = await fetch(`/api/invoices/${sendInvoice.id}/gmail-draft`, {
                method: "POST",
                headers: { "Content-Type": "application/json" },
                body: JSON.stringify({ body, subject, to }),
              });
              const payload = await response.json().catch(() => ({}));
              if (!response.ok) {
                throw new Error(typeof payload?.error === "string" ? payload.error : "Gmail-Entwurf konnte nicht erstellt werden.");
              }
              if (resolveInvoiceStatus(sendInvoice) !== "sent" && resolveInvoiceStatus(sendInvoice) !== "paid") {
                await updateInvoiceStatus(sendInvoice.id, "sent");
              }
              if (typeof payload?.webUrl === "string") {
                window.open(payload.webUrl, "_blank", "noopener,noreferrer");
              }
              setSendInvoiceId(null);
            }}
          />
        ) : null}
      </>
    );
  }

  return (
    <>
      <div className={PAGE_BG}>
        <div className="mx-auto max-w-6xl space-y-6">
          <div className="rounded-[30px] border border-sky-500/[0.14] bg-[radial-gradient(ellipse_at_top_left,rgba(14,165,233,0.09),rgba(10,8,18,0.98)_55%,rgba(9,8,15,1)_100%)] p-8">
            <div className="flex flex-wrap items-start justify-between gap-5">
              <div>
                <p className="text-xs font-semibold uppercase tracking-widest text-white/30">Invoicing OS</p>
                <h1 className="mt-1 text-[36px] font-black leading-none text-white">Rechnungen & Angebote</h1>
                <p className="mt-2 max-w-2xl text-sm text-white/42">
                  Ausgehend, eingehend, Angebote, Kundenstamm, Versandvorbereitung, Sammel-PDF und Timeline an einem Ort.
                </p>
                <div className="mt-4 flex flex-wrap gap-2">
                  <button
                    onClick={() => router.push("/integrations")}
                    className="inline-flex items-center gap-2 rounded-xl border border-sky-500/[0.18] bg-sky-500/10 px-3 py-2 text-xs font-semibold text-sky-300 transition-colors hover:bg-sky-500/18"
                  >
                    <CalendarDays size={14} />
                    Kalender & Gmail verbinden
                  </button>
                  <button
                    onClick={() => router.push("/developers")}
                    className="inline-flex items-center gap-2 rounded-xl border border-violet-500/[0.18] bg-violet-500/10 px-3 py-2 text-xs font-semibold text-violet-300 transition-colors hover:bg-violet-500/18"
                  >
                    <Code2 size={14} />
                    Website/API anbinden
                  </button>
                </div>
              </div>

              <div className="flex flex-wrap items-center gap-2">
                <SectionChip
                  active={section === "outgoing"}
                  icon={<Receipt size={14} />}
                  label="Ausgehend"
                  onClick={() => {
                    setSection("outgoing");
                    setActiveFolderId("all");
                    setFilter("all");
                  }}
                />
                <SectionChip
                  active={section === "incoming"}
                  icon={<Inbox size={14} />}
                  label="Eingehend"
                  onClick={() => {
                    setSection("incoming");
                    setActiveFolderId("all");
                    setFilter("all");
                  }}
                />
                <SectionChip
                  active={section === "quotes"}
                  icon={<FileText size={14} />}
                  label="Angebote"
                  onClick={() => {
                    setSection("quotes");
                    setActiveFolderId("all");
                    setFilter("all");
                  }}
                />
                <SectionChip
                  active={section === "customers"}
                  icon={<Users size={14} />}
                  label="Kunden"
                  onClick={() => setSection("customers")}
                />
              </div>
            </div>

            <div className="mt-8 grid gap-4 sm:grid-cols-2 xl:grid-cols-4">
              <div className="rounded-2xl border border-violet-500/[0.14] bg-violet-500/[0.06] p-4">
                <div className="mb-3 flex h-8 w-8 items-center justify-center rounded-xl border border-violet-500/[0.18] bg-violet-500/15">
                  <Receipt size={14} className="text-violet-400" />
                </div>
                <p className="text-lg font-black text-violet-300 tabular-nums">{formatInvoiceMoney(sectionStats.totalVolume)}</p>
                <p className="text-xs text-white/40">
                  {section === "quotes"
                    ? "Gesamt angeboten"
                    : section === "incoming"
                      ? "Gesamt erfasst"
                      : section === "customers"
                        ? "Volumen ausgehend"
                        : "Gesamt ausgestellt"}
                </p>
              </div>
              <div className="rounded-2xl border border-emerald-500/[0.14] bg-emerald-500/[0.06] p-4">
                <div className="mb-3 flex h-8 w-8 items-center justify-center rounded-xl border border-emerald-500/[0.18] bg-emerald-500/15">
                  <CheckCircle2 size={14} className="text-emerald-400" />
                </div>
                <p className="text-lg font-black text-emerald-300 tabular-nums">{formatInvoiceMoney(sectionStats.paidVolume)}</p>
                <p className="text-xs text-white/40">Bezahlt</p>
              </div>
              <div className="rounded-2xl border border-amber-500/[0.14] bg-amber-500/[0.06] p-4">
                <div className="mb-3 flex h-8 w-8 items-center justify-center rounded-xl border border-amber-500/[0.18] bg-amber-500/15">
                  <Clock size={14} className="text-amber-400" />
                </div>
                <p className="text-lg font-black text-amber-300 tabular-nums">{formatInvoiceMoney(sectionStats.activeVolume)}</p>
                <p className="text-xs text-white/40">Noch offen</p>
              </div>
              <div className="rounded-2xl border border-rose-500/[0.14] bg-rose-500/[0.06] p-4">
                <div className="mb-3 flex h-8 w-8 items-center justify-center rounded-xl border border-rose-500/[0.18] bg-rose-500/15">
                  <AlertCircle size={14} className="text-rose-400" />
                </div>
                <div className="flex items-baseline gap-2">
                  <p className="text-lg font-black text-rose-300 tabular-nums">{formatInvoiceMoney(sectionStats.overdueVolume)}</p>
                  {sectionStats.overdueCount > 0 ? (
                    <span className="text-xs text-rose-400/75">({sectionStats.overdueCount})</span>
                  ) : null}
                </div>
                <p className="text-xs text-white/40">Überfällig</p>
              </div>
            </div>

            <div className="mt-6 flex flex-wrap items-center justify-between gap-3">
              <p className="text-sm text-white/38">
                {section === "customers"
                  ? `${customers.length} Kontakte im Kundenstamm`
                  : `${sectionInvoices.length} ${section === "quotes" ? "Angebote" : "Rechnungen"} im aktuellen Blick`}
              </p>
              <div className="flex flex-wrap items-center gap-2">
                {section !== "customers" ? (
                  <button
                    onClick={() => void handleBulkExport()}
                    disabled={sectionInvoices.length === 0}
                    className="inline-flex items-center gap-2 rounded-2xl border border-violet-500/[0.18] bg-violet-500/10 px-4 py-2 text-sm font-semibold text-violet-300 transition-colors hover:bg-violet-500/18 disabled:cursor-not-allowed disabled:opacity-50"
                  >
                    <Download size={14} />
                    Alle als PDF
                  </button>
                ) : null}
                {section !== "customers" ? (
                  <>
                    <input
                      ref={importInputRef}
                      type="file"
                      multiple
                      accept=".pdf,image/*"
                      className="hidden"
                      onChange={async (event) => {
                        const files = event.target.files;
                        if (!files || files.length === 0) return;
                        await handleImportFiles(files);
                        event.target.value = "";
                      }}
                    />
                    <button
                      onClick={() => importInputRef.current?.click()}
                      className="inline-flex items-center gap-2 rounded-2xl border border-violet-500/[0.18] bg-violet-500/10 px-4 py-2 text-sm font-semibold text-violet-300 transition-colors hover:bg-violet-500/18"
                    >
                      <Upload size={14} />
                      {importing ? "Importiert..." : "PDF hochladen"}
                    </button>
                    <button
                      onClick={() => setFolderModalOpen(true)}
                      className="inline-flex items-center gap-2 rounded-2xl border border-white/[0.10] bg-white/[0.03] px-4 py-2 text-sm font-semibold text-white/65 transition-colors hover:text-white"
                    >
                      <FolderPlus size={14} />
                      Ordner
                    </button>
                  </>
                ) : null}
                <button
                  onClick={() => {
                    if (section === "customers") {
                      setEditingCustomerId(null);
                      setView("customer-editor");
                      return;
                    }
                    setEditingInvoiceId(null);
                    setNewDocumentType(section === "quotes" ? "quote" : "invoice");
                    setNewInvoiceDirection(section === "incoming" ? "incoming" : "outgoing");
                    setView("invoice-editor");
                  }}
                  className="inline-flex items-center gap-2 rounded-2xl border border-sky-500/[0.20] bg-sky-500/10 px-5 py-3 text-sm font-semibold text-sky-300 transition-colors hover:bg-sky-500/20"
                >
                  <Plus size={15} />
                  {section === "incoming"
                    ? "Neue Eingangsrechnung"
                    : section === "quotes"
                    ? "Neues Angebot"
                    : section === "customers"
                    ? "Neuer Kunde"
                    : "Neue Rechnung"}
                </button>
              </div>
            </div>
          </div>

          {error ? <p className="text-sm text-rose-300">{error}</p> : null}

          {section !== "customers" ? (
            <div className={`${CARD_SHELL} p-6`}>
              <div className="mb-5 flex items-center gap-2 overflow-x-auto">
                <button
                  onClick={() => setActiveFolderId("all")}
                  className={`shrink-0 rounded-xl px-3 py-1.5 text-sm font-medium transition-all ${
                    activeFolderId === "all" ? "bg-white/[0.08] text-white" : "text-white/40 hover:text-white/70"
                  }`}
                >
                  Alle Ordner
                </button>
                <button
                  onClick={() => setActiveFolderId("unfiled")}
                  className={`shrink-0 rounded-xl px-3 py-1.5 text-sm font-medium transition-all ${
                    activeFolderId === "unfiled" ? "bg-white/[0.08] text-white" : "text-white/40 hover:text-white/70"
                  }`}
                >
                  Ohne Ordner
                </button>
                {visibleFolders.map((folder) => {
                  const count = invoices.filter(
                    (invoice) =>
                      (invoice.document_type || "invoice") === (section === "quotes" ? "quote" : "invoice") &&
                      invoice.direction === (section === "incoming" ? "incoming" : "outgoing") &&
                      invoice.folder_id === folder.id,
                  ).length;
                  const active = activeFolderId === folder.id;
                  return (
                    <button
                      key={folder.id}
                      onClick={() => setActiveFolderId(folder.id)}
                      className={`shrink-0 rounded-xl border px-3 py-1.5 text-sm font-medium transition-all ${
                        active ? "text-white" : "text-white/40 hover:text-white/70"
                      }`}
                      style={{
                        backgroundColor: active ? `${folder.color}22` : "rgba(255,255,255,0.03)",
                        borderColor: active ? `${folder.color}55` : "rgba(255,255,255,0.08)",
                      }}
                    >
                      {folder.name}
                      <span className="ml-2 text-[10px] opacity-70">{count}</span>
                    </button>
                  );
                })}
              </div>
              <div className="mb-5 flex items-center gap-1 overflow-x-auto">
                {filters.map((tab) => {
                  const sectionDocumentType = section === "quotes" ? "quote" : "invoice";
                  const sectionDirection = section === "incoming" ? "incoming" : "outgoing";
                  const count =
                    tab.value === "all"
                      ? invoices.filter(
                          (invoice) =>
                            (invoice.document_type || "invoice") === sectionDocumentType &&
                            invoice.direction === sectionDirection,
                        ).length
                      : tab.value === "active"
                      ? invoices.filter((invoice) => {
                          const status = resolveInvoiceStatus(invoice);
                          return (
                            (invoice.document_type || "invoice") === sectionDocumentType &&
                            invoice.direction === sectionDirection &&
                            status !== "paid" &&
                            status !== "cancelled"
                          );
                        }).length
                      : invoices.filter(
                          (invoice) =>
                            (invoice.document_type || "invoice") === sectionDocumentType &&
                            invoice.direction === sectionDirection &&
                            resolveInvoiceStatus(invoice) === tab.value,
                        ).length;
                  const active = filter === tab.value;
                  return (
                    <button
                      key={tab.value}
                      onClick={() => setFilter(tab.value)}
                      className={`flex shrink-0 items-center gap-1.5 rounded-xl px-3 py-1.5 text-sm font-medium transition-all ${
                        active ? "bg-white/[0.08] text-white" : "text-white/40 hover:text-white/70"
                      }`}
                    >
                      {tab.label}
                      <span
                        className={`rounded-full px-1.5 py-0.5 text-[10px] font-bold ${
                          active ? "bg-white/[0.12] text-white/70" : "bg-white/[0.05] text-white/30"
                        }`}
                      >
                        {count}
                      </span>
                    </button>
                  );
                })}
              </div>

              {loading ? (
                <div className="rounded-2xl border border-white/[0.06] bg-white/[0.02] p-6 text-sm text-white/32">
                  Dokumente werden geladen...
                </div>
              ) : sectionInvoices.length === 0 ? (
                <div className="flex flex-col items-center justify-center gap-3 py-16 text-center">
                  <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-white/[0.08] bg-white/[0.03]">
                    {section === "incoming" ? <Inbox size={20} className="text-white/30" /> : <FileText size={20} className="text-white/30" />}
                  </div>
                  <p className="text-sm text-white/40">
                    {section === "quotes"
                      ? "Noch keine Angebote in diesem Blick."
                      : section === "incoming"
                        ? "Noch keine Eingangsrechnungen in diesem Blick."
                        : "Noch keine Ausgangsrechnungen in diesem Blick."}
                  </p>
                </div>
              ) : (
                <div className="space-y-2">
                  {sectionInvoices.map((invoice) => (
                    <div key={invoice.id} className="group relative">
                      <InvoiceCard invoice={invoice} onClick={() => handleOpenInvoice(invoice.id)} />
                      <button
                        onClick={(event) => {
                          event.stopPropagation();
                          if (!confirm(`${getInvoiceDocumentLabel(invoice)} ${invoice.invoice_number} wirklich löschen?`)) return;
                          void deleteInvoice(invoice.id);
                        }}
                        className="absolute right-14 top-1/2 -translate-y-1/2 rounded-xl p-2 text-white/20 opacity-0 transition-all hover:bg-rose-500/10 hover:text-rose-400 group-hover:opacity-100"
                      >
                        <Trash2 size={14} />
                      </button>
                    </div>
                  ))}
                </div>
              )}
            </div>
          ) : (
            <div className={`${CARD_SHELL} p-6`}>
              {customers.length === 0 ? (
                <div className="flex flex-col items-center justify-center gap-3 py-16 text-center">
                  <div className="flex h-12 w-12 items-center justify-center rounded-2xl border border-white/[0.08] bg-white/[0.03]">
                    <Users size={20} className="text-white/30" />
                  </div>
                  <p className="text-sm text-white/40">Noch keine Kunden angelegt.</p>
                </div>
              ) : (
                <div className="grid gap-4 xl:grid-cols-2">
                  {customers.map((customer) => (
                    <CustomerCard
                      key={customer.id}
                      customer={customer}
                      invoices={invoices}
                      onDelete={async () => {
                        if (!confirm(`Kunde ${customer.name} wirklich löschen?`)) return;
                        await deleteCustomer(customer.id);
                      }}
                      onEdit={() => {
                        setEditingCustomerId(customer.id);
                        setView("customer-editor");
                      }}
                    />
                  ))}
                </div>
              )}
            </div>
          )}
        </div>
      </div>

      {sendInvoice ? (
        <SendInvoiceModal
          invoice={sendInvoice}
          onClose={() => setSendInvoiceId(null)}
          onSend={async ({ body, subject, to }) => {
            const response = await fetch(`/api/invoices/${sendInvoice.id}/gmail-draft`, {
              method: "POST",
              headers: { "Content-Type": "application/json" },
              body: JSON.stringify({ body, subject, to }),
            });
            const payload = await response.json().catch(() => ({}));
            if (!response.ok) {
              throw new Error(typeof payload?.error === "string" ? payload.error : "Gmail-Entwurf konnte nicht erstellt werden.");
            }
            if (resolveInvoiceStatus(sendInvoice) !== "sent" && resolveInvoiceStatus(sendInvoice) !== "paid") {
              await updateInvoiceStatus(sendInvoice.id, "sent");
            }
            if (typeof payload?.webUrl === "string") {
              window.open(payload.webUrl, "_blank", "noopener,noreferrer");
            }
            setSendInvoiceId(null);
          }}
        />
      ) : null}
      {folderModalOpen ? (
        <FolderModal
          onClose={() => setFolderModalOpen(false)}
          onSave={async (input) => {
            await createFolder(input);
            setFolderModalOpen(false);
          }}
        />
      ) : null}
    </>
  );
}
