import { Fragment, useEffect, useState, type FormEvent } from "react";
import { EKDOS_VERSION } from "@/lib/version";
import { useAuth } from "@/auth/AuthProvider";
import { Permission } from "@/auth/types";
import { UsersView } from "@/views/UsersView";

type Stage = {
  title: string;
  question: string;
  task: string;
  helga: string;
  active: string[];
};

type OpenTicket = {
  id: string;
  status: string;
  reportStatus?: string;
  customer: string;
  property: string;
  title: string;
  updatedAt: string;
  continuation?: string;
  decisionCode?: string;
  consultationResult?: string;
  consultationUpdatedAt?: string;
  consultationBy?: string;
  requiresCustomerConsultation?: boolean;
  createdAt?: string;
  technician?: string;
  reportCount?: number;
};

type HourEntry = {
  date: string;
  label: string;
  status: string;
  customer?: string;
  property?: string;
  report?: string;
  hours: number;
};
type HourEmployee = {
  name: string;
  totalHours: number;
  entries: HourEntry[];
  statusDays?: { school: number; sick: number; vacation: number };
  workDaysYear?: number;
};
type HoursOverview = {
  month: string;
  year: number;
  generatedAt: string;
  employees: HourEmployee[];
  statusPriority?: string;
};
type InvoiceReview = {
  id: string;
  title: string;
  createdAt: string;
  body: string;
  status?: string;
  completedAt?: string;
};
type InvoiceSendTask = {
  id: string | number;
  versand_id?: string;
  ticketnummer?: string;
  kunde?: string;
  liegenschaft?: string;
  rechnungsnummer?: string;
  created_at?: string;
  versendet_am?: string;
};
type Customer = {
  id: string;
  kundennummer_bestand?: string;
  firma?: string;
  anrede?: string;
  name?: string;
  strasse?: string;
  plz?: string;
  ort?: string;
  telefon?: string;
  mobil?: string;
  email?: string;
  notiz?: string;
  aktualisiert_am?: string;
};
type OnlinePurchase = {
  id: string;
  artikel: string;
  kaufort: string;
  kaufdatum: string;
  status?: string;
  angelegt_von?: string;
  angelegt_am?: string;
  erledigt_von?: string;
  erledigt_am?: string;
};
type InternalTask = {
  id: string;
  aufgabe: string;
  empfaenger?: string;
  kategorie?: string;
  kunden_id?: string;
  status?: string;
  erstellt_von?: string;
  erstellt_am?: string;
  erledigt_von?: string;
  erledigt_am?: string;
};
type Offer = {
  id: string;
  dateiname: string;
  dateipfad?: string;
  angebot_nummer?: string;
  erstellt_am?: string;
  versendet?: boolean;
  versandart?: string;
  versendet_am?: string;
  status?: string;
  beauftragt_am?: string;
  gueltig_bis?: string;
  kunde?: string;
  objekt_zusatz?: string;
};
type CustomerInvoice = {
  id?: string;
  rechnungsnummer?: string;
  dateiname?: string;
  dateipfad?: string;
  kunde?: string;
  liegenschaft?: string;
  rechnungsdatum?: string;
};
type InvoiceProperty = { liegenschaft: string; count: number };

type WorkspaceArea = { title: string; kicker: string; description: string };

const workspaceAreas: Record<string, WorkspaceArea> = {
  "offers-all": {
    title: "Erstellte Angebote",
    kicker: "ANGEBOTE",
    description: "Hier erscheinen neu erstellte Angebote aus EK-DOS.",
  },
  "offers-commissioned": {
    title: "Beauftragte Angebote",
    kicker: "ANGEBOTE",
    description: "Hier werden beauftragte Angebote dargestellt.",
  },
  "offers-open": {
    title: "Offene Angebote",
    kicker: "ANGEBOTE",
    description: "Hier werden noch offene Angebote dargestellt.",
  },
  "offers-expired": {
    title: "Abgelaufene Angebote",
    kicker: "ANGEBOTE",
    description:
      "Hier werden nicht beauftragte Angebote nach Ablauf ihrer Gültigkeit dargestellt.",
  },
  "unit-prices": {
    title: "Einheitspreise",
    kicker: "KALKULATION",
    description:
      "Hier werden die Einheitspreise für EK-DOS bereitgestellt und gepflegt.",
  },
  "time-records": {
    title: "Stundennachweise",
    kicker: "MITARBEITER",
    description:
      "Hier werden die Stundennachweise der Mitarbeiter bereitgestellt.",
  },
  "internal-tasks": {
    title: "Interne Aufgaben",
    kicker: "ELEKTRO KRÜGER",
    description:
      "Hier werden gemeinsame interne Aufgaben für Svenja und Sascha zusammengeführt.",
  },
  "invoice-review-svenja": {
    title: "Rechnungen in Prüfung",
    kicker: "SVENJA · RECHNUNGEN",
    description: "Hier bearbeitet Svenja Rechnungen in der Prüfung.",
  },
  "invoices-send": {
    title: "Rechnungen zum Versenden",
    kicker: "RECHNUNGEN",
    description:
      "Hier stehen freigegebene Rechnungen bereit, die noch versendet werden müssen.",
  },
  "invoices-create": {
    title: "Rechnungen anfertigen",
    kicker: "SVENJA · RECHNUNGEN",
    description: "Hier erstellt Svenja die vorbereiteten Rechnungen.",
  },
  "invoices-created": {
    title: "Erstellte Rechnungen",
    kicker: "SVENJA · RECHNUNGEN",
    description:
      "Hier bleiben die bereits erstellten Rechnungen dauerhaft sichtbar.",
  },
  "online-purchases": {
    title: "Online Käufe",
    kicker: "SVENJA",
    description: "Hier bearbeitet Svenja die zugeordneten Online-Käufe.",
  },
  "online-purchases-new": {
    title: "Neue Online Käufe",
    kicker: "SASCHA",
    description: "Hier prüft Sascha neu eingegangene Online-Käufe.",
  },
  "invoices-review-sascha": {
    title: "Rechnungen prüfen",
    kicker: "SASCHA · RECHNUNGEN",
    description: "Hier prüft und gibt Sascha Rechnungen frei.",
  },
  postcalculation: {
    title: "Nachkalkulation",
    kicker: "SASCHA",
    description: "Hier stehen Aufträge für die Nachkalkulation bereit.",
  },
  analytics: {
    title: "Auswertungen",
    kicker: "SASCHA",
    description: "Hier werden die EK-DOS-Auswertungen bereitgestellt.",
  },
  cashflow: {
    title: "Cashflow",
    kicker: "SASCHA · AUSWERTUNGEN",
    description:
      "Hier wird der aktuelle Cashflow von Elektro Krüger ausgewertet.",
  },
};

function formatDateTime(value?: string) {
  if (!value) return "–";
  const date = new Date(value);
  return Number.isNaN(date.getTime())
    ? value
    : new Intl.DateTimeFormat("de-DE", {
        dateStyle: "medium",
        timeStyle: "short",
      }).format(date);
}

function formatDate(value?: string) {
  if (!value) return "–";
  const date = new Date(`${value.slice(0, 10)}T12:00:00`);
  return Number.isNaN(date.getTime())
    ? value
    : new Intl.DateTimeFormat("de-DE", { dateStyle: "medium" }).format(date);
}

function hoursStatusClass(status: string) {
  const normalized = status.trim().toLocaleLowerCase("de-DE");
  if (normalized === "krank") return "sick";
  if (normalized === "urlaub") return "vacation";
  if (normalized.startsWith("berufsschul")) return "school";
  return "work";
}

function reportStatusClass(status?: string) {
  const normalized = String(status ?? "")
    .trim()
    .toLocaleUpperCase("de-DE");
  if (normalized === "TEILERLEDIGT") return "ticket-report-status-partial";
  if (normalized === "ABGESCHLOSSEN") return "ticket-report-status-completed";
  return "";
}

function invoiceTicketNumber(task: InvoiceReview) {
  const match = `${task.title ?? ""}\n${task.body ?? ""}`.match(
    /(?:EK-DOS-TICKET|Ticket)\s*:\s*(\d{4}-\d+)/i,
  );
  return match?.[1] ?? "–";
}

function invoiceReviewFields(task: InvoiceReview) {
  const text = `${task.title ?? ""}\n${task.body ?? ""}`
    .replace(/\s+/g, " ")
    .trim();
  const field = (label: string, following: string[]) => {
    const boundary = `(?=\\s*(?:${following.join("|")})\\s*:|$)`;
    return (
      text
        .match(new RegExp(`${label}\\s*:\\s*(.*?)${boundary}`, "i"))?.[1]
        ?.trim() || ""
    );
  };
  const kunde =
    field("Kunde", [
      "Liegenschaft",
      "Ticket",
      "EK-DOS-TICKET",
      "Digitale Akte",
    ]) ||
    task.title
      .replace(/^Rechnung\s+prüfen\s*[–-]\s*/i, "")
      .replace(/\s*[–-]\s*Ticket\s*:\s*\d{4}-\d+.*$/i, "")
      .trim();
  const liegenschaft = field("Liegenschaft", [
    "Ticket",
    "EK-DOS-TICKET",
    "Digitale Akte",
  ]);
  const strasseMitHausnummer = liegenschaft
    .match(/^(.+?\s+\d+[a-zA-Z]?)\b/)?.[1]
    ?.trim();
  return {
    kunde: kunde || "–",
    liegenschaft: strasseMitHausnummer || liegenschaft || "–",
    ticket: invoiceTicketNumber(task),
  };
}

const stages: Stage[] = [
  {
    title: "Eingang und Zuordnung",
    question:
      "Workflow 1 bis 4: Der Servicebericht trifft ein, wird ausgelesen und Kunde, Liegenschaft sowie Ticket werden geprüft.",
    task: "Keine Aktion, solange Helga keine Rückfrage stellt. Die Verarbeitung von E-Mail und PDF läuft automatisch.",
    helga:
      "Ich lese den Servicebericht aus, prüfe Kunde und Ticket und lege bei Bedarf den neuen Kunden oder ein neues Ticket an.",
    active: ["mail", "pdf", "kunde", "ticketCheck", "ticketNew"],
  },
  {
    title: "Ticket und Status",
    question:
      "Workflow 4A und 4B: Abhängig davon, ob ein Ticket vorhanden ist, wird der Bericht dem richtigen Vorgang zugeordnet und der Status geprüft.",
    task: "Bei einer Helga-Rückfrage nur die fehlende Zuordnung oder Information beantworten.",
    helga:
      "Ich speichere den Bericht im Ticket, lege den Ticketordner der Digitalen Akte an und prüfe: teilerledigt oder abgeschlossen?",
    active: ["ticketNew", "ticketStore", "folder", "status"],
  },
  {
    title: "Teilerledigung",
    question:
      "Workflow 5A, 7, 9, 11 und 12: Ein teilerledigter Bericht bleibt im bestehenden Ticket offen und wird in Akte, NAS, Tagesübersicht und Stundenliste ergänzt.",
    task: "Die Teams-Rückfrage von Helga beantworten, wenn Material, Termin, Rücksprache mit Kunde oder Sascha betroffen ist.",
    helga:
      "Ich sichere den Bericht, aktualisiere die Digitale Akte und frage dich nur, wenn für die weitere Bearbeitung eine Entscheidung nötig ist.",
    active: ["partial", "nas", "akte", "daily", "hours", "teams"],
  },
  {
    title: "Abschluss, Rechnung und Versand",
    question:
      "Workflow 5B bis 18: Der Abschlussbericht schließt den Auftrag. Danach folgen Rechnungsaufgabe, Prüfung durch Sascha, Versandbestätigung und die abschließende Dokumentation.",
    task: "Rechnung erstellen, nach Saschas Freigabe versenden und den Versand in Teams oder To Do bestätigen.",
    helga:
      "Ich übergebe die Rechnung an Sascha zur Prüfung und dokumentiere nach deiner Versandbestätigung Ticket, Digitale Akte und Jahresübersicht.",
    active: [
      "completed",
      "close",
      "todo",
      "invoice",
      "review",
      "send",
      "archive",
    ],
  },
];

const nodes = [
  ["mail", "Workflow 1\nServicebericht: serviceberichte@…", "green"],
  ["pdf", "Workflow 2\nPDF auslesen und Felder speichern", "green"],
  ["kunde", "Workflow 3\nKunde neu? Kundendaten anlegen", "yellow"],
  ["ticketCheck", "Workflow 4\nTicket schon vorhanden?", "yellow"],
  ["ticketNew", "Workflow 4A\nTicket anlegen / Bericht speichern", "yellow"],
  ["folder", "Workflow 6\nDigitale Akte im Ticketordner erzeugen", "yellow"],
  ["status", "Workflow 4A / 4B\nTeilerledigt oder abgeschlossen?", "yellow"],
  ["partial", "Workflow 5A\nTeilerledigt", "yellow"],
  ["nas", "Workflow 5A / 5B\nServicebericht auf NAS speichern", "yellow"],
  ["akte", "Workflow 7\nDigitale Akte aktualisieren", "yellow"],
  ["daily", "Workflow 9 / 13\nTageszusammenfassung ergänzen", "yellow"],
  ["hours", "Workflow 11\nMitarbeiterstunden eintragen", "yellow"],
  ["teams", "Workflow 12\nHelga fragt Svenja in Teams", "yellow"],
  ["completed", "Workflow 5B / 8\nAbgeschlossen / Bericht beendet", "yellow"],
  ["close", "Workflow 10\nTo Do an Svenja übertragen", "yellow"],
  ["todo", "Workflow 15\nAufgabe „Rechnung erstellen“", "yellow"],
  ["invoice", "Svenja erstellt Rechnung\nund schließt die Aufgabe", "yellow"],
  ["review", "Workflow 15 / 16\nSascha prüft / Helga informiert", "yellow"],
  ["send", "Workflow 17\nVersand in Teams / To Do bestätigen", "yellow"],
  [
    "archive",
    "Workflow 18\nDigitale Akte und Jahresübersicht aktualisieren",
    "yellow",
  ],
];

const exercises = [
  {
    question:
      "Praxisfall: Der von Workflow 2 ausgelesene Kunde ist noch nicht in den Kundendaten vorhanden. Was passiert als Nächstes?",
    answers: [
      "Workflow 3 legt Kunde und Kundendaten neu an; anschließend prüft Workflow 4 das Ticket.",
      "Svenja erstellt sofort eine Rechnung.",
      "Der Servicebericht wird verworfen und muss neu gesendet werden.",
    ],
    correct: 0,
    note: "Richtig. Die Neuanlage des Kunden ist automatisiert; erst danach wird die Ticketlage beurteilt.",
  },
  {
    question:
      "Praxisfall: Zu Kunde und Liegenschaft gibt es bereits ein offenes Ticket. Welche Verzweigung ist richtig?",
    answers: [
      "Workflow 4B: Den Bericht dem bestehenden Ticket zuordnen und danach den Status prüfen.",
      "Workflow 4A: Immer ein zusätzliches Ticket eröffnen.",
      "Die Digitale Akte wird erst nach dem Rechnungsversand angelegt.",
    ],
    correct: 0,
    note: "Richtig. Ein bestehendes offenes Ticket wird ergänzt – doppelte Tickets werden vermieden.",
  },
  {
    question:
      "Praxisfall: Der Bericht ist als „Teilerledigt“ gekennzeichnet. Was ist für Svenja richtig?",
    answers: [
      "Die Helga-Rückfrage in Teams beantworten, falls Termin, Material oder Rücksprache erforderlich ist. Keine Rechnung erstellen.",
      "Die Aufgabe „Rechnung erstellen“ abschließen.",
      "Den Auftrag als abgeschlossen markieren.",
    ],
    correct: 0,
    note: "Richtig. Das Ticket bleibt offen. Workflow 5A sichert und dokumentiert den Bericht, aber löst noch keine Rechnung aus.",
  },
  {
    question:
      "Praxisfall: Der Abschlussbericht ist verarbeitet und Sascha hat die Rechnung freigegeben. Was fehlt noch?",
    answers: [
      "Svenja versendet die Rechnung und bestätigt den Versand in Teams oder To Do.",
      "Ein neues Ticket zum gleichen Auftrag anlegen.",
      "Die Stunden aus der Mitarbeiter-Tabelle löschen.",
    ],
    correct: 0,
    note: "Richtig. Die Versandbestätigung löst Workflow 18 aus: Digitale Akte und Jahresübersicht erhalten das Versanddatum.",
  },
];

function FlowNode({ id, activeIds }: { id: string; activeIds: string[] }) {
  const node = nodes.find(([nodeId]) => nodeId === id);
  if (!node) return null;
  const [, label, tone] = node;
  return (
    <div className={`flow-node ${tone} ${activeIds.includes(id) ? "lit" : ""}`}>
      <span>
        {label.split("\n").map((line, index) => (
          <>
            {index > 0 && <br />}
            {line}
          </>
        ))}
      </span>
    </div>
  );
}

export default function Home() {
  const [view, setView] = useState<string>("home");
  const [offersOpen, setOffersOpen] = useState(false);
  const [invoiceCreateOpen, setInvoiceCreateOpen] = useState(false);
  const [analyticsOpen, setAnalyticsOpen] = useState(false);
  const [stage, setStage] = useState(0);
  const [answers, setAnswers] = useState<Record<number, number>>({});
  // Anmeldung, Sitzungsverlängerung und Leerlaufabmeldung liegen im AuthProvider.
  // Hier steht nur noch, wer angemeldet ist und was diese Person darf.
  const { user: currentUser, signOut, can } = useAuth();
  const user = currentUser?.name ?? null;
  const [tickets, setTickets] = useState<OpenTicket[]>([]);
  const [ticketsLoading, setTicketsLoading] = useState(false);
  const [ticketsError, setTicketsError] = useState("");
  const [ticketsRefreshedAt, setTicketsRefreshedAt] = useState("");
  const [consultationDrafts, setConsultationDrafts] = useState<
    Record<string, string>
  >({});
  const [consultationSaving, setConsultationSaving] = useState<string | null>(
    null,
  );
  const [consultationError, setConsultationError] = useState<
    Record<string, string>
  >({});
  const [hoursOverview, setHoursOverview] = useState<HoursOverview | null>(
    null,
  );
  const [hoursLoading, setHoursLoading] = useState(false);
  const [hoursError, setHoursError] = useState("");
  const [invoiceReviews, setInvoiceReviews] = useState<InvoiceReview[]>([]);
  const [invoiceReviewsLoading, setInvoiceReviewsLoading] = useState(false);
  const [invoiceReviewsError, setInvoiceReviewsError] = useState("");
  const [invoiceReviewsRefreshedAt, setInvoiceReviewsRefreshedAt] =
    useState("");
  const [invoiceReviewCompleting, setInvoiceReviewCompleting] = useState<
    string | null
  >(null);
  const [invoiceCreateTasks, setInvoiceCreateTasks] = useState<InvoiceReview[]>(
    [],
  );
  const [invoiceCreateLoading, setInvoiceCreateLoading] = useState(false);
  const [invoiceCreateError, setInvoiceCreateError] = useState("");
  const [invoiceCreateRefreshedAt, setInvoiceCreateRefreshedAt] = useState("");
  const [invoiceCreateCompleting, setInvoiceCreateCompleting] = useState<
    string | null
  >(null);
  const openInvoiceCreateTasks = invoiceCreateTasks.filter(
    (task) => task.status !== "erledigt",
  );
  const completedInvoiceCreateTasks = invoiceCreateTasks.filter(
    (task) => task.status === "erledigt",
  );
  const [invoiceSendTasks, setInvoiceSendTasks] = useState<InvoiceSendTask[]>(
    [],
  );
  const [invoiceSendLoading, setInvoiceSendLoading] = useState(false);
  const [invoiceSendError, setInvoiceSendError] = useState("");
  const [invoiceSendRefreshedAt, setInvoiceSendRefreshedAt] = useState("");
  const [customers, setCustomers] = useState<Customer[]>([]);
  const [customersLoading, setCustomersLoading] = useState(false);
  const [customersError, setCustomersError] = useState("");
  const [customerSearch, setCustomerSearch] = useState("");
  const [customerSort, setCustomerSort] = useState<
    "name-asc" | "name-desc" | "number-asc" | "number-desc"
  >("name-asc");
  const [editingCustomer, setEditingCustomer] = useState<Customer | null>(null);
  const [creatingCustomer, setCreatingCustomer] = useState(false);
  const [customerTaskFilter, setCustomerTaskFilter] = useState<
    "all" | "open" | "done"
  >("all");
  const [customerSaving, setCustomerSaving] = useState(false);
  const [customerDeleteConfirming, setCustomerDeleteConfirming] =
    useState(false);
  const [invoiceCustomer, setInvoiceCustomer] = useState<Customer | null>(null);
  const [customerInvoicesLoading, setCustomerInvoicesLoading] = useState(false);
  const [invoiceProperties, setInvoiceProperties] = useState<InvoiceProperty[]>(
    [],
  );
  const [propertyInvoices, setPropertyInvoices] = useState<
    Record<string, CustomerInvoice[]>
  >({});
  const [propertyInvoiceLoading, setPropertyInvoiceLoading] = useState<
    string | null
  >(null);
  const [propertyInvoiceError, setPropertyInvoiceError] = useState<
    Record<string, string>
  >({});
  const [invoiceOverview, setInvoiceOverview] = useState<CustomerInvoice[]>([]);
  const [invoiceOverviewLoading, setInvoiceOverviewLoading] = useState(false);
  const [invoiceOverviewError, setInvoiceOverviewError] = useState("");
  const [invoiceOverviewTab, setInvoiceOverviewTab] = useState<
    "all" | "unassigned"
  >("all");
  const [invoiceAssignmentSearch, setInvoiceAssignmentSearch] = useState<
    Record<string, string>
  >({});
  const [invoiceAssignmentBusy, setInvoiceAssignmentBusy] = useState<
    string | null
  >(null);
  const [onlinePurchases, setOnlinePurchases] = useState<OnlinePurchase[]>([]);
  const [onlinePurchasesLoading, setOnlinePurchasesLoading] = useState(false);
  const [onlinePurchasesError, setOnlinePurchasesError] = useState("");
  const [onlinePurchaseSaving, setOnlinePurchaseSaving] = useState(false);
  const [onlinePurchaseCompleting, setOnlinePurchaseCompleting] = useState<
    string | null
  >(null);
  const [onlinePurchaseDeleting, setOnlinePurchaseDeleting] = useState<
    string | null
  >(null);
  const [onlinePurchaseForm, setOnlinePurchaseForm] = useState({
    artikel: "",
    kaufort: "",
    kaufdatum: new Date().toISOString().slice(0, 10),
  });
  const [internalTasks, setInternalTasks] = useState<InternalTask[]>([]);
  const [internalTaskDrafts, setInternalTaskDrafts] = useState<
    Record<string, { aufgabe: string; kategorie: string; kunden_id: string }>
  >({});
  const [internalTaskCustomerSearch, setInternalTaskCustomerSearch] = useState<
    Record<string, string>
  >({});
  const [
    editingInternalTaskCustomerSearch,
    setEditingInternalTaskCustomerSearch,
  ] = useState("");
  const [editingInternalTaskCustomerId, setEditingInternalTaskCustomerId] =
    useState("");
  const [internalTaskError, setInternalTaskError] = useState("");
  const [internalTaskBusy, setInternalTaskBusy] = useState<string | null>(null);
  const [internalTasksOpen, setInternalTasksOpen] = useState(false);
  const [saschaTasksOpen, setSaschaTasksOpen] = useState(false);
  const [internalTaskFilter, setInternalTaskFilter] = useState<string | null>(
    null,
  );
  const [internalTaskRecipientFilter, setInternalTaskRecipientFilter] =
    useState<"sascha" | "svenja">("svenja");
  const [editingInternalTask, setEditingInternalTask] =
    useState<InternalTask | null>(null);
  const [offers, setOffers] = useState<Offer[]>([]);
  const [offersLoading, setOffersLoading] = useState(false);
  const [offersError, setOffersError] = useState("");
  const [offerBusy, setOfferBusy] = useState<string | null>(null);
  const [offerShipping, setOfferShipping] = useState<
    Record<string, "E-Mail" | "Post">
  >({});
  const [offerSearch, setOfferSearch] = useState("");
  const [offerConfirming, setOfferConfirming] = useState<Offer | null>(null);
  const [dashboardNow, setDashboardNow] = useState(() => new Date());
  const current = stages[stage];
  const exercise = exercises[stage];
  const workspace = workspaceAreas[view];
  // Früher wurde hier auf den Namen geprüft. Jetzt entscheidet das Recht, damit
  // ein drittes Konto dieselben Ansichten bekommen kann, ohne dass hier etwas
  // angefasst werden muss. Die Rolle "Büro" trägt Svenjas Rechte, "Inhaber" die
  // von Sascha.
  const isSvenja = can(Permission.InvoicesProcess);
  const isSascha = can(Permission.PurchasesCreate);
  const canManageUsers = currentUser?.canManageUsers ?? false;
  const visibleInvoiceReviews = invoiceReviews.filter(
    (invoice) => invoice.status !== "erledigt",
  );
  const internalTaskRecipient = (task: InternalTask) =>
    task.empfaenger === "sascha" || task.empfaenger === "svenja"
      ? task.empfaenger
      : task.kategorie === "svenja"
        ? "svenja"
        : "sascha";
  const internalTaskCategory = (task: InternalTask) => {
    if (
      [
        "angebote",
        "steuerberater",
        "kundenruecksprache",
        "interne_bueroaufgaben",
        "heute_erledigen",
      ].includes(task.kategorie ?? "")
    )
      return task.kategorie as
        | "angebote"
        | "steuerberater"
        | "kundenruecksprache"
        | "interne_bueroaufgaben"
        | "heute_erledigen";
    return /angebot/i.test(task.aufgabe) ? "angebote" : "interne_bueroaufgaben";
  };
  const openTaskCount = (empfaenger: string) =>
    internalTasks.filter(
      (task) =>
        task.status !== "erledigt" &&
        internalTaskRecipient(task) === empfaenger,
    ).length;
  const internalTaskCategories = [
    ["angebote", "Angebote"],
    ["steuerberater", "Steuerberater"],
    ["kundenruecksprache", "Rücksprache mit Kunde"],
    ["interne_bueroaufgaben", "Interne Büroaufgaben"],
    ["heute_erledigen", "WICHTIG! NOCH HEUTE ERLEDIGEN"],
  ] as const;
  const openTaskCategoryCount = (
    kategorie: string,
    empfaenger = isSascha ? "sascha" : "svenja",
  ) =>
    internalTasks.filter(
      (task) =>
        task.status !== "erledigt" &&
        internalTaskRecipient(task) === empfaenger &&
        (kategorie === "interne_bueroaufgaben"
          ? ["interne_bueroaufgaben", "kundenruecksprache"].includes(
              internalTaskCategory(task),
            )
          : internalTaskCategory(task) === kategorie),
    ).length;
  const activeInternalTaskRecipient = isSvenja
    ? internalTaskRecipientFilter
    : "sascha";
  const activeInternalTaskCategories =
    activeInternalTaskRecipient === "sascha"
      ? ([
          ["angebote", "Saschas Angebote"],
          ["steuerberater", "Saschas Steuerberater"],
          ["interne_bueroaufgaben", "Saschas Büroaufgaben"],
          ["heute_erledigen", "Saschas WICHTIG!"],
        ] as const)
      : internalTaskCategories;
  const customerTaskName = (customer: Customer) => {
    const person = (customer.name ?? "").trim();
    const parts = person.split(/\s+/).filter(Boolean);
    const orderedPerson =
      parts.length > 1
        ? `${parts.at(-1)}, ${parts.slice(0, -1).join(" ")}`
        : person;
    return customer.firma
      ? `${customer.firma}${orderedPerson ? ` · ${orderedPerson}` : ""}`
      : orderedPerson || "Unbenannter Kunde";
  };
  const customerTaskOptions = customers
    .map((customer) => ({
      customer,
      label: customerTaskName(customer),
      search:
        `${customerTaskName(customer)} ${customer.name ?? ""} ${customer.firma ?? ""}`.toLocaleLowerCase(
          "de-DE",
        ),
    }))
    .sort((a, b) => a.label.localeCompare(b.label, "de"));
  const internalTaskCustomerName = (task: InternalTask) =>
    customerTaskOptions.find(
      (option) => String(option.customer.id) === String(task.kunden_id ?? ""),
    )?.label ?? "";
  const openOnlinePurchaseCount = onlinePurchases.filter(
    (purchase) => purchase.status?.toLocaleLowerCase("de-DE") !== "erledigt",
  ).length;
  const offerExpired = (offer: Offer) =>
    offer.status !== "beauftragt" &&
    !!offer.gueltig_bis &&
    Date.parse(offer.gueltig_bis) < Date.now();
  const unsentOfferCount = offers.filter(
    (offer) =>
      !offer.versendet && offer.status !== "beauftragt" && !offerExpired(offer),
  ).length;
  const openOfferCount = offers.filter(
    (offer) =>
      !!offer.versendet &&
      offer.status !== "beauftragt" &&
      !offerExpired(offer),
  ).length;
  const openInvoiceCreateCount = openInvoiceCreateTasks.length;
  const openInvoiceReviewCount = invoiceReviews.filter(
    (invoice) => invoice.status !== "erledigt",
  ).length;
  const openInvoiceSendCount = invoiceSendTasks.filter(
    (task) => !task.versendet_am,
  ).length;
  const dashboardGreeting =
    dashboardNow.getHours() < 12
      ? "Guten Morgen"
      : dashboardNow.getHours() < 18
        ? "Guten Tag"
        : "Guten Abend";
  const dashboardDate = new Intl.DateTimeFormat("de-DE", {
    weekday: "long",
    day: "2-digit",
    month: "long",
    year: "numeric",
  }).format(dashboardNow);
  const recentServiceTickets = tickets.filter((ticket) => {
    const date = new Date(ticket.updatedAt);
    if (Number.isNaN(date.getTime())) return false;
    const today = new Date();
    today.setHours(0, 0, 0, 0);
    const tomorrow = new Date(today);
    tomorrow.setDate(tomorrow.getDate() + 1);
    const yesterday = new Date(today);
    yesterday.setDate(yesterday.getDate() - 1);
    return date >= yesterday && date < tomorrow;
  });
  const svenjaStartItems = [
    {
      view: "tickets",
      icon: "▣",
      label: "Offene Tickets",
      detail: "Vorgänge warten auf Bearbeitung",
      count: tickets.length,
    },
    {
      view: "offers-all",
      icon: "▤",
      label: "Erstellte Angebote",
      detail: "Angebote warten noch auf den Versand",
      count: unsentOfferCount,
    },
    {
      view: "offers-open",
      icon: "▤",
      label: "Offene Angebote",
      detail: "Versendet – Rückmeldung steht noch aus",
      count: openOfferCount,
    },
    {
      view: "internal-tasks",
      icon: "☑",
      label: "Interne Aufgaben",
      detail: "Für dich oder gemeinsam",
      count: openTaskCount("svenja"),
    },
    {
      view: "invoices-create",
      icon: "✎",
      label: "Rechnungen anfertigen",
      detail: "Rechnungsaufgaben warten auf dich",
      count: openInvoiceCreateCount,
    },
    {
      view: "invoice-review-svenja",
      icon: "◈",
      label: "Rechnungen in Prüfung",
      detail: "Rechnungen in Saschas Prüfliste",
      count: openInvoiceReviewCount,
    },
    {
      view: "invoices-send",
      icon: "✉",
      label: "Rechnungen zum Versenden",
      detail: "Geprüfte Rechnungen warten auf den Versand",
      count: openInvoiceSendCount,
    },
    {
      view: "online-purchases",
      icon: "⌘",
      label: "Online Käufe",
      detail: "Belege warten auf die Ablage",
      count: openOnlinePurchaseCount,
    },
  ].filter((item) => item.count > 0);
  const visibleCustomers = customers
    .filter((customer) =>
      [
        customer.kundennummer_bestand,
        customer.firma,
        customer.anrede,
        customer.name,
        customer.ort,
        customer.telefon,
        customer.mobil,
        customer.email,
      ]
        .join(" ")
        .toLocaleLowerCase("de-DE")
        .includes(customerSearch.toLocaleLowerCase("de-DE")),
    )
    .sort((left, right) => {
      const collator = new Intl.Collator("de-DE", {
        numeric: true,
        sensitivity: "base",
      });
      const byName = collator.compare(
        left.firma || left.name || "",
        right.firma || right.name || "",
      );
      const byNumber = collator.compare(
        left.kundennummer_bestand || "",
        right.kundennummer_bestand || "",
      );
      if (customerSort === "name-desc") return -byName;
      if (customerSort === "number-asc") return byNumber;
      if (customerSort === "number-desc") return -byNumber;
      return byName;
    });
  const refreshOffers = async () => {
    setOffersLoading(true);
    setOffersError("");
    try {
      const response = await fetch("/api/offers", { cache: "no-store" });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Angebote konnten nicht geladen werden.",
        );
      setOffers(
        (Array.isArray(data.offers) ? data.offers : []).sort(
          (a: Offer, b: Offer) =>
            `${b.erstellt_am ?? ""}`.localeCompare(`${a.erstellt_am ?? ""}`),
        ),
      );
    } catch (error) {
      setOffersError(
        error instanceof Error
          ? error.message
          : "Die Angebote konnten nicht geladen werden.",
      );
    } finally {
      setOffersLoading(false);
    }
  };
  const updateOffer = async (
    offer: Offer,
    action: "versendet" | "beauftragt" | "zuruecksetzen",
  ) => {
    setOfferBusy(`${action}-${offer.id}`);
    setOffersError("");
    try {
      const response = await fetch("/api/offers", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(
          action === "versendet"
            ? {
                id: offer.id,
                action,
                versandart: offerShipping[offer.id] ?? "E-Mail",
              }
            : action === "beauftragt"
              ? {
                  id: offer.id,
                  action,
                  angebot_nummer: offer.angebot_nummer ?? "",
                  kunde: offer.kunde ?? "",
                  objekt_zusatz: offer.objekt_zusatz ?? "",
                }
              : { id: offer.id, action },
        ),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Das Angebot konnte nicht aktualisiert werden.",
        );
      await refreshOffers();
    } catch (error) {
      setOffersError(
        error instanceof Error
          ? error.message
          : "Das Angebot konnte nicht aktualisiert werden.",
      );
    } finally {
      setOfferBusy(null);
      setOfferConfirming(null);
    }
  };
  const deleteOffer = async (offer: Offer) => {
    if (
      !window.confirm(
        `Angebot ${offer.angebot_nummer || offer.dateiname} wirklich löschen?`,
      )
    )
      return;
    setOfferBusy(`delete-${offer.id}`);
    setOffersError("");
    try {
      const response = await fetch("/api/offers", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: offer.id }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Das Angebot konnte nicht gelöscht werden.",
        );
      setOffers((items) => items.filter((item) => item.id !== offer.id));
    } catch (error) {
      setOffersError(
        error instanceof Error
          ? error.message
          : "Das Angebot konnte nicht gelöscht werden.",
      );
    } finally {
      setOfferBusy(null);
    }
  };
  const refreshCustomers = async () => {
    setCustomersLoading(true);
    setCustomersError("");
    try {
      const response = await fetch("/api/customers", { cache: "no-store" });
      const data = await response.json();
      if (!response.ok)
        throw new Error(
          data.error ?? "Der Kundenstamm konnte nicht geladen werden.",
        );
      setCustomers(Array.isArray(data.customers) ? data.customers : []);
    } catch (error) {
      setCustomersError(
        error instanceof Error
          ? error.message
          : "Der Kundenstamm konnte nicht geladen werden.",
      );
    } finally {
      setCustomersLoading(false);
    }
  };
  const syncCustomerInvoices = async () => {
    const response = await fetch("/api/customer-invoices/sync", {
      method: "POST",
      cache: "no-store",
    }).catch(() => null);
    const data = response ? await response.json().catch(() => ({})) : {};
    if (!response?.ok)
      throw new Error(
        data.error ?? "Der Rechnungsabgleich ist zurzeit nicht verfügbar.",
      );
  };
  const customerInvoiceAliases = (customer: Customer) =>
    [
      ...new Set(
        [
          customer.firma,
          customer.name,
          [customer.anrede, customer.name].filter(Boolean).join(" "),
        ]
          .map((value) => String(value ?? "").trim())
          .filter(Boolean),
      ),
    ].join("|");
  const normalizeCustomerName = (value?: string) =>
    String(value ?? "")
      .toLocaleLowerCase("de-DE")
      .replace(/^(herrn?|frau)\s+/, "")
      .replace(/[ä]/g, "ae")
      .replace(/[ö]/g, "oe")
      .replace(/[ü]/g, "ue")
      .replace(/ß/g, "ss")
      .replace(/[^a-z0-9]+/g, " ")
      .trim();
  const knownCustomerInvoiceNames = new Set(
    customers.flatMap((customer) =>
      [
        customer.firma,
        customer.name,
        [customer.anrede, customer.name].filter(Boolean).join(" "),
      ]
        .map(normalizeCustomerName)
        .filter(Boolean),
    ),
  );
  const unassignedInvoices = invoiceOverview.filter(
    (invoice) =>
      !knownCustomerInvoiceNames.has(normalizeCustomerName(invoice.kunde)),
  );
  const refreshInvoiceOverview = async () => {
    setInvoiceOverviewLoading(true);
    setInvoiceOverviewError("");
    try {
      const response = await fetch("/api/customer-invoices?mode=all", {
        cache: "no-store",
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Rechnungen konnten nicht geladen werden.",
        );
      setInvoiceOverview(
        (Array.isArray(data.invoices) ? data.invoices : []).sort(
          (left: CustomerInvoice, right: CustomerInvoice) =>
            String(right.rechnungsdatum ?? "").localeCompare(
              String(left.rechnungsdatum ?? ""),
            ),
        ),
      );
    } catch (error) {
      setInvoiceOverviewError(
        error instanceof Error
          ? error.message
          : "Rechnungen konnten nicht geladen werden.",
      );
    } finally {
      setInvoiceOverviewLoading(false);
    }
  };
  const assignInvoiceToCustomer = async (
    invoice: CustomerInvoice,
    customer: Customer,
  ) => {
    const id = String(invoice.id ?? "");
    const kunde = customer.firma || customer.name || "";
    if (!id || !kunde) return;
    setInvoiceAssignmentBusy(id);
    setInvoiceOverviewError("");
    try {
      const response = await fetch("/api/customer-invoices", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({
          id,
          kunde,
          kundennummer: customer.kundennummer_bestand ?? "",
        }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(data.error ?? "Rechnung konnte nicht zugeordnet werden.");
      setInvoiceAssignmentSearch((current) => ({ ...current, [id]: "" }));
      await refreshInvoiceOverview();
    } catch (error) {
      setInvoiceOverviewError(
        error instanceof Error
          ? error.message
          : "Rechnung konnte nicht zugeordnet werden.",
      );
    } finally {
      setInvoiceAssignmentBusy(null);
    }
  };
  const openCustomerInvoices = async (customer: Customer) => {
    const kunde = customer.firma || customer.name || "";
    setInvoiceCustomer(customer);
    setCustomerInvoicesLoading(true);
    setInvoiceProperties([]);
    setPropertyInvoices({});
    setPropertyInvoiceError({});
    try {
      await syncCustomerInvoices();
      const response = await fetch(
        `/api/customer-invoices?kunde=${encodeURIComponent(kunde)}&aliases=${encodeURIComponent(customerInvoiceAliases(customer))}&mode=summary`,
        { cache: "no-store" },
      );
      const data = await response.json();
      if (!response.ok)
        throw new Error(
          data.error ?? "Rechnungen konnten nicht geladen werden.",
        );
      setInvoiceProperties(
        Array.isArray(data.properties) ? data.properties : [],
      );
    } catch (error) {
      setCustomersError(
        error instanceof Error
          ? error.message
          : "Rechnungen konnten nicht geladen werden.",
      );
    } finally {
      setCustomerInvoicesLoading(false);
    }
  };
  const loadPropertyInvoices = async (liegenschaft: string) => {
    if (
      !invoiceCustomer ||
      propertyInvoices[liegenschaft] ||
      propertyInvoiceLoading === liegenschaft
    )
      return;
    const kunde = invoiceCustomer.firma || invoiceCustomer.name || "";
    setPropertyInvoiceLoading(liegenschaft);
    setPropertyInvoiceError((errors) => ({ ...errors, [liegenschaft]: "" }));
    try {
      const response = await fetch(
        `/api/customer-invoices?kunde=${encodeURIComponent(kunde)}&aliases=${encodeURIComponent(customerInvoiceAliases(invoiceCustomer))}&liegenschaft=${encodeURIComponent(liegenschaft)}`,
        { cache: "no-store" },
      );
      const data = await response.json();
      if (!response.ok)
        throw new Error(
          data.error ?? "Rechnungen konnten nicht geladen werden.",
        );
      setPropertyInvoices((items) => ({
        ...items,
        [liegenschaft]: Array.isArray(data.invoices) ? data.invoices : [],
      }));
    } catch (error) {
      setPropertyInvoiceError((errors) => ({
        ...errors,
        [liegenschaft]:
          error instanceof Error
            ? error.message
            : "Rechnungen konnten nicht geladen werden.",
      }));
    } finally {
      setPropertyInvoiceLoading((current) =>
        current === liegenschaft ? null : current,
      );
    }
  };
  const saveCustomer = async () => {
    if (!editingCustomer) return;
    if (!(editingCustomer.firma ?? "").trim() && !(editingCustomer.name ?? "").trim()) {
      setCustomersError("Bitte mindestens Firma oder Kundenname eintragen.");
      return;
    }
    setCustomerSaving(true);
    setCustomersError("");
    try {
      const response = await fetch("/api/customers", {
        method: creatingCustomer ? "POST" : "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(editingCustomer),
      });
      const data = await response.json();
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Kundendaten konnten nicht gespeichert werden.",
        );
      if (creatingCustomer) await refreshCustomers();
      else setCustomers((items) =>
        items.map((item) =>
          item.id === editingCustomer.id
            ? {
                ...item,
                ...editingCustomer,
                aktualisiert_am:
                  data.customer?.aktualisiert_am ?? new Date().toISOString(),
              }
            : item,
        ),
      );
      setEditingCustomer(null);
      setCreatingCustomer(false);
    } catch (error) {
      setCustomersError(
        error instanceof Error
          ? error.message
          : "Die Kundendaten konnten nicht gespeichert werden.",
      );
    } finally {
      setCustomerSaving(false);
    }
  };
  const deleteCustomer = async () => {
    if (!editingCustomer || !isSascha) return;
    setCustomerSaving(true);
    setCustomersError("");
    try {
      const response = await fetch("/api/customers", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: editingCustomer.id }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ??
            "Der Kunde konnte nicht aus dem Kundenstamm gelöscht werden.",
        );
      setCustomers((items) =>
        items.filter((item) => item.id !== editingCustomer.id),
      );
      setEditingCustomer(null);
      setCreatingCustomer(false);
    } catch (error) {
      setCustomersError(
        error instanceof Error
          ? error.message
          : "Der Kunde konnte nicht aus dem Kundenstamm gelöscht werden.",
      );
    } finally {
      setCustomerSaving(false);
      setCustomerDeleteConfirming(false);
    }
  };
  const refreshOnlinePurchases = async () => {
    setOnlinePurchasesLoading(true);
    setOnlinePurchasesError("");
    try {
      const response = await fetch("/api/online-purchases", {
        cache: "no-store",
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Online-Käufe konnten nicht geladen werden.",
        );
      const purchases = Array.isArray(data.purchases) ? data.purchases : [];
      purchases.sort((left: OnlinePurchase, right: OnlinePurchase) => {
        const leftDone = left.status?.toLocaleLowerCase("de-DE") === "erledigt";
        const rightDone =
          right.status?.toLocaleLowerCase("de-DE") === "erledigt";
        if (leftDone !== rightDone) return leftDone ? 1 : -1;
        return `${right.kaufdatum ?? ""}${right.angelegt_am ?? ""}`.localeCompare(
          `${left.kaufdatum ?? ""}${left.angelegt_am ?? ""}`,
          "de",
        );
      });
      setOnlinePurchases(purchases);
    } catch (error) {
      setOnlinePurchasesError(
        error instanceof Error
          ? error.message
          : "Die Online-Käufe konnten nicht geladen werden.",
      );
    } finally {
      setOnlinePurchasesLoading(false);
    }
  };
  const saveOnlinePurchase = async (
    event: FormEvent<HTMLFormElement>,
  ) => {
    event.preventDefault();
    const artikel = onlinePurchaseForm.artikel.trim();
    const kaufort = onlinePurchaseForm.kaufort.trim();
    const kaufdatum = onlinePurchaseForm.kaufdatum;
    if (!artikel || !kaufort || !kaufdatum) {
      setOnlinePurchasesError(
        "Bitte Artikel, Marktplatz und Kaufdatum ausfüllen.",
      );
      return;
    }
    setOnlinePurchaseSaving(true);
    setOnlinePurchasesError("");
    try {
      const response = await fetch("/api/online-purchases", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ artikel, kaufort, kaufdatum }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Der Online-Kauf konnte nicht gespeichert werden.",
        );
      setOnlinePurchaseForm({
        artikel: "",
        kaufort: "",
        kaufdatum: new Date().toISOString().slice(0, 10),
      });
      await refreshOnlinePurchases();
    } catch (error) {
      setOnlinePurchasesError(
        error instanceof Error
          ? error.message
          : "Der Online-Kauf konnte nicht gespeichert werden.",
      );
    } finally {
      setOnlinePurchaseSaving(false);
    }
  };
  const completeOnlinePurchase = async (purchase: OnlinePurchase) => {
    setOnlinePurchaseCompleting(purchase.id);
    setOnlinePurchasesError("");
    try {
      const response = await fetch("/api/online-purchases", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: String(purchase.id) }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Der Kauf konnte nicht abgeschlossen werden.",
        );
      setOnlinePurchases((items) =>
        items.map((item) =>
          item.id === purchase.id
            ? {
                ...item,
                status: "erledigt",
                erledigt_von: "Svenja",
                erledigt_am: data.erledigt_am ?? new Date().toISOString(),
              }
            : item,
        ),
      );
    } catch (error) {
      setOnlinePurchasesError(
        error instanceof Error
          ? error.message
          : "Der Kauf konnte nicht abgeschlossen werden.",
      );
    } finally {
      setOnlinePurchaseCompleting(null);
    }
  };
  const refreshInternalTasks = async () => {
    const response = await fetch("/api/internal-tasks", { cache: "no-store" });
    const data = await response.json().catch(() => ({}));
    if (!response.ok) {
      setInternalTaskError(
        data.error ?? "Interne Aufgaben konnten nicht geladen werden.",
      );
      return;
    }
    setInternalTasks(
      (data.tasks ?? []).sort(
        (a: InternalTask, b: InternalTask) =>
          (a.status === "erledigt" ? 1 : 0) -
            (b.status === "erledigt" ? 1 : 0) ||
          `${b.erstellt_am ?? ""}`.localeCompare(`${a.erstellt_am ?? ""}`),
      ),
    );
  };
  const saveInternalTask = async (
    event: FormEvent<HTMLFormElement>,
    empfaenger: "sascha" | "svenja",
  ) => {
    event.preventDefault();
    const draft = internalTaskDrafts[empfaenger] ?? {
      aufgabe: "",
      kategorie: "angebote",
      kunden_id: "",
    };
    const aufgabe = draft.aufgabe.trim();
    if (!aufgabe) return;
    setInternalTaskBusy(`new-${empfaenger}`);
    setInternalTaskError("");
    const response = await fetch("/api/internal-tasks", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        aufgabe,
        empfaenger,
        kategorie: draft.kategorie,
        kunden_id: draft.kunden_id,
      }),
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok)
      setInternalTaskError(
        data.error ?? "Aufgabe konnte nicht gespeichert werden.",
      );
    else {
      setInternalTaskDrafts((value) => ({
        ...value,
        [empfaenger]: { aufgabe: "", kategorie: "angebote", kunden_id: "" },
      }));
      setInternalTaskCustomerSearch((value) => ({
        ...value,
        [empfaenger]: "",
      }));
      await refreshInternalTasks();
    }
    setInternalTaskBusy(null);
  };
  const changeInternalTask = async (
    task: InternalTask,
    method: "PUT" | "DELETE",
  ) => {
    setInternalTaskBusy(task.id);
    setInternalTaskError("");
    const response = await fetch("/api/internal-tasks", {
      method,
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ id: task.id }),
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok)
      setInternalTaskError(
        data.error ?? "Aufgabe konnte nicht geändert werden.",
      );
    else await refreshInternalTasks();
    setInternalTaskBusy(null);
  };
  const updateInternalTask = async (
    event: FormEvent<HTMLFormElement>,
  ) => {
    event.preventDefault();
    if (!editingInternalTask) return;
    const form = new FormData(event.currentTarget);
    const aufgabe = String(form.get("aufgabe") ?? "").trim();
    const empfaenger = String(form.get("empfaenger") ?? "");
    const kategorie = String(form.get("kategorie") ?? "");
    const kunden_id = String(form.get("kunden_id") ?? "");
    setInternalTaskBusy(editingInternalTask.id);
    setInternalTaskError("");
    const response = await fetch("/api/internal-tasks", {
      method: "PATCH",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        id: editingInternalTask.id,
        aufgabe,
        empfaenger,
        kategorie,
        kunden_id,
      }),
    });
    const data = await response.json().catch(() => ({}));
    if (!response.ok)
      setInternalTaskError(
        data.error ?? "Aufgabe konnte nicht bearbeitet werden.",
      );
    else {
      setEditingInternalTask(null);
      await refreshInternalTasks();
    }
    setInternalTaskBusy(null);
  };
  const deleteOnlinePurchase = async (purchase: OnlinePurchase) => {
    setOnlinePurchaseDeleting(purchase.id);
    setOnlinePurchasesError("");
    try {
      const response = await fetch("/api/online-purchases", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: String(purchase.id) }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(data.error ?? "Der Kauf konnte nicht gelöscht werden.");
      setOnlinePurchases((items) =>
        items.filter((item) => item.id !== purchase.id),
      );
    } catch (error) {
      setOnlinePurchasesError(
        error instanceof Error
          ? error.message
          : "Der Kauf konnte nicht gelöscht werden.",
      );
    } finally {
      setOnlinePurchaseDeleting(null);
    }
  };
  const refreshInvoiceReviews = async () => {
    setInvoiceReviewsLoading(true);
    setInvoiceReviewsError("");
    try {
      const response = await fetch("/api/invoices-review", {
        cache: "no-store",
      });
      const data = await response.json();
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Prüfliste konnte nicht geladen werden.",
        );
      setInvoiceReviews(Array.isArray(data.invoices) ? data.invoices : []);
      setInvoiceReviewsRefreshedAt(
        data.generatedAt ?? new Date().toISOString(),
      );
    } catch (error) {
      setInvoiceReviewsError(
        error instanceof Error
          ? error.message
          : "Die Prüfliste konnte nicht geladen werden.",
      );
    } finally {
      setInvoiceReviewsLoading(false);
    }
  };
  const refreshInvoiceCreateTasks = async () => {
    setInvoiceCreateLoading(true);
    setInvoiceCreateError("");
    try {
      const response = await fetch("/api/invoices-create", {
        cache: "no-store",
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Rechnungsaufgaben konnten nicht geladen werden.",
        );
      setInvoiceCreateTasks(Array.isArray(data.invoices) ? data.invoices : []);
      setInvoiceCreateRefreshedAt(data.generatedAt ?? new Date().toISOString());
    } catch (error) {
      setInvoiceCreateError(
        error instanceof Error
          ? error.message
          : "Die Rechnungsaufgaben konnten nicht geladen werden.",
      );
    } finally {
      setInvoiceCreateLoading(false);
    }
  };
  const refreshInvoiceSendTasks = async () => {
    setInvoiceSendLoading(true);
    setInvoiceSendError("");
    try {
      const response = await fetch("/api/invoices-send", { cache: "no-store" });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Die Versandaufgaben konnten nicht geladen werden.",
        );
      setInvoiceSendTasks(Array.isArray(data.invoices) ? data.invoices : []);
      setInvoiceSendRefreshedAt(data.generatedAt ?? new Date().toISOString());
    } catch (error) {
      setInvoiceSendError(
        error instanceof Error
          ? error.message
          : "Die Versandaufgaben konnten nicht geladen werden.",
      );
    } finally {
      setInvoiceSendLoading(false);
    }
  };
  const completeInvoiceCreateTask = async (task: InvoiceReview) => {
    setInvoiceCreateCompleting(task.id);
    setInvoiceCreateError("");
    try {
      const response = await fetch("/api/invoices-create", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: String(task.id) }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ??
            "Die Rechnungsaufgabe konnte nicht abgeschlossen werden.",
        );
      setInvoiceCreateTasks((tasks) =>
        tasks.map((item) =>
          item.id === task.id
            ? {
                ...item,
                status: "erledigt",
                completedAt: data.erledigt_am ?? new Date().toISOString(),
              }
            : item,
        ),
      );
    } catch (error) {
      setInvoiceCreateError(
        error instanceof Error
          ? error.message
          : "Die Rechnungsaufgabe konnte nicht abgeschlossen werden.",
      );
    } finally {
      setInvoiceCreateCompleting(null);
    }
  };
  const completeInvoiceReview = async (invoice: InvoiceReview) => {
    setInvoiceReviewCompleting(invoice.id);
    setInvoiceReviewsError("");
    try {
      const response = await fetch("/api/invoices-review", {
        method: "PUT",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ id: String(invoice.id) }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok || data?.ok === false)
        throw new Error(
          data?.error ??
            "Die Rechnungsprüfung konnte nicht abgeschlossen werden.",
        );
      await refreshInvoiceReviews();
    } catch (error) {
      setInvoiceReviewsError(
        error instanceof Error
          ? error.message
          : "Die Rechnungsprüfung konnte nicht abgeschlossen werden.",
      );
    } finally {
      setInvoiceReviewCompleting(null);
    }
  };
  useEffect(() => {
    document.documentElement.dataset.theme = "dark";
  }, []);
  useEffect(() => {
    const timer = window.setInterval(() => setDashboardNow(new Date()), 30_000);
    return () => window.clearInterval(timer);
  }, []);
  // Die Navigations-Badges müssen sofort nach der Anmeldung sichtbar sein.
  useEffect(() => {
    if (user) void refreshInvoiceReviews();
  }, [user]);
  useEffect(() => {
    if (isSvenja) void refreshInvoiceCreateTasks();
  }, [user]);
  useEffect(() => {
    if (isSvenja) void refreshInvoiceSendTasks();
  }, [user]);
  useEffect(() => {
    if (user) void refreshCustomers();
  }, [user]);
  useEffect(() => {
    if (user) void syncCustomerInvoices().catch(() => undefined);
  }, [user]);
  useEffect(() => {
    if (user && view === "customer-invoices") void refreshInvoiceOverview();
  }, [user, view]);
  useEffect(() => {
    if (user) void refreshOffers();
  }, [user]);
  useEffect(() => {
    if (
      user &&
      ((isSascha && view === "online-purchases-new") ||
        (isSvenja && view === "online-purchases"))
    )
      void refreshOnlinePurchases();
  }, [user, view]);
  useEffect(() => {
    if (user) void refreshOnlinePurchases();
  }, [user]);
  useEffect(() => {
    if (user)
      void refreshInternalTasks().catch(() =>
        setInternalTaskError("Interne Aufgaben konnten nicht geladen werden."),
      );
  }, [user]);
  useEffect(() => {
    if (!user) return;
    let active = true;
    const load = async () => {
      setHoursLoading(true);
      setHoursError("");
      const response = await fetch("/api/hours", { cache: "no-store" }).catch(
        () => null,
      );
      const data = response ? await response.json().catch(() => ({})) : {};
      if (!active) return;
      if (!response?.ok) {
        setHoursError(
          data.error ?? "Die Stundennachweise konnten nicht geladen werden.",
        );
        setHoursLoading(false);
        return;
      }
      setHoursOverview(data);
      setHoursLoading(false);
    };
    void load();
    return () => {
      active = false;
    };
  }, [user]);
  // Auth-Sonde, Sitzungsverlängerung und Leerlaufabmeldung liegen jetzt im
  // AuthProvider. Diese Ansicht bekommt den angemeldeten Benutzer fertig geliefert.
  const refreshTickets = async () => {
    setTicketsLoading(true);
    setTicketsError("");
    const response = await fetch("/api/tickets", { cache: "no-store" }).catch(
      () => null,
    );
    const data = response ? await response.json().catch(() => ({})) : {};
    if (!response?.ok) {
      setTicketsError(
        data.error ?? "Die offenen Tickets konnten nicht geladen werden.",
      );
      setTicketsLoading(false);
      return;
    }
    setTickets(Array.isArray(data.tickets) ? data.tickets : []);
    setTicketsRefreshedAt(data.refreshedAt ?? new Date().toISOString());
    setTicketsLoading(false);
  };
  useEffect(() => {
    if (user) void refreshTickets();
  }, [user]);
  const needsCustomerConsultation = (ticket: OpenTicket) =>
    ticket.requiresCustomerConsultation === true;
  const saveCustomerConsultation = async (ticket: OpenTicket) => {
    const result = (
      consultationDrafts[ticket.id] ??
      ticket.consultationResult ??
      ""
    ).trim();
    if (!result) {
      setConsultationError((errors) => ({
        ...errors,
        [ticket.id]: "Bitte trage das Ergebnis der Rücksprache ein.",
      }));
      return;
    }
    setConsultationSaving(ticket.id);
    setConsultationError((errors) => ({ ...errors, [ticket.id]: "" }));
    try {
      const response = await fetch("/api/tickets/consultation", {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ ticketnummer: ticket.id, ergebnis: result }),
      });
      const data = await response.json().catch(() => ({}));
      if (!response.ok)
        throw new Error(
          data.error ?? "Das Ergebnis konnte nicht gespeichert werden.",
        );
      const updatedAt = data.updatedAt ?? new Date().toISOString();
      setTickets((items) =>
        items.map((item) =>
          item.id === ticket.id
            ? {
                ...item,
                consultationResult: result,
                consultationUpdatedAt: updatedAt,
                consultationBy: "Svenja",
              }
            : item,
        ),
      );
      setConsultationDrafts((drafts) => ({ ...drafts, [ticket.id]: result }));
    } catch (error) {
      setConsultationError((errors) => ({
        ...errors,
        [ticket.id]:
          error instanceof Error
            ? error.message
            : "Das Ergebnis konnte nicht gespeichert werden.",
      }));
    } finally {
      setConsultationSaving(null);
    }
  };
  useEffect(() => {
    if (!user || view !== "tickets") return;
    let active = true;
    const load = async () => {
      const response = await fetch("/api/tickets", { cache: "no-store" }).catch(
        () => null,
      );
      const data = response ? await response.json().catch(() => ({})) : {};
      if (!active) return;
      if (!response?.ok) {
        setTicketsError(
          data.error ?? "Die offenen Tickets konnten nicht geladen werden.",
        );
        return;
      }
      setTickets(Array.isArray(data.tickets) ? data.tickets : []);
      setTicketsRefreshedAt(data.refreshedAt ?? new Date().toISOString());
      setTicketsError("");
    };
    void load();
    const interval = window.setInterval(() => void load(), 20000);
    return () => {
      active = false;
      window.clearInterval(interval);
    };
  }, [user, view]);
  useEffect(() => {
    if (!user || view !== "time-records") return;
    let active = true;
    const load = async () => {
      setHoursLoading(true);
      setHoursError("");
      const response = await fetch("/api/hours", { cache: "no-store" }).catch(
        () => null,
      );
      const data = response ? await response.json().catch(() => ({})) : {};
      if (!active) return;
      if (!response?.ok) {
        setHoursError(
          data.error ?? "Die Stundennachweise konnten nicht geladen werden.",
        );
        setHoursLoading(false);
        return;
      }
      setHoursOverview(data);
      setHoursLoading(false);
    };
    void load();
    return () => {
      active = false;
    };
  }, [user, view]);
  // Anmeldemaske und Ladezustand rendert die AuthGate-Hülle in App.tsx.
  // Ab hier ist garantiert jemand angemeldet.
  const logout = signOut;

  // App.tsx rendert diese Ansicht nur angemeldet. Die Abfrage engt für
  // TypeScript den Typ von `user` auf string ein und kostet sonst nichts.
  if (!user) return null;

  return (
    <main className="training-shell">
      <header className="app-header">
        <div className="company">
          <img
            src="/elektro-krueger-logo.png"
            alt="Elektro Krüger – Wir setzen Sie unter Strom."
          />
        </div>
        <div className="app-title">
          <b>EK-DOS</b>
          <span>Die digitale Schaltzentrale</span>
        </div>
        <div className="session-user">
          <b>{user.slice(0, 1)}</b>
          <span>
            {user}
            <small>angemeldet</small>
          </span>
          <button onClick={logout}>Abmelden</button>
        </div>
      </header>
      <div className="app-body">
        <aside className="app-nav">
          <button
            className={view === "home" ? "selected" : ""}
            onClick={() => setView("home")}
          >
            <span>⌂</span>Dashboard
          </button>
          <button
            className={view === "customers" ? "selected" : ""}
            onClick={() => setView("customers")}
          >
            <span>♙</span>Kundenstamm
          </button>
          <button
            className={view === "customer-invoices" ? "selected" : ""}
            onClick={() => setView("customer-invoices")}
          >
            <span>▤</span>Rechnungen
          </button>
          <button
            className={view === "tickets" ? "selected" : ""}
            onClick={() => setView("tickets")}
          >
            <span>▣</span>Offene Tickets
            {tickets.length > 0 && (
              <i className="nav-count">{tickets.length}</i>
            )}
          </button>
          <button
            className={view.startsWith("offers-") ? "selected" : ""}
            onClick={() => setOffersOpen((value) => !value)}
          >
            <span>▤</span>Angebote
            <i className={offersOpen ? "nav-chevron open" : "nav-chevron"}>⌄</i>
            {unsentOfferCount > 0 && (
              <i className="nav-badge">{unsentOfferCount}</i>
            )}
          </button>
          {offersOpen && (
            <div className="nav-submenu">
              <button
                className={view === "offers-all" ? "active" : ""}
                onClick={() => setView("offers-all")}
              >
                Erstellte Angebote
                {unsentOfferCount > 0 && (
                  <i className="nav-badge">{unsentOfferCount}</i>
                )}
              </button>
              <button
                className={view === "offers-open" ? "active" : ""}
                onClick={() => setView("offers-open")}
              >
                Offene Angebote
                {openOfferCount > 0 && (
                  <i className="nav-badge">{openOfferCount}</i>
                )}
              </button>
              <button
                className={view === "offers-commissioned" ? "active" : ""}
                onClick={() => setView("offers-commissioned")}
              >
                Beauftragte Angebote
              </button>
              <button
                className={view === "offers-expired" ? "active" : ""}
                onClick={() => setView("offers-expired")}
              >
                Abgelaufene Angebote
              </button>
            </div>
          )}
          <button
            className={view === "time-records" ? "selected" : ""}
            onClick={() => setView("time-records")}
          >
            <span>◷</span>Stundennachweise
          </button>
          <button
            className={view === "internal-tasks" ? "selected" : ""}
            onClick={() => {
              setView("internal-tasks");
              setInternalTaskFilter(null);
              setInternalTaskRecipientFilter(isSascha ? "sascha" : "svenja");
              setInternalTasksOpen((value) => !value);
            }}
          >
            <span>☑</span>Interne Aufgaben
            <i
              className={internalTasksOpen ? "nav-chevron open" : "nav-chevron"}
            >
              ⌄
            </i>
            {user && openTaskCount(isSascha ? "sascha" : "svenja") > 0 && (
              <i className="nav-badge">
                {openTaskCount(isSascha ? "sascha" : "svenja")}
              </i>
            )}
          </button>
          {internalTasksOpen && (
            <div className="nav-submenu">
              {internalTaskCategories.map(([key, label]) => {
                const count = openTaskCategoryCount(key);
                return (
                  <button
                    key={key}
                    className={
                      view === "internal-tasks" &&
                      activeInternalTaskRecipient ===
                        (isSascha ? "sascha" : "svenja") &&
                      internalTaskFilter === key
                        ? "active"
                        : ""
                    }
                    onClick={() => {
                      setView("internal-tasks");
                      setInternalTaskRecipientFilter(
                        isSascha ? "sascha" : "svenja",
                      );
                      setInternalTaskFilter(key);
                    }}
                  >
                    {label}
                    {count > 0 && <i className="nav-badge">{count}</i>}
                  </button>
                );
              })}
              {isSvenja && (
                <>
                  <button
                    className={
                      activeInternalTaskRecipient === "sascha" ? "active" : ""
                    }
                    onClick={() => {
                      setView("internal-tasks");
                      setInternalTaskRecipientFilter("sascha");
                      setInternalTaskFilter(null);
                      setSaschaTasksOpen((value) => !value);
                    }}
                  >
                    Saschas Aufgaben
                    <i
                      className={
                        saschaTasksOpen ? "nav-chevron open" : "nav-chevron"
                      }
                    >
                      ⌄
                    </i>
                    {openTaskCount("sascha") > 0 && (
                      <i className="nav-badge">{openTaskCount("sascha")}</i>
                    )}
                  </button>
                  {saschaTasksOpen && (
                    <div className="nav-submenu nav-submenu-nested">
                      {activeInternalTaskCategories.map(([key, label]) => {
                        const count = openTaskCategoryCount(key, "sascha");
                        return (
                          <button
                            key={key}
                            className={
                              view === "internal-tasks" &&
                              activeInternalTaskRecipient === "sascha" &&
                              internalTaskFilter === key
                                ? "active"
                                : ""
                            }
                            onClick={() => {
                              setView("internal-tasks");
                              setInternalTaskRecipientFilter("sascha");
                              setInternalTaskFilter(key);
                            }}
                          >
                            {label}
                            {count > 0 && <i className="nav-badge">{count}</i>}
                          </button>
                        );
                      })}
                    </div>
                  )}
                </>
              )}
            </div>
          )}
          {isSvenja && (
            <>
              <button
                className={
                  view === "invoices-create" || view === "invoices-created"
                    ? "selected"
                    : ""
                }
                onClick={() => {
                  setView("invoices-create");
                  setInvoiceCreateOpen((value) => !value);
                }}
              >
                <span>✎</span>Rechnungen anfertigen
                {openInvoiceCreateCount > 0 && (
                  <i className="nav-badge">{openInvoiceCreateCount}</i>
                )}
                <i
                  className={
                    invoiceCreateOpen ? "nav-chevron open" : "nav-chevron"
                  }
                >
                  ⌄
                </i>
              </button>
              {invoiceCreateOpen && (
                <div className="nav-submenu">
                  <button
                    className={view === "invoices-created" ? "active" : ""}
                    onClick={() => setView("invoices-created")}
                  >
                    Erstellte Rechnungen
                  </button>
                </div>
              )}
            </>
          )}
          {isSvenja && (
            <button
              className={view === "invoice-review-svenja" ? "selected" : ""}
              onClick={() => setView("invoice-review-svenja")}
            >
              <span>◈</span>Rechnungen in Prüfung
              {openInvoiceReviewCount > 0 && (
                <i className="nav-badge">{openInvoiceReviewCount}</i>
              )}
            </button>
          )}
          {isSvenja && (
            <button
              className={view === "invoices-send" ? "selected" : ""}
              onClick={() => setView("invoices-send")}
            >
              <span>✉</span>Rechnungen zum Versenden
              {openInvoiceSendCount > 0 && (
                <i className="nav-badge">{openInvoiceSendCount}</i>
              )}
            </button>
          )}
          <button
            className={view === "training" ? "selected" : ""}
            onClick={() => setView("training")}
          >
            <span>▷</span>Schulung &amp; Arbeitsablauf
          </button>
          {canManageUsers && (
            <button
              className={view === "users" ? "selected" : ""}
              onClick={() => setView("users")}
            >
              <span>⚙</span>Benutzer
            </button>
          )}
          {isSvenja && (
            <div className="nav-role">
              <b>Svenja</b>
              <button
                className={view === "online-purchases" ? "selected" : ""}
                onClick={() => setView("online-purchases")}
              >
                <span>⌘</span>Online Käufe
                {openOnlinePurchaseCount > 0 && (
                  <i className="nav-badge">{openOnlinePurchaseCount}</i>
                )}
              </button>
            </div>
          )}
          {isSascha && (
            <div className="nav-role">
              <b>Sascha</b>
              <button
                className={view === "online-purchases-new" ? "selected" : ""}
                onClick={() => setView("online-purchases-new")}
              >
                <span>⌘</span>Neue Online Käufe
                {openOnlinePurchaseCount > 0 && (
                  <i className="nav-badge">{openOnlinePurchaseCount}</i>
                )}
              </button>
              <button
                className={view === "invoices-review-sascha" ? "selected" : ""}
                onClick={() => setView("invoices-review-sascha")}
              >
                <span>✓</span>Rechnungen prüfen
                {openInvoiceReviewCount > 0 && (
                  <i className="nav-badge">{openInvoiceReviewCount}</i>
                )}
              </button>
              <button
                className={view === "postcalculation" ? "selected" : ""}
                onClick={() => setView("postcalculation")}
              >
                <span>◫</span>Nachkalkulation
              </button>
              <button
                className={view === "unit-prices" ? "selected" : ""}
                onClick={() => setView("unit-prices")}
              >
                <span>€</span>Einheitspreise
              </button>
              <button
                className={
                  view === "analytics" || view === "cashflow" ? "selected" : ""
                }
                onClick={() => setAnalyticsOpen((value) => !value)}
              >
                <span>◔</span>Auswertungen
                <i
                  className={analyticsOpen ? "nav-chevron open" : "nav-chevron"}
                >
                  ⌄
                </i>
              </button>
              {analyticsOpen && (
                <div className="nav-submenu">
                  <button
                    className={view === "analytics" ? "active" : ""}
                    onClick={() => setView("analytics")}
                  >
                    Übersicht
                  </button>
                  <button
                    className={view === "cashflow" ? "active" : ""}
                    onClick={() => setView("cashflow")}
                  >
                    Cashflow
                  </button>
                </div>
              )}
            </div>
          )}
          <div className="system">
            <span>●</span>
            <div>
              <b>Systemstatus</b>
              <small>Alle Systeme online</small>
            </div>
          </div>
        </aside>
        {view === "users" ? (
          <UsersView />
        ) : view === "customers" ? (
          <section className="customers-page">
            <div className="customers-heading">
              <div>
                <p className="home-kicker">EK-DOS · STAMMDATEN</p>
                <h2>Kundenstamm</h2>
                <p>Kundendaten, interne Notizen und direkte Neuanlage von Kunden.</p>
              </div>
              <div className="customers-heading-actions">
                <button
                  className="customer-create-button"
                  onClick={() => {
                    setCustomerTaskFilter("all");
                    setCustomerDeleteConfirming(false);
                    setCreatingCustomer(true);
                    setEditingCustomer({ id: "" });
                  }}
                >
                  Kunde anlegen
                </button>
                <button
                  onClick={() => void refreshCustomers()}
                  disabled={customersLoading}
                >
                  {customersLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
                </button>
              </div>
            </div>
            <div className="customers-toolbar">
              <input
                value={customerSearch}
                onChange={(event) => setCustomerSearch(event.target.value)}
                placeholder="Kunde, Firma, Ort oder Telefonnummer suchen …"
              />
              <label>
                Sortieren
                <select
                  value={customerSort}
                  onChange={(event) =>
                    setCustomerSort(event.target.value as typeof customerSort)
                  }
                >
                  <option value="name-asc">Name A–Z</option>
                  <option value="name-desc">Name Z–A</option>
                  <option value="number-asc">Kundennummer aufsteigend</option>
                  <option value="number-desc">Kundennummer absteigend</option>
                </select>
              </label>
              <span>
                {visibleCustomers.length} von {customers.length} Kunden
              </span>
            </div>
            {customersError && (
              <div className="tickets-error">{customersError}</div>
            )}
            {!customersError && customersLoading && customers.length === 0 && (
              <div className="tickets-empty">
                <b>Kundenstamm wird geladen …</b>
              </div>
            )}
            {!customersError && customers.length > 0 && (
              <div className="customers-table-wrap">
                <table className="customers-table">
                  <thead>
                    <tr>
                      <th>Kundennummer</th>
                      <th>Kunde</th>
                      <th>Anschrift</th>
                      <th>Kontakt</th>
                      <th>Interne Notiz</th>
                      <th />
                    </tr>
                  </thead>
                  <tbody>
                    {visibleCustomers.map((customer) => {
                      const contactName = [customer.anrede, customer.name]
                        .filter(Boolean)
                        .join(" ");
                      return (
                        <tr key={customer.id}>
                          <td>
                            <b>{customer.kundennummer_bestand || "–"}</b>
                          </td>
                          <td>
                            <strong>
                              {customer.firma ||
                                contactName ||
                                "Unbenannter Kunde"}
                            </strong>
                            {customer.firma && contactName && (
                              <small>{contactName}</small>
                            )}
                          </td>
                          <td>
                            {[
                              customer.strasse,
                              [customer.plz, customer.ort]
                                .filter(Boolean)
                                .join(" "),
                            ]
                              .filter(Boolean)
                              .join(" · ") || "–"}
                          </td>
                          <td>
                            {[
                              customer.telefon && `Tel. ${customer.telefon}`,
                              customer.mobil && `Mobil ${customer.mobil}`,
                              customer.email,
                            ]
                              .filter(Boolean)
                              .join(" · ") || "–"}
                          </td>
                          <td className="customer-note-cell">
                            {customer.notiz || "–"}
                          </td>
                          <td>
                            <div className="customer-row-actions">
                              <button
                                onClick={() =>
                                  void openCustomerInvoices(customer)
                                }
                              >
                                Rechnungen
                              </button>
                              <button
                                onClick={() => {
                                  setCustomerTaskFilter("all");
                                  setEditingCustomer({ ...customer });
                                }}
                              >
                                Akte einsehen
                              </button>
                            </div>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
            {invoiceCustomer && (
              <div
                className="customer-modal-backdrop"
                role="dialog"
                aria-modal="true"
              >
                <div className="customer-modal invoice-modal">
                  <div>
                    <p className="home-kicker">RECHNUNGEN</p>
                    <h3>
                      {invoiceCustomer.firma || invoiceCustomer.name || "Kunde"}
                    </h3>
                    <p className="invoice-modal-hint">
                      Rechnungen nach Liegenschaft
                    </p>
                  </div>
                  {customerInvoicesLoading ? (
                    <p>Rechnungen werden geladen …</p>
                  ) : invoiceProperties.length === 0 ? (
                    <p>
                      Für diesen Kunden liegen noch keine zugeordneten
                      Rechnungen vor.
                    </p>
                  ) : (
                    <div className="invoice-property-list">
                      {invoiceProperties.map(({ liegenschaft, count }) => {
                        const invoices = propertyInvoices[liegenschaft];
                        const loading = propertyInvoiceLoading === liegenschaft;
                        return (
                          <details
                            className="invoice-property-card"
                            key={liegenschaft}
                            onToggle={(event) => {
                              if (event.currentTarget.open)
                                void loadPropertyInvoices(liegenschaft);
                            }}
                          >
                            <summary>
                              <span className="invoice-property-icon">⌂</span>
                              <span>
                                <b>{liegenschaft}</b>
                                <small>
                                  {count}{" "}
                                  {count === 1 ? "Rechnung" : "Rechnungen"}
                                </small>
                              </span>
                              <i>⌄</i>
                            </summary>
                            <div className="invoice-items">
                              {loading ? (
                                <p>Rechnungen werden geladen …</p>
                              ) : propertyInvoiceError[liegenschaft] ? (
                                <p>{propertyInvoiceError[liegenschaft]}</p>
                              ) : (
                                invoices?.map((invoice) => (
                                  <div
                                    className="invoice-item"
                                    key={invoice.dateiname}
                                  >
                                    <span>
                                      <b>
                                        Rechnung{" "}
                                        {invoice.rechnungsnummer ||
                                          invoice.dateiname}
                                      </b>
                                      <small>
                                        {formatDate(invoice.rechnungsdatum)}
                                      </small>
                                    </span>
                                    <a
                                      href={`/api/customer-invoices/pdf?path=${encodeURIComponent(invoice.dateipfad || "")}`}
                                      target="_blank"
                                      rel="noopener noreferrer"
                                    >
                                      PDF öffnen
                                    </a>
                                  </div>
                                ))
                              )}
                            </div>
                          </details>
                        );
                      })}
                    </div>
                  )}
                  <div className="invoice-modal-actions">
                    <button
                      type="button"
                      onClick={() => setInvoiceCustomer(null)}
                    >
                      × Schließen
                    </button>
                  </div>
                </div>
              </div>
            )}
            {editingCustomer && (
              <div className="customer-modal-backdrop" role="presentation">
                <form
                  className="customer-modal"
                  onSubmit={(event) => {
                    event.preventDefault();
                    void saveCustomer();
                  }}
                >
                  <div>
                    <p className="home-kicker">
                      {creatingCustomer ? "KUNDEN ANLEGEN" : "KUNDENDATEN ÄNDERN"}
                    </p>
                    <h3>
                      {creatingCustomer
                        ? "Neuen Kunden anlegen"
                        : editingCustomer.firma ||
                        [editingCustomer.anrede, editingCustomer.name]
                          .filter(Boolean)
                          .join(" ") ||
                        "Kunde"}
                    </h3>
                  </div>
                  {!creatingCustomer && <a
                    className="customer-digital-file"
                    href={`/api/customers/digitale-akte?customer=${encodeURIComponent(editingCustomer.firma || editingCustomer.name || "")}`}
                    target="_blank"
                    rel="noopener noreferrer"
                  >
                    Letzte digitale Akte öffnen
                  </a>}
                  <div className="customer-form-grid">
                    <label>
                      Kundennummer
                      <input
                        value={editingCustomer.kundennummer_bestand ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            kundennummer_bestand: event.target.value,
                          })
                        }
                        maxLength={80}
                      />
                    </label>
                    <label>
                      Firma
                      <input
                        value={editingCustomer.firma ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            firma: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      Ansprechpartner
                      <input
                        value={editingCustomer.name ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            name: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      Straße
                      <input
                        value={editingCustomer.strasse ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            strasse: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      PLZ
                      <input
                        value={editingCustomer.plz ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            plz: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      Ort
                      <input
                        value={editingCustomer.ort ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            ort: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      Telefon
                      <input
                        value={editingCustomer.telefon ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            telefon: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      Mobil
                      <input
                        value={editingCustomer.mobil ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            mobil: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label>
                      E-Mail
                      <input
                        type="email"
                        value={editingCustomer.email ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            email: event.target.value,
                          })
                        }
                      />
                    </label>
                    <label className="customer-note-field">
                      Interne Notiz
                      <textarea
                        value={editingCustomer.notiz ?? ""}
                        onChange={(event) =>
                          setEditingCustomer({
                            ...editingCustomer,
                            notiz: event.target.value,
                          })
                        }
                      />
                    </label>
                  </div>
                  {!creatingCustomer && (() => {
                    const tasks = internalTasks.filter(
                      (task) =>
                        String(task.kunden_id ?? "") ===
                        String(editingCustomer.id),
                    );
                    const visibleTasks = tasks.filter((task) =>
                      customerTaskFilter === "all" ||
                      customerTaskFilter === "open"
                        ? task.status !== "erledigt"
                        : task.status === "erledigt",
                    );
                    const openCount = tasks.filter(
                      (task) => task.status !== "erledigt",
                    ).length;
                    const doneCount = tasks.length - openCount;
                    return (
                      <section className="customer-task-overview">
                        <div className="customer-task-heading">
                          <div>
                            <p className="home-kicker">AUFGABEN</p>
                            <h4>Aufgaben zu diesem Kunden</h4>
                          </div>
                          <div className="customer-task-tabs">
                            <button
                              type="button"
                              className={
                                customerTaskFilter === "all" ? "active" : ""
                              }
                              onClick={() => setCustomerTaskFilter("all")}
                            >
                              Alle ({tasks.length})
                            </button>
                            <button
                              type="button"
                              className={
                                customerTaskFilter === "open" ? "active" : ""
                              }
                              onClick={() => setCustomerTaskFilter("open")}
                            >
                              Offen ({openCount})
                            </button>
                            <button
                              type="button"
                              className={
                                customerTaskFilter === "done" ? "active" : ""
                              }
                              onClick={() => setCustomerTaskFilter("done")}
                            >
                              Erledigt ({doneCount})
                            </button>
                          </div>
                        </div>
                        {visibleTasks.length ? (
                          <div className="customer-task-list">
                            {visibleTasks.map((task) => (
                              <article
                                key={task.id}
                                className={
                                  `${internalTaskRecipient(task)} ${task.status === "erledigt" ? "done" : "open"}`
                                }
                              >
                                <i>{task.status === "erledigt" ? "✓" : "○"}</i>
                                <div>
                                  <b>{task.aufgabe}</b>
                                  <small>
                                    {internalTaskRecipient(task) === "sascha"
                                      ? "Sascha"
                                      : "Svenja"}{" "}
                                    ·{" "}
                                    {task.status === "erledigt"
                                      ? `erledigt ${formatDateTime(task.erledigt_am)}`
                                      : `offen seit ${formatDateTime(task.erstellt_am)}`}
                                  </small>
                                </div>
                              </article>
                            ))}
                          </div>
                        ) : (
                          <p className="customer-task-empty">
                            {tasks.length
                              ? "Für diesen Filter liegen keine Aufgaben vor."
                              : "Keine diesem Kunden zugeordneten Aufgaben vorhanden."}
                          </p>
                        )}
                      </section>
                    );
                  })()}
                  <div className="customer-modal-actions">
                    {!creatingCustomer && isSascha && (
                      <button
                        className="customer-delete-button"
                        type="button"
                        onClick={() => setCustomerDeleteConfirming(true)}
                        disabled={customerSaving}
                      >
                        {customerSaving ? "Löscht …" : "Löschen"}
                      </button>
                    )}
                    <button
                      type="button"
                      onClick={() => { setEditingCustomer(null); setCreatingCustomer(false); }}
                      disabled={customerSaving}
                    >
                      Abbrechen
                    </button>
                    <button type="submit" disabled={customerSaving}>
                      {customerSaving ? "Speichert …" : creatingCustomer ? "Kunde anlegen" : "Änderungen speichern"}
                    </button>
                  </div>
                  {customerDeleteConfirming && (
                    <div
                      className="customer-delete-confirm"
                      role="alertdialog"
                      aria-modal="true"
                      aria-labelledby="customer-delete-title"
                    >
                      <p className="home-kicker">ACHTUNG</p>
                      <h4 id="customer-delete-title">Kundeneintrag löschen?</h4>
                      <p>
                        <b>
                          {editingCustomer.firma ||
                            [editingCustomer.anrede, editingCustomer.name]
                              .filter(Boolean)
                              .join(" ") ||
                            "Dieser Kunde"}
                        </b>{" "}
                        wird nur aus dem Kundenstamm entfernt.
                      </p>
                      <small>
                        Tickets, Angebote und Dateien bleiben unverändert.
                      </small>
                      <div>
                        <button
                          type="button"
                          onClick={() => setCustomerDeleteConfirming(false)}
                          disabled={customerSaving}
                        >
                          Abbrechen
                        </button>
                        <button
                          className="customer-delete-confirm-button"
                          type="button"
                          onClick={() => void deleteCustomer()}
                          disabled={customerSaving}
                        >
                          {customerSaving ? "Löscht …" : "Endgültig löschen"}
                        </button>
                      </div>
                    </div>
                  )}
                </form>
              </div>
            )}
          </section>
        ) : view === "customer-invoices" ? (
          <section className="invoices-overview-page">
            <div className="offers-heading">
              <div>
                <p className="home-kicker">EK-DOS · RECHNUNGEN</p>
                <h2>Rechnungen</h2>
                <p>
                  Alle importierten Rechnungen mit direktem Zugriff auf die
                  jeweilige PDF-Datei.
                </p>
              </div>
              <button
                onClick={() => void refreshInvoiceOverview()}
                disabled={invoiceOverviewLoading}
              >
                {invoiceOverviewLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
              </button>
            </div>
            <div className="invoice-overview-tabs" role="tablist">
              <button
                className={invoiceOverviewTab === "all" ? "active" : ""}
                onClick={() => setInvoiceOverviewTab("all")}
              >
                Alle Rechnungen
              </button>
              <button
                className={invoiceOverviewTab === "unassigned" ? "active" : ""}
                onClick={() => setInvoiceOverviewTab("unassigned")}
              >
                Nicht zugeordnet
              </button>
            </div>
            {invoiceOverviewError && (
              <div className="tickets-error">{invoiceOverviewError}</div>
            )}
            {invoiceOverviewLoading && invoiceOverview.length === 0 ? (
              <div className="tickets-empty">
                <b>Rechnungen werden geladen …</b>
              </div>
            ) : (
              (() => {
                const visible =
                  invoiceOverviewTab === "unassigned"
                    ? unassignedInvoices
                    : invoiceOverview;
                return visible.length === 0 ? (
                  <div className="tickets-empty">
                    <b>
                      {invoiceOverviewTab === "unassigned"
                        ? "Alle Rechnungen sind Kunden zugeordnet."
                        : "Keine Rechnungen vorhanden."}
                    </b>
                  </div>
                ) : (
                  <div className="invoice-overview-list">
                    {visible.map((invoice) => {
                      const assignmentId = String(invoice.id ?? "");
                      const assignmentSearch = invoiceAssignmentSearch[assignmentId] ?? "";
                      const selectedCustomer = customerTaskOptions.find(
                        (option) => option.label === assignmentSearch,
                      )?.customer;
                      return <article
                        className="invoice-overview-item"
                        key={`${invoice.id ?? ""}-${invoice.dateiname ?? invoice.rechnungsnummer ?? ""}`}
                      >
                        <div>
                          <small>RECHNUNG</small>
                          <b>
                            {invoice.rechnungsnummer ||
                              invoice.dateiname ||
                              "–"}
                          </b>
                        </div>
                        <div>
                          <small>KUNDE</small>
                          <b>{invoice.kunde || "–"}</b>
                        </div>
                        <div>
                          <small>LIEGENSCHAFT</small>
                          <span>{invoice.liegenschaft || "–"}</span>
                        </div>
                        <div>
                          <small>DATUM</small>
                          <span>{formatDate(invoice.rechnungsdatum)}</span>
                        </div>
                        <a
                          href={`/api/customer-invoices/pdf?path=${encodeURIComponent(invoice.dateipfad || "")}`}
                          target="_blank"
                          rel="noopener noreferrer"
                        >
                          Rechnung öffnen
                        </a>
                        {invoiceOverviewTab === "unassigned" && <div className="invoice-assignment"><label>Kunde zuordnen<input list={`invoice-customers-${assignmentId}`} value={assignmentSearch} onChange={event => setInvoiceAssignmentSearch(current => ({ ...current, [assignmentId]: event.target.value }))} placeholder="Nachname oder Firma suchen …" autoComplete="off" /><datalist id={`invoice-customers-${assignmentId}`}>{customerTaskOptions.map(option => <option key={option.customer.id} value={option.label} />)}</datalist></label><button type="button" disabled={!selectedCustomer || invoiceAssignmentBusy === assignmentId} onClick={() => selectedCustomer && void assignInvoiceToCustomer(invoice, selectedCustomer)}>{invoiceAssignmentBusy === assignmentId ? "Ordnet zu …" : "Zuordnen"}</button></div>}
                      </article>;
                    })}
                  </div>
                );
              })()
            )}
          </section>
        ) : view === "tickets" ? (
          <section className="tickets-page">
            <div className="tickets-heading">
              <div>
                <p className="home-kicker">EK-DOS · LIVE-ÜBERSICHT</p>
                <h2>Offene Tickets</h2>
                <p>
                  Alle noch offenen Vorgänge aus n8n. Die Ansicht aktualisiert
                  sich automatisch alle 20 Sekunden.
                </p>
              </div>
              <div className="tickets-actions">
                <span>
                  {ticketsRefreshedAt
                    ? `Stand: ${formatDateTime(ticketsRefreshedAt)}`
                    : "Noch nicht aktualisiert"}
                </span>
                <button
                  onClick={() => void refreshTickets()}
                  disabled={ticketsLoading}
                >
                  {ticketsLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
                </button>
              </div>
            </div>
            {ticketsError && (
              <div className="tickets-error">{ticketsError}</div>
            )}
            {!ticketsLoading && !ticketsError && tickets.length === 0 && (
              <div className="tickets-empty">
                <b>Noch keine offenen Tickets übertragen.</b>
                <p>
                  Sobald der Workflow „Datenübergabe an EK-DOS-WEB“ Ticketdaten
                  an diese Anwendung sendet, erscheinen sie hier automatisch.
                </p>
              </div>
            )}
            {tickets.length > 0 && (
              <div className="tickets-table-wrap">
                <table className="tickets-table">
                  <thead>
                    <tr>
                      <th>Ticket</th>
                      <th>Kunde / Liegenschaft</th>
                      <th>Fortsetzung</th>
                      <th>Letzter Servicebericht</th>
                      <th>Ticketstatus</th>
                      <th>Aktualisiert</th>
                    </tr>
                  </thead>
                  <tbody>
                    {tickets.map((ticket, index) => {
                      const tone =
                        index % 2 === 0
                          ? "ticket-tone-blue"
                          : "ticket-tone-green";
                      return (
                        <Fragment key={ticket.id}>
                          <tr className={`ticket-row ${tone}`}>
                            <td>
                              <b>{ticket.id}</b>
                            </td>
                            <td>
                              <strong>{ticket.customer}</strong>
                              <small>{ticket.property}</small>
                            </td>
                            <td className="ticket-continuation">
                              {ticket.continuation ?? "–"}
                            </td>
                            <td>
                              <div className="ticket-report-actions">
                                <a
                                  className="ticket-report-file"
                                  href={`/api/tickets/digitale-akte?ticket=${encodeURIComponent(ticket.id)}`}
                                  target="_blank"
                                  rel="noopener noreferrer"
                                >
                                  Digitale Akte
                                </a>
                                <a
                                  className="ticket-report-file"
                                  href={`/api/tickets/servicebericht?ticket=${encodeURIComponent(ticket.id)}`}
                                  target="_blank"
                                  rel="noopener noreferrer"
                                >
                                  Letzter Servicebericht
                                </a>
                                <span
                                  className={`ticket-status ${reportStatusClass(ticket.reportStatus)}`}
                                >
                                  {ticket.reportStatus ?? "–"}
                                </span>
                              </div>
                            </td>
                            <td>
                              <span className="ticket-status">
                                {ticket.status}
                              </span>
                            </td>
                            <td>{formatDateTime(ticket.updatedAt)}</td>
                          </tr>
                          {needsCustomerConsultation(ticket) && (
                            <tr className="ticket-consultation-row">
                              <td colSpan={6}>
                                <div className={`ticket-consultation ${tone}`}>
                                  <div>
                                    <p>
                                      TICKET {ticket.id} · KUNDENRÜCKSPRACHE
                                    </p>
                                    <b>Halte Rücksprache mit Kunden</b>
                                  </div>
                                  <div className="ticket-consultation-result">
                                    <span>Ergebnis der Rücksprache</span>
                                    {ticket.consultationResult ? (
                                      <>
                                        <strong>
                                          {ticket.consultationResult}
                                        </strong>
                                        <small>
                                          {ticket.consultationBy ?? "Svenja"} ·{" "}
                                          {formatDateTime(
                                            ticket.consultationUpdatedAt,
                                          )}
                                        </small>
                                      </>
                                    ) : (
                                      <em>Noch kein Ergebnis hinterlegt.</em>
                                    )}
                                  </div>
                                  {isSvenja && !ticket.consultationResult && (
                                    <div className="ticket-consultation-edit">
                                      <label
                                        htmlFor={`consultation-${ticket.id}`}
                                      >
                                        Ergebnis eintragen
                                      </label>
                                      <textarea
                                        id={`consultation-${ticket.id}`}
                                        value={
                                          consultationDrafts[ticket.id] ?? ""
                                        }
                                        onChange={(event) =>
                                          setConsultationDrafts((drafts) => ({
                                            ...drafts,
                                            [ticket.id]: event.target.value,
                                          }))
                                        }
                                        placeholder="Ergebnis der Rücksprache mit dem Kunden …"
                                        maxLength={4000}
                                      />
                                      <button
                                        onClick={() =>
                                          void saveCustomerConsultation(ticket)
                                        }
                                        disabled={
                                          consultationSaving === ticket.id
                                        }
                                      >
                                        {consultationSaving === ticket.id
                                          ? "Speichert …"
                                          : "Ergebnis speichern"}
                                      </button>
                                      {consultationError[ticket.id] && (
                                        <small className="ticket-consultation-error">
                                          {consultationError[ticket.id]}
                                        </small>
                                      )}
                                    </div>
                                  )}
                                </div>
                              </td>
                            </tr>
                          )}
                        </Fragment>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </section>
        ) : view === "time-records" ? (
          <section className="hours-page">
            <div className="hours-heading">
              <div>
                <p className="home-kicker">EK-DOS · MITARBEITER</p>
                <h2>Stundennachweise</h2>
                <p>
                  Aktuelle Monatsstunden. Die Daten werden beim Öffnen dieser
                  Seite aus n8n geladen.
                </p>
              </div>
              <span>
                {hoursOverview
                  ? `Stand: ${formatDateTime(hoursOverview.generatedAt)}`
                  : "Lädt …"}
              </span>
            </div>
            {hoursError && <div className="hours-error">{hoursError}</div>}
            {hoursLoading && !hoursOverview && (
              <div className="hours-empty">
                <b>Stundennachweise werden geladen …</b>
              </div>
            )}
            {hoursOverview && !hoursError && (
              <>
                <div className="hours-employee-list">
                  {hoursOverview.employees.map((employee) => (
                    <details className="hours-employee" key={employee.name}>
                      <summary>
                        <span>
                          <b>{employee.name}</b>
                          <small>
                            {employee.entries.length} Buchungen ·{" "}
                            {hoursOverview.month} {hoursOverview.year}
                          </small>
                          <div className="hours-absence-summary">
                            <span>
                              <em className="sick">
                                {employee.statusDays?.sick ??
                                  employee.entries.filter(
                                    (entry) =>
                                      hoursStatusClass(entry.status) === "sick",
                                  ).length}{" "}
                                Krank
                              </em>
                              <em className="vacation">
                                {employee.statusDays?.vacation ??
                                  employee.entries.filter(
                                    (entry) =>
                                      hoursStatusClass(entry.status) ===
                                      "vacation",
                                  ).length}{" "}
                                Urlaub
                              </em>
                            </span>
                            {!["Sascha Krüger", "Svenja Vietsch"].includes(
                              employee.name,
                            ) && (
                              <em className="school">
                                {employee.statusDays?.school ??
                                  employee.entries.filter(
                                    (entry) =>
                                      hoursStatusClass(entry.status) ===
                                      "school",
                                  ).length}{" "}
                                Berufsschule
                              </em>
                            )}
                          </div>
                        </span>
                        <div className="hours-summary-total">
                          <small>
                            {
                              new Set(
                                employee.entries
                                  .filter(
                                    (entry) =>
                                      hoursStatusClass(entry.status) === "work",
                                  )
                                  .map((entry) => entry.date),
                              ).size
                            }{" "}
                            Produktive Tage Monat ·{" "}
                            {employee.workDaysYear ?? "–"} Produktive Tage Jahr
                          </small>
                          <strong>
                            {employee.totalHours.toLocaleString("de-DE", {
                              maximumFractionDigits: 2,
                            })}{" "}
                            Std.
                          </strong>
                        </div>
                        <i>⌄</i>
                      </summary>
                      <div className="hours-table-wrap">
                        <table className="hours-table">
                          <thead>
                            <tr>
                              <th>Datum</th>
                              <th>Status</th>
                              <th>Stunden</th>
                              <th>Servicebericht / Einsatz</th>
                            </tr>
                          </thead>
                          <tbody>
                            {employee.entries.map((entry, index) => {
                              const statusClass = hoursStatusClass(
                                entry.status,
                              );
                              return (
                                <tr
                                  key={`${employee.name}-${entry.date}-${index}`}
                                >
                                  <td className={`hours-date ${statusClass}`}>
                                    {entry.label}
                                  </td>
                                  <td>
                                    <span
                                      className={`hours-status ${statusClass}`}
                                    >
                                      {entry.status}
                                    </span>
                                  </td>
                                  <td>
                                    {Number(entry.hours).toLocaleString(
                                      "de-DE",
                                      { maximumFractionDigits: 2 },
                                    )}
                                  </td>
                                  <td>
                                    {entry.report ? (
                                      <>
                                        <b>{entry.report}</b>
                                        <small>
                                          {[entry.customer, entry.property]
                                            .filter(Boolean)
                                            .join(" · ")}
                                        </small>
                                      </>
                                    ) : (
                                      "–"
                                    )}
                                  </td>
                                </tr>
                              );
                            })}
                          </tbody>
                        </table>
                      </div>
                    </details>
                  ))}
                </div>
                <p className="hours-note">
                  Berechnungsreihenfolge:{" "}
                  {hoursOverview.statusPriority ?? "wie Workflow 11"}.
                </p>
              </>
            )}
            {hoursOverview && !hoursError && (
              <p className="hours-manual-warning">
                Manuell erstellte Stunden werden nicht anerkannt, um Missbrauch
                entgegen zu wirken.
              </p>
            )}
          </section>
        ) : view === "invoices-send" ? (
          <section className="tickets-page">
            <div className="tickets-heading">
              <div>
                <p className="home-kicker">SVENJA · RECHNUNGEN</p>
                <h2>Rechnungen zum Versenden</h2>
                <p>
                  Von Sascha geprüfte Rechnungen. Den Versandweg bestätigst du
                  anschließend über Helgas Teams-Karte.
                </p>
              </div>
              <div className="tickets-actions">
                <span>
                  {invoiceSendRefreshedAt
                    ? `Stand: ${formatDateTime(invoiceSendRefreshedAt)}`
                    : "Noch nicht aktualisiert"}
                </span>
                <button
                  onClick={() => void refreshInvoiceSendTasks()}
                  disabled={invoiceSendLoading}
                >
                  {invoiceSendLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
                </button>
              </div>
            </div>
            {invoiceSendError && (
              <div className="tickets-error">{invoiceSendError}</div>
            )}
            {invoiceSendLoading && invoiceSendTasks.length === 0 && (
              <div className="tickets-empty">
                <b>Versandaufgaben werden geladen …</b>
              </div>
            )}
            {!invoiceSendLoading &&
              !invoiceSendError &&
              invoiceSendTasks.length === 0 && (
                <div className="tickets-empty">
                  <b>Keine Rechnungen zum Versenden.</b>
                  <p>
                    Sobald Sascha eine Rechnungsprüfung abschließt, erscheint
                    die Versandaufgabe hier.
                  </p>
                </div>
              )}
            {invoiceSendTasks.length > 0 && (
              <div className="tickets-table-wrap">
                <table className="tickets-table">
                  <thead>
                    <tr>
                      <th>Ticketnummer</th>
                      <th>Kunde / Liegenschaft</th>
                      <th>Rechnungsnummer</th>
                      <th>Freigegeben</th>
                      <th>Status</th>
                    </tr>
                  </thead>
                  <tbody>
                    {invoiceSendTasks.map((task) => (
                      <tr key={String(task.id)}>
                        <td>
                          <b>{task.ticketnummer || "–"}</b>
                        </td>
                        <td>
                          <strong>{task.kunde || "–"}</strong>
                          <small>{task.liegenschaft || "–"}</small>
                        </td>
                        <td>
                          <b>{task.rechnungsnummer || "–"}</b>
                        </td>
                        <td>{formatDateTime(task.created_at)}</td>
                        <td>
                          <span className="ticket-status">
                            Zum Versand bereit
                          </span>
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
            )}
          </section>
        ) : view === "invoices-create" || view === "invoices-created" ? (
          <section className="tickets-page">
            {view === "invoices-create" ? (
              <>
                <div className="tickets-heading">
                  <div>
                    <p className="home-kicker">SVENJA · RECHNUNGEN</p>
                    <h2>Rechnungen anfertigen</h2>
                    <p>
                      Rechnungsaufgaben aus Svenjas Microsoft To Do. Mit
                      „Erledigt“ wird die Aufgabe für Saschas Prüfung
                      weitergegeben.
                    </p>
                  </div>
                  <div className="tickets-actions">
                    <span>
                      {invoiceCreateRefreshedAt
                        ? `Stand: ${formatDateTime(invoiceCreateRefreshedAt)}`
                        : "Noch nicht aktualisiert"}
                    </span>
                    <button
                      onClick={() => void refreshInvoiceCreateTasks()}
                      disabled={invoiceCreateLoading}
                    >
                      {invoiceCreateLoading
                        ? "Aktualisiert …"
                        : "↻ Aktualisieren"}
                    </button>
                  </div>
                </div>
                {invoiceCreateError && (
                  <div className="tickets-error">{invoiceCreateError}</div>
                )}
                {invoiceCreateLoading &&
                  openInvoiceCreateTasks.length === 0 && (
                    <div className="tickets-empty">
                      <b>Rechnungsaufgaben werden geladen …</b>
                    </div>
                  )}
                {!invoiceCreateLoading &&
                  !invoiceCreateError &&
                  openInvoiceCreateTasks.length === 0 && (
                    <div className="tickets-empty">
                      <b>Keine Rechnungsaufgaben offen.</b>
                      <p>
                        Bereits erledigte Aufgaben stehen unter „Erstellte
                        Rechnungen“.
                      </p>
                    </div>
                  )}
                {openInvoiceCreateTasks.length > 0 && (
                  <div className="tickets-table-wrap">
                    <table className="tickets-table">
                      <thead>
                        <tr>
                          <th>Rechnung / Aufgabe</th>
                          <th>Ticketnummer</th>
                          <th>Erstellt</th>
                          <th>Status</th>
                        </tr>
                      </thead>
                      <tbody>
                        {openInvoiceCreateTasks.map((task) => (
                          <tr key={task.id}>
                            <td>
                              <b>{task.title}</b>
                            </td>
                            <td>
                              <b>{invoiceTicketNumber(task)}</b>
                            </td>
                            <td>{formatDateTime(task.createdAt)}</td>
                            <td>
                              <div className="invoice-create-actions">
                                <a
                                  className="invoice-create-file"
                                  href={`/api/invoices-create/digitale-akte?taskId=${encodeURIComponent(task.id)}`}
                                  target="_blank"
                                  rel="noopener noreferrer"
                                >
                                  Digitale Akte
                                </a>
                                <button
                                  className="invoice-create-complete"
                                  onClick={() =>
                                    void completeInvoiceCreateTask(task)
                                  }
                                  disabled={invoiceCreateCompleting === task.id}
                                >
                                  {invoiceCreateCompleting === task.id
                                    ? "Schließt …"
                                    : "✓ Erledigt"}
                                </button>
                              </div>
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </>
            ) : (
              <>
                <div className="tickets-heading">
                  <div>
                    <p className="home-kicker">SVENJA · RECHNUNGEN</p>
                    <h2>Erstellte Rechnungen</h2>
                    <p>
                      Abgeschlossene Rechnungsaufgaben aus Svenjas Microsoft To
                      Do. Sie bleiben hier dauerhaft sichtbar.
                    </p>
                  </div>
                  <div className="tickets-actions">
                    <span>
                      {invoiceCreateRefreshedAt
                        ? `Stand: ${formatDateTime(invoiceCreateRefreshedAt)}`
                        : "Noch nicht aktualisiert"}
                    </span>
                    <button
                      onClick={() => void refreshInvoiceCreateTasks()}
                      disabled={invoiceCreateLoading}
                    >
                      {invoiceCreateLoading
                        ? "Aktualisiert …"
                        : "↻ Aktualisieren"}
                    </button>
                  </div>
                </div>
                {invoiceCreateError && (
                  <div className="tickets-error">{invoiceCreateError}</div>
                )}
                {invoiceCreateLoading &&
                  completedInvoiceCreateTasks.length === 0 && (
                    <div className="tickets-empty">
                      <b>Erstellte Rechnungen werden geladen …</b>
                    </div>
                  )}
                {!invoiceCreateLoading &&
                  !invoiceCreateError &&
                  completedInvoiceCreateTasks.length === 0 && (
                    <div className="tickets-empty">
                      <b>Noch keine Rechnung erstellt.</b>
                    </div>
                  )}
                {completedInvoiceCreateTasks.length > 0 && (
                  <div className="tickets-table-wrap">
                    <table className="tickets-table">
                      <thead>
                        <tr>
                          <th>Rechnung / Aufgabe</th>
                          <th>Ticketnummer</th>
                          <th>Erstellt</th>
                          <th>Abgeschlossen</th>
                        </tr>
                      </thead>
                      <tbody>
                        {completedInvoiceCreateTasks.map((task) => (
                          <tr
                            key={task.id}
                            className="invoice-review-row-completed"
                          >
                            <td>
                              <b>{task.title}</b>
                            </td>
                            <td>
                              <b>{invoiceTicketNumber(task)}</b>
                            </td>
                            <td>{formatDateTime(task.createdAt)}</td>
                            <td>
                              <span className="ticket-status invoice-review-status-completed">
                                Erledigt
                              </span>
                              {task.completedAt && (
                                <small className="invoice-review-completed-at">
                                  {formatDateTime(task.completedAt)}
                                </small>
                              )}
                            </td>
                          </tr>
                        ))}
                      </tbody>
                    </table>
                  </div>
                )}
              </>
            )}
          </section>
        ) : view === "invoices-review-sascha" ||
          view === "invoice-review-svenja" ? (
          <section className="tickets-page">
            <div className="tickets-heading">
              <div>
                <p className="home-kicker">
                  {isSvenja ? "SVENJA · RECHNUNGEN" : "SASCHA · RECHNUNGEN"}
                </p>
                <h2>
                  {isSvenja ? "Rechnungen in Prüfung" : "Rechnungen prüfen"}
                </h2>
                <p>
                  Offene Rechnungen aus Saschas Prüfliste. Nach Saschas Prüfung
                  verschwinden sie automatisch aus dieser Ansicht.
                </p>
              </div>
              <div className="tickets-actions">
                <span>
                  {invoiceReviewsRefreshedAt
                    ? `Stand: ${formatDateTime(invoiceReviewsRefreshedAt)}`
                    : "Noch nicht aktualisiert"}
                </span>
                <button
                  onClick={() => void refreshInvoiceReviews()}
                  disabled={invoiceReviewsLoading}
                >
                  {invoiceReviewsLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
                </button>
              </div>
            </div>
            {invoiceReviewsError && (
              <div className="tickets-error">{invoiceReviewsError}</div>
            )}
            {!invoiceReviewsLoading &&
              !invoiceReviewsError &&
              visibleInvoiceReviews.length === 0 && (
                <div className="tickets-empty">
                  <b>
                    {isSvenja
                      ? "Keine Rechnungen in Prüfung."
                      : "Keine Rechnungen in der Prüfliste."}
                  </b>
                  <p>
                    Sobald eine Rechnung in Saschas To-Do-Liste „Rechnungen
                    prüfen“ liegt, erscheint sie hier.
                  </p>
                </div>
              )}
            {visibleInvoiceReviews.length > 0 && (
              <div className="tickets-table-wrap">
                <table className="tickets-table invoice-review-table">
                  <thead>
                    <tr>
                      <th>Kunde</th>
                      <th>Liegenschaft</th>
                      <th>Ticket-Nr.</th>
                      <th>Datum</th>
                    </tr>
                  </thead>
                  <tbody>
                    {visibleInvoiceReviews.map((invoice) => {
                      const fields = invoiceReviewFields(invoice);
                      return (
                        <tr key={invoice.id}>
                          <td>
                            <b>{fields.kunde}</b>
                          </td>
                          <td>{fields.liegenschaft}</td>
                          <td>
                            <b>{fields.ticket}</b>
                          </td>
                          <td>
                            <div className="invoice-review-date">
                              <span>{formatDate(invoice.createdAt)}</span>
                              {isSascha && (
                                <button
                                  className="invoice-review-complete"
                                  onClick={() =>
                                    void completeInvoiceReview(invoice)
                                  }
                                  disabled={
                                    invoiceReviewCompleting === invoice.id
                                  }
                                >
                                  {invoiceReviewCompleting === invoice.id
                                    ? "Schließt …"
                                    : "✓ Erledigt"}
                                </button>
                              )}
                            </div>
                          </td>
                        </tr>
                      );
                    })}
                  </tbody>
                </table>
              </div>
            )}
          </section>
        ) : view === "internal-tasks" ? (
          <section className="online-purchases-page">
            <div className="online-purchases-heading">
              <div>
                <p className="home-kicker">EK-DOS · AUFGABEN</p>
                <h2>
                  {internalTaskFilter
                    ? activeInternalTaskCategories.find(
                        ([key]) => key === internalTaskFilter,
                      )?.[1]
                    : activeInternalTaskRecipient === "sascha"
                      ? "Saschas Aufgaben"
                      : "Interne Aufgaben"}
                </h2>
                <p>
                  {activeInternalTaskRecipient === "sascha"
                    ? "Aufgaben für Sascha – nach Themen geordnet."
                    : "Deine Aufgaben für Svenja – klar nach Themen geordnet."}
                </p>
              </div>
              <button onClick={() => void refreshInternalTasks()}>
                ↻ Aktualisieren
              </button>
            </div>
            {internalTaskError && (
              <div className="tickets-error">{internalTaskError}</div>
            )}
            <div className="internal-task-columns internal-task-single-column">
              {([activeInternalTaskRecipient] as const).map((empfaenger) => {
                const title =
                  empfaenger === "sascha"
                    ? "Aufgaben für Sascha"
                    : "Aufgaben für Svenja";
                const draft = internalTaskDrafts[empfaenger] ?? {
                  aufgabe: "",
                  kategorie: "angebote",
                  kunden_id: "",
                };
                return (
                  <div className="internal-task-column" key={empfaenger}>
                    <h3>{title}</h3>
                    <form
                      className="internal-task-form"
                      onSubmit={(event) =>
                        void saveInternalTask(event, empfaenger)
                      }
                    >
                      <label>
                        Neue Aufgabe
                        <input
                          value={draft.aufgabe}
                          onChange={(event) =>
                            setInternalTaskDrafts((value) => ({
                              ...value,
                              [empfaenger]: {
                                ...draft,
                                aufgabe: event.target.value,
                              },
                            }))
                          }
                          placeholder="Aufgabe eintragen …"
                          maxLength={500}
                          required
                        />
                      </label>
                      <label>
                        Kategorie
                        <select
                          value={draft.kategorie}
                          onChange={(event) =>
                            setInternalTaskDrafts((value) => ({
                              ...value,
                              [empfaenger]: {
                                ...draft,
                                kategorie: event.target.value,
                              },
                            }))
                          }
                        >
                          {internalTaskCategories.map(([key, label]) => (
                            <option value={key} key={key}>
                              {label}
                            </option>
                          ))}
                        </select>
                      </label>
                      <label>
                        Kunde
                        <div className="internal-task-customer-search">
                          <input
                            list={`task-customers-${empfaenger}`}
                            value={
                              internalTaskCustomerSearch[empfaenger] ??
                              (draft.kunden_id
                                ? customerTaskOptions.find(
                                    (option) =>
                                      option.customer.id === draft.kunden_id,
                                  )?.label ?? ""
                                : "")
                            }
                            onChange={(event) => {
                              const value = event.target.value;
                              const match = customerTaskOptions.find(
                                (option) => option.label === value,
                              );
                              setInternalTaskCustomerSearch((current) => ({
                                ...current,
                                [empfaenger]: value,
                              }));
                              setInternalTaskDrafts((current) => ({
                                ...current,
                                [empfaenger]: {
                                  ...draft,
                                  kunden_id: String(match?.customer.id ?? ""),
                                },
                              }));
                            }}
                            placeholder="Kunde suchen …"
                            autoComplete="off"
                          />
                          <datalist id={`task-customers-${empfaenger}`}>
                            {customerTaskOptions.map((option) => (
                              <option
                                key={option.customer.id}
                                value={option.label}
                              />
                            ))}
                          </datalist>
                          {draft.kunden_id ? <small>Kunde zugeordnet</small> : null}
                        </div>
                      </label>
                      <button
                        type="submit"
                        disabled={internalTaskBusy === `new-${empfaenger}`}
                      >
                        {internalTaskBusy === `new-${empfaenger}`
                          ? "Speichert …"
                          : "Aufgabe anlegen"}
                      </button>
                    </form>
                    {activeInternalTaskCategories
                      .filter(
                        ([category]) =>
                          !internalTaskFilter ||
                          category === internalTaskFilter,
                      )
                      .map(([category, label]) => {
                        const tasks = internalTasks.filter(
                          (task) =>
                            internalTaskRecipient(task) === empfaenger &&
                            (category === "interne_bueroaufgaben"
                              ? [
                                  "interne_bueroaufgaben",
                                  "kundenruecksprache",
                                ].includes(internalTaskCategory(task))
                              : internalTaskCategory(task) === category),
                        );
                        const open = tasks.filter(
                          (task) => task.status !== "erledigt",
                        );
                        const done = tasks.filter(
                          (task) => task.status === "erledigt",
                        );
                        const renderTask = (task: InternalTask) => (
                          <article className="internal-task-item" key={task.id}>
                            <span
                              className={`internal-task-check ${task.status === "erledigt" ? "done" : ""}`}
                              aria-label={task.status === "erledigt" ? "Erledigt" : "Offen"}
                            >
                              ✓
                            </span>
                            <div className="internal-task-details">
                              <b>{task.aufgabe}</b>
                              <small>
                                Erstellt von {task.erstellt_von ?? "–"} ·{" "}
                                {task.erstellt_am
                                  ? formatDateTime(task.erstellt_am)
                                  : "–"}
                              </small>
                              {task.status === "erledigt" && (
                                <small>
                                  Erledigt von {task.erledigt_von ?? "–"}
                                </small>
                              )}
                            </div>
                            <div className="internal-task-customer-column">
                              {internalTaskCustomerName(task) && (
                                <>
                                  <small>KUNDE</small>
                                  <b>{internalTaskCustomerName(task)}</b>
                                </>
                              )}
                            </div>
                            <div className="online-purchase-status">
                        <button
                          className="internal-task-edit"
                          onClick={() => {
                            setEditingInternalTaskCustomerSearch(
                              customerTaskOptions.find(
                                (option) =>
                                  String(option.customer.id) ===
                                  String(task.kunden_id ?? ""),
                              )?.label ?? "",
                            );
                            setEditingInternalTaskCustomerId(
                              String(task.kunden_id ?? ""),
                            );
                            setEditingInternalTask(task);
                          }}
                                disabled={internalTaskBusy === task.id}
                              >
                                Bearbeiten
                              </button>
                              {task.status === "erledigt" ? (
                                <strong>Erledigt</strong>
                              ) : (
                                <button
                                  onClick={() =>
                                    void changeInternalTask(task, "PUT")
                                  }
                                  disabled={internalTaskBusy === task.id}
                                >
                                  ✓ Erledigt
                                </button>
                              )}
                              {isSascha && (
                                <button
                                  className="online-purchase-delete"
                                  onClick={() =>
                                    void changeInternalTask(task, "DELETE")
                                  }
                                  disabled={internalTaskBusy === task.id}
                                >
                                  Löschen
                                </button>
                              )}
                            </div>
                          </article>
                        );
                        return (
                          <section
                            className="internal-task-category"
                            key={category}
                          >
                            <h4>
                              <span
                                className={`internal-task-dot ${category}`}
                              ></span>
                              {label}
                              <b>{open.length}</b>
                            </h4>
                            {open.length ? (
                              open.map(renderTask)
                            ) : (
                              <p>Keine offenen Aufgaben.</p>
                            )}
                            {done.length > 0 && (
                              <details>
                                <summary>Erledigt ({done.length})</summary>
                                {done.map(renderTask)}
                              </details>
                            )}
                          </section>
                        );
                      })}
                  </div>
                );
              })}
            </div>
            {editingInternalTask && (
              <div
                className="internal-task-edit-backdrop"
                role="dialog"
                aria-modal="true"
              >
                <form
                  className="internal-task-edit-modal"
                  onSubmit={(event) => void updateInternalTask(event)}
                >
                  <p>AUFGABE BEARBEITEN</p>
                  <h3>Interne Aufgabe</h3>
                  <label>
                    Aufgabe
                    <input
                      name="aufgabe"
                      defaultValue={editingInternalTask.aufgabe}
                      maxLength={500}
                      required
                      autoFocus
                    />
                  </label>
                  <label>
                    Empfänger
                    <select
                      name="empfaenger"
                      defaultValue={internalTaskRecipient(editingInternalTask)}
                    >
                      <option value="sascha">Sascha</option>
                      <option value="svenja">Svenja</option>
                    </select>
                  </label>
                  <label>
                    Kategorie
                    <select
                      name="kategorie"
                      defaultValue={internalTaskCategory(editingInternalTask)}
                    >
                      {internalTaskCategories.map(([key, label]) => (
                        <option value={key} key={key}>
                          {label}
                        </option>
                      ))}
                    </select>
                  </label>
                  <label>
                    Kunde
                    <div className="internal-task-customer-search">
                      <input
                        name="kunden_suche"
                        list="task-customers-edit"
                        value={editingInternalTaskCustomerSearch}
                        onChange={(event) => {
                          const value = event.target.value;
                          const match = customerTaskOptions.find(
                            (option) => option.label === value,
                          );
                          setEditingInternalTaskCustomerSearch(value);
                          setEditingInternalTaskCustomerId(
                            String(match?.customer.id ?? ""),
                          );
                        }}
                        placeholder="Kunde suchen …"
                        autoComplete="off"
                      />
                      <input
                        type="hidden"
                        name="kunden_id"
                        value={editingInternalTaskCustomerId}
                      />
                      <datalist id="task-customers-edit">
                        {customerTaskOptions.map((option) => (
                          <option
                            key={option.customer.id}
                            value={option.label}
                          />
                        ))}
                      </datalist>
                      {editingInternalTaskCustomerId ? (
                        <small>Kunde zugeordnet</small>
                      ) : null}
                    </div>
                  </label>
                  <div>
                    <button
                      type="button"
                      onClick={() => setEditingInternalTask(null)}
                    >
                      Abbrechen
                    </button>
                    <button
                      type="submit"
                      disabled={internalTaskBusy === editingInternalTask.id}
                    >
                      {internalTaskBusy === editingInternalTask.id
                        ? "Speichert …"
                        : "Änderungen speichern"}
                    </button>
                  </div>
                </form>
              </div>
            )}
          </section>
        ) : view === "online-purchases-new" || view === "online-purchases" ? (
          <section className="online-purchases-page">
            <div className="online-purchases-heading">
              <div>
                <p className="home-kicker">
                  EK-DOS · {isSascha ? "EINKAUF" : "BELEGPRÜFUNG"}
                </p>
                <h2>{isSascha ? "Neue Online Käufe" : "Online Käufe"}</h2>
                <p>
                  {isSascha
                    ? "Trage neue Online-Käufe ein. Svenja erhält sie anschließend zur Belegablage."
                    : "Prüfe die aufgeführten Käufe. Nach der Belegablage schließt du den Kauf mit „Erledigt“ ab."}
                </p>
              </div>
              <button
                onClick={() => void refreshOnlinePurchases()}
                disabled={onlinePurchasesLoading}
              >
                {onlinePurchasesLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
              </button>
            </div>
            {isSascha && (
              <form
                className="online-purchase-form"
                onSubmit={saveOnlinePurchase}
              >
                <label>
                  Artikel
                  <input
                    value={onlinePurchaseForm.artikel}
                    onChange={(event) =>
                      setOnlinePurchaseForm((form) => ({
                        ...form,
                        artikel: event.target.value,
                      }))
                    }
                    placeholder="z. B. Sicherungsautomat"
                    maxLength={240}
                    required
                  />
                </label>
                <label>
                  Marktplatz
                  <input
                    value={onlinePurchaseForm.kaufort}
                    onChange={(event) =>
                      setOnlinePurchaseForm((form) => ({
                        ...form,
                        kaufort: event.target.value,
                      }))
                    }
                    placeholder="z. B. Online-Shop / Händler"
                    maxLength={240}
                    required
                  />
                </label>
                <label>
                  Kaufdatum
                  <input
                    type="date"
                    value={onlinePurchaseForm.kaufdatum}
                    onChange={(event) =>
                      setOnlinePurchaseForm((form) => ({
                        ...form,
                        kaufdatum: event.target.value,
                      }))
                    }
                    required
                  />
                </label>
                <button type="submit" disabled={onlinePurchaseSaving}>
                  {onlinePurchaseSaving ? "Speichert …" : "Kauf speichern"}
                </button>
              </form>
            )}
            {onlinePurchasesError && (
              <div className="tickets-error">{onlinePurchasesError}</div>
            )}
            {onlinePurchasesLoading && onlinePurchases.length === 0 && (
              <div className="tickets-empty">
                <b>Online-Käufe werden geladen …</b>
              </div>
            )}
            {!onlinePurchasesLoading &&
              !onlinePurchasesError &&
              onlinePurchases.length === 0 && (
                <div className="tickets-empty">
                  <b>Noch keine Online-Käufe eingetragen.</b>
                  <p>
                    {isSascha
                      ? "Neue Einkäufe können oben direkt erfasst werden."
                      : "Sobald Sascha einen Online-Kauf erfasst, erscheint er hier zur Belegablage."}
                  </p>
                </div>
              )}
            {onlinePurchases.length > 0 && (
              <div className="online-purchases-list">
                {onlinePurchases.map((purchase) => {
                  const done =
                    purchase.status?.toLocaleLowerCase("de-DE") === "erledigt";
                  return (
                    <article
                      className={`online-purchase-item ${done ? "is-done" : ""}`}
                      key={purchase.id}
                    >
                      <span
                        className="online-purchase-check"
                        aria-label={done ? "Erledigt" : "Offen"}
                      >
                        {done ? "✓" : "○"}
                      </span>
                      <div>
                        <small>ARTIKEL</small>
                        <b>{purchase.artikel}</b>
                      </div>
                      <div>
                        <small>MARKTPLATZ</small>
                        <span>{purchase.kaufort}</span>
                      </div>
                      <div>
                        <small>KAUFDATUM</small>
                        <span>{formatDate(purchase.kaufdatum)}</span>
                      </div>
                      <div className="online-purchase-status">
                        {done ? (
                          <>
                            <strong>Erledigt</strong>
                            <small>
                              {purchase.erledigt_von ?? "Svenja"}
                              {purchase.erledigt_am
                                ? ` · ${formatDateTime(purchase.erledigt_am)}`
                                : ""}
                            </small>
                          </>
                        ) : isSvenja ? (
                          <button
                            onClick={() =>
                              void completeOnlinePurchase(purchase)
                            }
                            disabled={onlinePurchaseCompleting === purchase.id}
                          >
                            {onlinePurchaseCompleting === purchase.id
                              ? "Schließt …"
                              : "✓ Erledigt"}
                          </button>
                        ) : (
                          <>
                            <strong>Offen für Svenja</strong>
                            <button
                              className="online-purchase-delete"
                              onClick={() =>
                                void deleteOnlinePurchase(purchase)
                              }
                              disabled={onlinePurchaseDeleting === purchase.id}
                            >
                              {onlinePurchaseDeleting === purchase.id
                                ? "Löscht …"
                                : "Löschen"}
                            </button>
                          </>
                        )}
                      </div>
                    </article>
                  );
                })}
              </div>
            )}
          </section>
        ) : view.startsWith("offers-") ? (
          <section className="offers-page">
            <div className="offers-heading">
              <div>
                <p className="home-kicker">EK-DOS · ANGEBOTE</p>
                <h2>
                  {view === "offers-commissioned"
                    ? "Beauftragte Angebote"
                    : view === "offers-open"
                      ? "Offene Angebote"
                      : view === "offers-expired"
                        ? "Abgelaufene Angebote"
                        : "Erstellte Angebote"}
                </h2>
                <p>
                  {view === "offers-commissioned"
                    ? "Beauftragte Angebote mit bestätigter Unterschrift."
                    : view === "offers-open"
                      ? "Versendete Angebote ohne Beauftragung und innerhalb ihrer Gültigkeit."
                      : view === "offers-expired"
                        ? "Nicht beauftragte Angebote, deren Gültigkeit abgelaufen ist."
                        : "Angebote aus dem Ordner Angebote. Der Versand wird hier dokumentiert."}
                </p>
              </div>
              <div className="offers-toolbar">
                <input
                  value={offerSearch}
                  onChange={(event) => setOfferSearch(event.target.value)}
                  placeholder="Angebot, Kunde oder Objekt suchen …"
                  aria-label="Angebote durchsuchen"
                />
                <button
                  onClick={() => void refreshOffers()}
                  disabled={offersLoading}
                >
                  {offersLoading ? "Aktualisiert …" : "↻ Aktualisieren"}
                </button>
              </div>
            </div>
            {offersError && <div className="tickets-error">{offersError}</div>}
            {offersLoading && offers.length === 0 && (
              <div className="tickets-empty">
                <b>Angebote werden geladen …</b>
              </div>
            )}
            {!offersLoading &&
              (() => {
                const search = offerSearch.trim().toLocaleLowerCase("de-DE");
                const visible = offers.filter((offer) => {
                  const expired = offerExpired(offer);
                  const categoryMatches =
                    view === "offers-commissioned"
                      ? offer.status === "beauftragt"
                      : view === "offers-open"
                        ? !!offer.versendet &&
                          offer.status !== "beauftragt" &&
                          !expired
                        : view === "offers-expired"
                          ? expired
                          : !offer.versendet &&
                            offer.status !== "beauftragt" &&
                            !expired;
                  const searchable = [
                    offer.angebot_nummer,
                    offer.dateiname,
                    offer.kunde,
                    offer.objekt_zusatz,
                  ]
                    .filter(Boolean)
                    .join(" ")
                    .toLocaleLowerCase("de-DE");
                  return (
                    categoryMatches && (!search || searchable.includes(search))
                  );
                });
                return visible.length === 0 ? (
                  <div className="tickets-empty">
                    <b>
                      {search
                        ? "Keine passenden Angebote gefunden."
                        : "Keine Angebote vorhanden."}
                    </b>
                    <p>
                      {search
                        ? "Passe den Suchbegriff an oder lösche ihn."
                        : "Neue PDF-Angebote aus dem Ordner „50 Angebote“ werden automatisch übernommen."}
                    </p>
                  </div>
                ) : (
                  <div className="offers-list">
                    {visible.map((offer) => {
                      const commissioned = offer.status === "beauftragt";
                      const expired = offerExpired(offer);
                      const shipping =
                        offerShipping[offer.id] ??
                        (offer.versandart === "Post" ? "Post" : "E-Mail");
                      return (
                        <article
                          className={`offer-item ${commissioned ? "is-commissioned" : ""} ${expired ? "is-expired" : ""}`}
                          key={offer.id}
                        >
                          <div className="offer-main">
                            <small>ANGEBOT</small>
                            <b>
                              {offer.angebot_nummer ||
                                offer.dateiname.replace(/\.pdf$/i, "")}
                            </b>
                          </div>
                          <div>
                            <small>KUNDE</small>
                            <b>{offer.kunde || "–"}</b>
                            {offer.objekt_zusatz && (
                              <span className="offer-property">
                                {offer.objekt_zusatz}
                              </span>
                            )}
                          </div>
                          <div>
                            <small>ERSTELLT</small>
                            <span>{formatDate(offer.erstellt_am)}</span>
                          </div>
                          <div>
                            <small>GÜLTIG BIS</small>
                            <span className={expired ? "offer-expired" : ""}>
                              {formatDate(offer.gueltig_bis)}
                              {expired ? " · Abgelaufen" : ""}
                            </span>
                          </div>
                          <div className="offer-status">
                            <small>STATUS</small>
                            {commissioned ? (
                              <strong>
                                Beauftragt · {formatDate(offer.beauftragt_am)}
                              </strong>
                            ) : offer.versendet ? (
                              <strong>
                                Versendet · {offer.versandart || "–"}
                              </strong>
                            ) : (
                              <strong>Noch nicht versendet</strong>
                            )}
                          </div>
                          {view === "offers-all" && (
                            <div className="offer-actions">
                              <select
                                value={shipping}
                                onChange={(event) =>
                                  setOfferShipping((values) => ({
                                    ...values,
                                    [offer.id]: event.target.value as
                                      "E-Mail" | "Post",
                                  }))
                                }
                              >
                                <option>E-Mail</option>
                                <option>Post</option>
                              </select>
                              <button
                                onClick={() =>
                                  void updateOffer(offer, "versendet")
                                }
                                disabled={offerBusy === `versendet-${offer.id}`}
                              >
                                {offerBusy === `versendet-${offer.id}`
                                  ? "Speichert …"
                                  : "Versendet"}
                              </button>
                            </div>
                          )}
                          {!commissioned && view === "offers-open" && (
                            <div className="offer-open-actions">
                              <button
                                className="offer-reset"
                                onClick={() =>
                                  void updateOffer(offer, "zuruecksetzen")
                                }
                                disabled={
                                  offerBusy === `zuruecksetzen-${offer.id}`
                                }
                              >
                                {offerBusy === `zuruecksetzen-${offer.id}`
                                  ? "Setzt zurück …"
                                  : "Zurücksetzen"}
                              </button>
                              <button
                                className="offer-commission"
                                onClick={() => setOfferConfirming(offer)}
                              >
                                Beauftragt
                              </button>
                            </div>
                          )}
                          {isSascha && (
                            <button
                              className="offer-delete"
                              onClick={() => void deleteOffer(offer)}
                              disabled={offerBusy === `delete-${offer.id}`}
                            >
                              {offerBusy === `delete-${offer.id}`
                                ? "Löscht …"
                                : "Löschen"}
                            </button>
                          )}
                        </article>
                      );
                    })}
                  </div>
                );
              })()}
            {offerConfirming && (
              <div
                className="offer-confirm-backdrop"
                role="dialog"
                aria-modal="true"
              >
                <div className="offer-confirm">
                  <p>BEAUFTRAGUNG BESTÄTIGEN</p>
                  <strong>
                    Hast du ein unterschriebenes Angebot vorliegen? Eine reine
                    Aussage reicht nicht aus!
                  </strong>
                  <span>
                    {offerConfirming.angebot_nummer ||
                      offerConfirming.dateiname}
                  </span>
                  <div>
                    <button onClick={() => setOfferConfirming(null)}>
                      NEIN
                    </button>
                    <button
                      onClick={() =>
                        void updateOffer(offerConfirming, "beauftragt")
                      }
                      disabled={
                        offerBusy === `beauftragt-${offerConfirming.id}`
                      }
                    >
                      {offerBusy === `beauftragt-${offerConfirming.id}`
                        ? "Speichert …"
                        : "JA"}
                    </button>
                  </div>
                </div>
              </div>
            )}
          </section>
        ) : view === "home" ? (
          <section className="dashboard-page">
            <div className="dashboard-welcome">
              <div className="dashboard-greeting">
                <p>EK-DOS · TAGESÜBERSICHT</p>
                <h1>
                  {dashboardGreeting}, {user}
                </h1>
              </div>
              <div className="dashboard-datetime">
                <span>{dashboardDate}</span>
                <b>
                  {dashboardNow.toLocaleTimeString("de-DE", {
                    hour: "2-digit",
                    minute: "2-digit",
                  })} Uhr
                </b>
              </div>
              <div className="dashboard-v2">
                <b>EK-DOS</b>
                <span>{EKDOS_VERSION} · DIGITAL OPERATING SYSTEM</span>
              </div>
            </div>
            <section
              className="dashboard-kpis"
              aria-label="Aktuelle Kennzahlen"
            >
              <button onClick={() => setView("tickets")}>
                <span className="kpi-icon blue">▣</span>
                <div>
                  <small>OFFENE TICKETS</small>
                  <b>{tickets.length}</b>
                  <em>aktive Vorgänge</em>
                </div>
              </button>
              <button
                onClick={() => {
                  setOffersOpen(true);
                  setView("offers-open");
                }}
              >
                <span className="kpi-icon orange">▤</span>
                <div>
                  <small>OFFENE ANGEBOTE</small>
                  <b>{openOfferCount}</b>
                  <em>Rückmeldung ausstehend</em>
                </div>
              </button>
              <button
                onClick={() =>
                  setView(
                    isSvenja ? "invoices-create" : "invoices-review-sascha",
                  )
                }
              >
                <span className="kpi-icon violet">◈</span>
                <div>
                  <small>RECHNUNGEN</small>
                  <b>
                    {isSvenja ? openInvoiceCreateCount : openInvoiceReviewCount}
                  </b>
                  <em>zur Bearbeitung</em>
                </div>
              </button>
              <button onClick={() => setView("internal-tasks")}>
                <span className="kpi-icon green">✓</span>
                <div>
                  <small>OFFENE AUFGABEN</small>
                  <b>{openTaskCount(isSascha ? "sascha" : "svenja")}</b>
                  <em>für dich und gemeinsam</em>
                </div>
              </button>
            </section>
            <section className="dashboard-grid">
              <article className="dashboard-panel dashboard-activity">
                <div className="panel-heading">
                  <div>
                    <p>LIVE-ÜBERSICHT</p>
                    <h2>Neueste Vorgänge</h2>
                  </div>
                  <button onClick={() => setView("tickets")}>
                    Alle Vorgänge →
                  </button>
                </div>
                <div className="activity-list">
                  {tickets.slice(0, 4).map((ticket) => {
                    const reportStatus = String(ticket.reportStatus ?? "")
                      .trim()
                      .toLocaleUpperCase("de-DE");
                    const statusTone =
                      reportStatus === "TEILERLEDIGT"
                        ? "orange"
                        : reportStatus === "ABGESCHLOSSEN"
                          ? "green"
                          : "blue";
                    return (
                      <button
                        key={ticket.id}
                        onClick={() => setView("tickets")}
                      >
                        <i className={`activity-dot ${statusTone}`} />
                        <span>
                          <b>{ticket.customer || "Unbekannter Kunde"}</b>
                          <small>{ticket.property || ticket.id}</small>
                        </span>
                        <em className={`activity-status ${statusTone}`}>
                          {ticket.reportStatus || ticket.status || "Offen"}
                        </em>
                        <time>{formatDateTime(ticket.updatedAt)}</time>
                      </button>
                    );
                  })}
                  {tickets.length === 0 && (
                    <div className="activity-empty">
                      <i className="activity-dot green" />
                      Keine neuen Vorgänge – EK-DOS ist bereit.
                    </div>
                  )}
                </div>
              </article>
              <article className="dashboard-panel helga-card">
                <div className="helga-photo">
                  <img
                    src="/helga-profile.png"
                    alt="Helga, digitale Assistentin von EK-DOS"
                  />
                </div>
                <div>
                  <p>DEINE DIGITALE ASSISTENTIN</p>
                  <h2>Helga</h2>
                  <b>Alle Systeme im Blick</b>
                  <small>
                    Ich überwache Eingänge, Tickets und deine offenen Aufgaben.
                  </small>
                </div>
              </article>
              <article className="dashboard-panel dashboard-inbox">
                <div className="panel-heading">
                  <div>
                    <p>HEUTE</p>
                    <h2>Eingang</h2>
                  </div>
                  <span className="count-pill">
                    {recentServiceTickets.length}
                  </span>
                </div>
                <button onClick={() => setView("tickets")}>
                  <i className="activity-dot blue" />
                  <span>
                    <b>Serviceberichte</b>
                    <small>
                      {recentServiceTickets.length} von heute und gestern
                    </small>
                  </span>
                  <em>Öffnen →</em>
                </button>
              </article>
              <article className="dashboard-panel dashboard-offers">
                <div className="panel-heading">
                  <div>
                    <p>ANGEBOTE</p>
                    <h2>Neue Angebote</h2>
                  </div>
                  <span className="count-pill">{unsentOfferCount}</span>
                </div>
                <button
                  onClick={() => {
                    setOffersOpen(true);
                    setView("offers-all");
                  }}
                >
                  <i className="activity-dot orange" />
                  <span>
                    <b>Noch nicht versendet</b>
                    <small>{unsentOfferCount} neue Angebote</small>
                  </span>
                  <em>Öffnen →</em>
                </button>
              </article>
              <article className="dashboard-panel dashboard-tasks">
                <div className="panel-heading">
                  <div>
                    <p>PRIORITÄTEN</p>
                    <h2>Offene Aufgaben</h2>
                  </div>
                  <button onClick={() => setView("internal-tasks")}>
                    Öffnen →
                  </button>
                </div>
                <div className="task-lines">
                  <span>
                    <i className="activity-dot orange" />
                    Rechnungen bearbeiten{" "}
                    <b>
                      {isSvenja
                        ? openInvoiceCreateCount
                        : openInvoiceReviewCount}
                    </b>
                  </span>
                  <span>
                    <i className="activity-dot blue" />
                    Interne Aufgaben{" "}
                    <b>{openTaskCount(isSascha ? "sascha" : "svenja")}</b>
                  </span>
                  <span>
                    <i className="activity-dot green" />
                    Rechnungen versenden <b>{openInvoiceSendCount}</b>
                  </span>
                </div>
              </article>
            </section>
            <footer className="dashboard-footer">
              <span>EK-DOS · Elektro Krüger · Wir setzen Sie unter Strom</span>
              <span>
                Systemstatus: <b>Alle Systeme online</b>
              </span>
            </footer>
          </section>
        ) : workspace ? (
          <section className="workspace-page">
            <p className="home-kicker">{workspace.kicker}</p>
            <h2>{workspace.title}</h2>
            <div className="workspace-empty">
              <b>Bereich wird vorbereitet</b>
              <p>{workspace.description}</p>
              <small>
                Die Navigation und Zugriffsrechte sind eingerichtet. Die
                Datenanbindung folgt mit dem jeweiligen n8n-Workflow.
              </small>
            </div>
          </section>
        ) : (
          <section className="lesson">
            <div className="stage-bar">
              {stages.map((item, index) => (
                <button
                  onClick={() => setStage(index)}
                  className={
                    stage === index
                      ? "stage active"
                      : index < stage
                        ? "stage complete"
                        : "stage"
                  }
                  key={item.title}
                >
                  <b>{index + 1}</b>
                  <span>
                    <strong>{item.title}</strong>
                    <small>
                      {index === 0
                        ? "Workflow 1–4"
                        : index === 1
                          ? "Workflow 4A / 4B / 6"
                          : index === 2
                            ? "Workflow 5A / 7 / 9 / 11 / 12"
                            : "Workflow 5B / 8 / 10 / 15–18"}
                    </small>
                  </span>
                </button>
              ))}
              <button
                className="restart"
                onClick={() => {
                  setStage(0);
                  setAnswers({});
                }}
              >
                ↻&nbsp; Neustart
              </button>
            </div>
            <div className="map-layout">
              <div className="map-card process-map">
                <div className="map-caption">
                  Aktueller Lernpfad: <b>{current.title}</b>
                </div>
                <section className="flow-lane">
                  <b className="flow-lane-title">1 · Eingang und Zuordnung</b>
                  <div className="flow-row">
                    <FlowNode id="mail" activeIds={current.active} />
                    <i>→</i>
                    <FlowNode id="pdf" activeIds={current.active} />
                    <i>→</i>
                    <FlowNode id="kunde" activeIds={current.active} />
                    <i>→</i>
                    <FlowNode id="ticketCheck" activeIds={current.active} />
                  </div>
                </section>
                <section className="flow-lane ticket-branch">
                  <b className="flow-lane-title">2 · Ticketprüfung</b>
                  <div className="branch-grid">
                    <div>
                      <small>Kein offenes Ticket</small>
                      <div className="flow-row">
                        <FlowNode id="ticketNew" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="folder" activeIds={current.active} />
                      </div>
                    </div>
                    <div>
                      <small>Offenes Ticket vorhanden</small>
                      <div className="flow-row">
                        <FlowNode id="status" activeIds={current.active} />
                      </div>
                    </div>
                  </div>
                  <div className="flow-merge">
                    ↓ <span>Berichtsstatus prüfen</span> ↓
                  </div>
                </section>
                <section className="flow-lane result-branch">
                  <b className="flow-lane-title">3 · Statusentscheidung</b>
                  <div className="branch-grid">
                    <div>
                      <small>Teilerledigt – Ticket bleibt offen</small>
                      <div className="flow-row">
                        <FlowNode id="partial" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="nas" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="akte" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="daily" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="hours" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="teams" activeIds={current.active} />
                      </div>
                    </div>
                    <div>
                      <small>Abgeschlossen – Übergabe an Rechnung</small>
                      <div className="flow-row">
                        <FlowNode id="completed" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="close" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="todo" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="invoice" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="review" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="send" activeIds={current.active} />
                        <i>→</i>
                        <FlowNode id="archive" activeIds={current.active} />
                      </div>
                    </div>
                  </div>
                </section>
              </div>
              <aside className="legend">
                <div>
                  <i className="legend-dot bright" />
                  Aktueller Schritt
                </div>
                <div>
                  <i className="legend-dot green-dot" />
                  Bereits erledigt
                </div>
                <div>
                  <i className="legend-dot yellow-dot" />
                  Noch nicht erreicht
                </div>
                <hr />
                <b>ⓘ Hinweis</b>
                <p>
                  Die grün markierten Schritte wurden bereits durchlaufen. Der
                  nächste Schritt wird automatisch hervorgehoben.
                </p>
              </aside>
            </div>
            <div className="explanation">
              <div className="lesson-number">{stage + 1}</div>
              <div className="explain-main">
                <h2>{current.title}</h2>
                <p>{current.question}</p>
              </div>
              <div className="explain-col">
                <b>♧ Was wird gemacht?</b>
                <ul>
                  <li>Informationen werden automatisch zugeordnet</li>
                  <li>EK-DOS aktualisiert Ticket und Digitale Akte</li>
                </ul>
              </div>
              <div className="explain-col">
                <b>✓ Was muss Svenja tun?</b>
                <p>{current.task}</p>
              </div>
              <div className="helga">
                <b>🤖 Helga sagt:</b>
                <p>„{current.helga}“</p>
              </div>
              <button
                className="next"
                onClick={() => setStage((value) => (value + 1) % stages.length)}
              >
                Weiter <span>→</span>
              </button>
            </div>
            <div className="exercise-card">
              <div className="exercise-heading">
                <span>ÜBUNG</span>
                <b>Entscheidung in {current.title}</b>
              </div>
              <h3>{exercise.question}</h3>
              <div className="exercise-answers">
                {exercise.answers.map((answer, index) => {
                  const selected = answers[stage] === index;
                  const answered = answers[stage] !== undefined;
                  const state = !answered
                    ? ""
                    : index === exercise.correct
                      ? " correct"
                      : selected
                        ? " wrong"
                        : "";
                  return (
                    <button
                      key={answer}
                      className={state}
                      disabled={answered}
                      onClick={() =>
                        setAnswers((value) => ({ ...value, [stage]: index }))
                      }
                    >
                      <i>{String.fromCharCode(65 + index)}</i>
                      {answer}
                    </button>
                  );
                })}
              </div>
              {answers[stage] !== undefined && (
                <div
                  className={
                    answers[stage] === exercise.correct
                      ? "exercise-note good"
                      : "exercise-note"
                  }
                >
                  {answers[stage] === exercise.correct ? "✓ " : "! "}
                  {answers[stage] === exercise.correct
                    ? exercise.note
                    : "Noch nicht richtig. Vergleiche die grün markierten Prozessschritte und wähle beim nächsten Durchlauf erneut."}
                </div>
              )}
            </div>
          </section>
        )}
      </div>
    </main>
  );
}
