import { redirect } from "next/navigation";
import Link from "next/link";
import { isAdminSession, hasPermission, getAllPermissions } from "@/lib/adminAuth";
import { connectDB } from "@/lib/db";
import { Order } from "@/models/Order";
import { Client } from "@/models/Client";
import { PriceProposal } from "@/models/PriceProposal";
import { Expense } from "@/models/Expense";
import { Income } from "@/models/Income";
import { OrderFeedback } from "@/models/OrderFeedback";
import { PhotoRating } from "@/models/PhotoRating";
import { Testimonial } from "@/models/Testimonial";
import { QuickReview } from "@/models/QuickReview";
import { Convention } from "@/models/Convention";
import { WaitlistEntry } from "@/models/WaitlistEntry";
import { GiftVoucher } from "@/models/GiftVoucher";
import { DiscountCode } from "@/models/DiscountCode";
import { PageView } from "@/models/PageView";
import { getPayableAmount, getTotalOrderDiscount } from "@/lib/discounts";
import { AdminNavLinks } from "@/components/admin/AdminNavLinks";
import { AdminPageHeader } from "@/components/admin/AdminPageHeader";
import { StatCard } from "@/components/admin/StatCard";
import { DonutChart } from "@/components/admin/DonutChart";
import { RevenueTrendChart } from "@/components/admin/RevenueTrendChart";
import { SatisfactionTrendChart } from "@/components/admin/SatisfactionTrendChart";
import { DayTrendChart } from "@/components/admin/DayTrendChart";
import { MonthHeatmap } from "@/components/admin/MonthHeatmap";
import { StatsTabs } from "@/components/admin/StatsTabs";
import { getSettings } from "@/lib/settings";
import {
  ORDER_TAGS,
  ORDER_TAG_LABELS,
  ORDER_TAG_COLORS,
  SHOOTING_TYPES,
  SHOOTING_TYPE_COLORS,
  PAYMENT_METHODS,
  PAYMENT_METHOD_LABELS,
  formatEUR,
  formatPaymentReference,
} from "@/lib/orderConstants";

export const dynamic = "force-dynamic";

function monthKey(d: Date) {
  return new Date(d).toISOString().slice(0, 7);
}

export default async function AdminStatisticsPage() {
  if (!(await isAdminSession())) redirect("/de/login?next=%2Fde%2Fadmin%2Forders");

  if (!(await hasPermission("statistics"))) redirect("/de/account");

  const permissions = await getAllPermissions();

  await connectDB();
  const settings = await getSettings();
  const orders = await Order.find({}).lean();
  const clients = await Client.find({}).lean();
  const clientById = new Map(clients.map((c) => [String(c._id), c]));
  // Client.find({}) enthält auch Mitarbeiter-Konten — für Kundenzahlen zählt
  // nur role:"client". clientById bleibt bewusst ungefiltert (wird auch für
  // Mitarbeiter-Namensauflösung bei zugewiesenen Aufträgen gebraucht).
  const realClients = clients.filter((c) => c.role === "client");
  const expenses = await Expense.find({}).lean();
  const feedbackEntries = await OrderFeedback.find({ submitted: true, rating: { $gt: 0 } }).lean();
  const ordersById = new Map(orders.map((o) => [String(o._id), o]));
  // Ein Auftrag, dessen Preis akzeptiert, der dann aber storniert/abgelehnt
  // wurde, ist kein tatsächlicher Umsatz — sonst zählen Absagen nach
  // Preiseinigung dauerhaft (und fälschlich) in Umsatz/Gewinn mit. Bewusst
  // auch Proposals ohne (mehr) existierenden Auftrag ausschließen (z. B.
  // nach einer harten Kontolöschung).
  const acceptedProposals = (await PriceProposal.find({ status: "accepted" }).lean()).filter((p) => {
    const o = ordersById.get(String(p.orderId));
    return o && !o.rejected;
  });
  // Ein eingelöster Rabattcode mindert den tatsächlichen Umsatz — alle
  // Umsatzberechnungen unten arbeiten daher mit dem rabattierten Betrag,
  // nicht mit dem rohen Preisvorschlag.
  const payableFor = (p: { orderId: unknown; amount: number }) => {
    const o = ordersById.get(String(p.orderId));
    return getPayableAmount(p.amount, o ? getTotalOrderDiscount(o) : 0);
  };

  // Auftrags-Funnel
  const tagCounts = new Map<string, number>();
  for (const tag of ORDER_TAGS) tagCounts.set(tag, 0);
  for (const o of orders) tagCounts.set(o.tag, (tagCounts.get(o.tag) ?? 0) + 1);
  const rejectedCount = orders.filter((o) => o.rejected).length;

  // Preise & Umsatz
  // "Umsatz" ist bewusst nur der TATSÄCHLICH bezahlte Betrag (Zufluss-
  // Prinzip) — genau wie /admin/tax und die EÜR es schon immer gehandhabt
  // haben. Ein vereinbarter, aber noch nicht bezahlter Preis ist noch kein
  // Umsatz, sondern offenes Geld — sonst würden Gewinn und Steuerrücklage
  // weiter unten Geld einrechnen, das noch gar nicht eingegangen ist.
  const amounts = acceptedProposals.map((p) => payableFor(p));
  const totalAgreed = amounts.reduce((a, b) => a + b, 0);
  const acceptedByOrderId = new Map(acceptedProposals.map((p) => [String(p.orderId), p]));

  const paidOrdersWithPrice = orders.filter(
    (o) => o.paid && !o.rejected && acceptedByOrderId.has(String(o._id))
  );
  const paidAmounts = paidOrdersWithPrice.map((o) => payableFor(acceptedByOrderId.get(String(o._id))!));
  const totalRevenue = paidAmounts.reduce((a, b) => a + b, 0);
  const avgRevenue = paidAmounts.length ? totalRevenue / paidAmounts.length : 0;

  // Nach Zahlungsdatum gruppiert (nicht nach Vereinbarungsdatum) — zeigt,
  // wann das Geld tatsächlich reinkam, nicht wann der Preis feststand.
  const revenueByMonth = new Map<string, number>();
  for (const o of paidOrdersWithPrice) {
    const amount = payableFor(acceptedByOrderId.get(String(o._id))!);
    const key = monthKey(o.paidAt || o.createdAt);
    revenueByMonth.set(key, (revenueByMonth.get(key) ?? 0) + amount);
  }
  const revenueMonths = [...revenueByMonth.entries()].sort(([a], [b]) => a.localeCompare(b));

  const openPaymentOrders = orders.filter(
    (o) => o.compensationType === "paid" && !o.paid && !o.rejected && !o.archived && acceptedByOrderId.has(String(o._id))
  );
  const openPaymentAmount = openPaymentOrders.reduce(
    (sum, o) => sum + payableFor(acceptedByOrderId.get(String(o._id))!),
    0
  );

  const revenueByMethod = new Map<string, number>();
  for (const o of orders) {
    if (!o.paid || !o.paymentMethod) continue;
    const accepted = acceptedByOrderId.get(String(o._id));
    if (!accepted) continue;
    revenueByMethod.set(o.paymentMethod, (revenueByMethod.get(o.paymentMethod) ?? 0) + payableFor(accepted));
  }
  const revenueByMethodRows = PAYMENT_METHODS.map((m) => [m, revenueByMethod.get(m) ?? 0] as const).filter(
    ([, amount]) => amount > 0
  );

  // Einnahmen & Ausgaben
  // Manuell erfasste Einnahmen (ohne Auftragsbezug, z. B. Workshops) zählen
  // für Gewinn/Steuerrücklage genauso mit wie Auftragsumsatz — "Umsatz
  // (bezahlt)" oben und der Preise-&-Umsatz-Bereich bleiben aber bewusst rein
  // auftragsbezogen (totalRevenue unverändert), dafür gibt es hier eine
  // eigene kombinierte Summe.
  const manualIncome = await Income.find({}).lean();
  const manualIncomeTotal = manualIncome.reduce((sum, i) => sum + i.amount, 0);
  const combinedIncomeTotal = totalRevenue + manualIncomeTotal;
  const combinedIncomeByMonth = new Map(revenueByMonth);
  for (const i of manualIncome) {
    const key = monthKey(i.date);
    combinedIncomeByMonth.set(key, (combinedIncomeByMonth.get(key) ?? 0) + i.amount);
  }

  const totalExpenses = expenses.reduce((sum, e) => sum + e.amount, 0);
  const expensesByMonth = new Map<string, number>();
  for (const e of expenses) {
    const key = monthKey(e.date);
    expensesByMonth.set(key, (expensesByMonth.get(key) ?? 0) + e.amount);
  }
  const profitMonths = [...new Set([...combinedIncomeByMonth.keys(), ...expensesByMonth.keys()])]
    .sort((a, b) => a.localeCompare(b))
    .map((month) => {
      const income = combinedIncomeByMonth.get(month) ?? 0;
      const expense = expensesByMonth.get(month) ?? 0;
      return { month, income, expense, profit: income - expense };
    });

  // Ablehnungsgründe
  const reasonCounts = new Map<string, number>();
  for (const o of orders) {
    if (o.rejected && o.rejectionReason) reasonCounts.set(o.rejectionReason, (reasonCounts.get(o.rejectionReason) ?? 0) + 1);
  }
  const reasonRows = [...reasonCounts.entries()].sort(([, a], [, b]) => b - a);
  const maxReasonCount = Math.max(1, ...reasonRows.map(([, c]) => c));

  // Kunden
  const verifiedCount = realClients.filter((c) => c.verified).length;
  const clientsByMonth = new Map<string, number>();
  for (const c of realClients) {
    const key = monthKey(c.createdAt);
    clientsByMonth.set(key, (clientsByMonth.get(key) ?? 0) + 1);
  }
  const clientMonths = [...clientsByMonth.entries()].sort(([a], [b]) => a.localeCompare(b));

  // Wiederkehrende Kunden — nicht-abgelehnte Aufträge pro Kunde gezählt.
  const orderCountByClient = new Map<string, number>();
  for (const o of orders) {
    if (o.rejected) continue;
    const key = String(o.clientId);
    orderCountByClient.set(key, (orderCountByClient.get(key) ?? 0) + 1);
  }
  const repeatClientCount = [...orderCountByClient.values()].filter((c) => c > 1).length;
  const clientsWithOrders = orderCountByClient.size;

  // Angebote (Art des Shootings)
  const shootingTypeCounts = new Map<string, number>();
  for (const t of SHOOTING_TYPES) shootingTypeCounts.set(t, 0);
  for (const o of orders) shootingTypeCounts.set(o.shootingType, (shootingTypeCounts.get(o.shootingType) ?? 0) + 1);

  // Fandom-/Charakter-Auswertung — grobe Normalisierung (klein geschrieben,
  // getrimmt) reicht für eine Häufigkeits-Übersicht; exakte Duplikate durch
  // leicht abweichende Schreibweisen im Freitextfeld sind nicht vermeidbar.
  const characterCounts = new Map<string, { label: string; count: number }>();
  for (const o of orders) {
    const raw = o.characterOrConcept?.trim();
    if (!raw) continue;
    const key = raw.toLowerCase();
    const existing = characterCounts.get(key);
    if (existing) existing.count += 1;
    else characterCounts.set(key, { label: raw, count: 1 });
  }
  const topCharacters = [...characterCounts.values()].sort((a, b) => b.count - a.count).slice(0, 15);
  const topCharacterMax = topCharacters[0]?.count ?? 0;

  // Zufriedenheits-Trend — nach Einreichungsdatum der Bewertung, nicht nach
  // Auftragsdatum, damit sich der Trend auf tatsächliches Feedback bezieht.
  const ratingByMonth = new Map<string, { sum: number; count: number }>();
  for (const f of feedbackEntries) {
    if (!f.submittedAt) continue;
    const key = monthKey(f.submittedAt);
    const entry = ratingByMonth.get(key) ?? { sum: 0, count: 0 };
    entry.sum += f.rating;
    entry.count += 1;
    ratingByMonth.set(key, entry);
  }
  const satisfactionMonths = [...ratingByMonth.entries()]
    .sort(([a], [b]) => a.localeCompare(b))
    .map(([month, { sum, count }]) => ({ month, avg: sum / count, count }));

  // Auslastung — nach tatsächlichem Shooting-Termin, nicht nach Anfragedatum,
  // damit saisonale Spitzen (z. B. Convention-Saison) sichtbar werden.
  const shootsByMonth = new Map<string, number>();
  for (const o of orders) {
    if (!o.shootDate || o.rejected) continue;
    const key = monthKey(o.shootDate);
    shootsByMonth.set(key, (shootsByMonth.get(key) ?? 0) + 1);
  }
  const shootMonths = [...shootsByMonth.entries()].map(([month, count]) => ({ month, count }));

  const staffById = clientById; // gleiche Map, nur zur Klarheit an den Stellen unten mit Mitarbeiterbezug

  // Gebuchte Leistungen/Pakete — aus den Snapshot-Feldern, die beim Buchen
  // über /angebote auf dem Auftrag gespeichert werden (kein FK auf Service/
  // Bundle, da sich Preise/Namen später ändern können).
  const bookedServiceCounts = new Map<string, number>();
  const bookedBundleCounts = new Map<string, number>();
  for (const o of orders) {
    if (o.bookedServiceTitle) {
      const key = o.bookedTierName ? `${o.bookedServiceTitle} — ${o.bookedTierName}` : o.bookedServiceTitle;
      bookedServiceCounts.set(key, (bookedServiceCounts.get(key) ?? 0) + 1);
    }
    if (o.bookedBundleTitle) bookedBundleCounts.set(o.bookedBundleTitle, (bookedBundleCounts.get(o.bookedBundleTitle) ?? 0) + 1);
  }
  const bookedServiceRows = [...bookedServiceCounts.entries()].sort(([, a], [, b]) => b - a);
  const maxBookedService = Math.max(1, ...bookedServiceRows.map(([, c]) => c));
  const bookedBundleRows = [...bookedBundleCounts.entries()].sort(([, a], [, b]) => b - a);
  const maxBookedBundle = Math.max(1, ...bookedBundleRows.map(([, c]) => c));

  // TFP vs. bezahlt
  const compensationCounts = new Map<string, number>([
    ["paid", 0],
    ["tfp", 0],
  ]);
  for (const o of orders) compensationCounts.set(o.compensationType, (compensationCounts.get(o.compensationType) ?? 0) + 1);

  // Aufträge & Umsatz pro Mitarbeiter (nur zugewiesene Aufträge)
  const staffOrderCounts = new Map<string, { name: string; count: number; revenue: number }>();
  for (const o of orders) {
    if (!o.assignedStaffId) continue;
    const staff = staffById.get(String(o.assignedStaffId));
    if (!staff) continue;
    const entry = staffOrderCounts.get(String(o.assignedStaffId)) ?? { name: staff.name, count: 0, revenue: 0 };
    entry.count += 1;
    if (o.paid && !o.rejected) {
      const accepted = acceptedByOrderId.get(String(o._id));
      if (accepted) entry.revenue += payableFor(accepted);
    }
    staffOrderCounts.set(String(o.assignedStaffId), entry);
  }
  const staffOrderRows = [...staffOrderCounts.values()].sort((a, b) => b.count - a.count);

  // Foto-Bewertungen — Sterne, die Kunden ihren gelieferten Fotos geben
  // (stars: 0 = unbewertet), plus die Freigabequote zum Download.
  const photoRatingDocs = await PhotoRating.find({}).lean();
  const ratedPhotos = photoRatingDocs.filter((r) => r.stars > 0);
  const avgPhotoStars = ratedPhotos.length ? ratedPhotos.reduce((sum, r) => sum + r.stars, 0) / ratedPhotos.length : 0;
  const photoStarDist = [5, 4, 3, 2, 1].map((n) => ({ n, count: ratedPhotos.filter((r) => r.stars === n).length }));
  const maxPhotoStarCount = Math.max(1, ...photoStarDist.map((d) => d.count));
  const approvedPhotoCount = photoRatingDocs.filter((r) => r.approvedForDownload).length;

  // Bewertungen — Testimonials (Kundenstimmen, teils von Google importiert)
  // und Kurzbewertungen (nur Sterne+Name, Startseiten-Fließband) getrennt
  // gezählt, aber für den Gesamtschnitt zusammengefasst.
  const testimonials = await Testimonial.find({}).lean();
  const quickReviews = await QuickReview.find({}).lean();
  const allReviewStars = [...testimonials.map((t) => t.rating), ...quickReviews.map((q) => q.rating)].filter((r) => r > 0);
  const avgReviewStars = allReviewStars.length ? allReviewStars.reduce((a, b) => a + b, 0) / allReviewStars.length : 0;
  const visibleTestimonials = testimonials.filter((t) => t.visible).length;
  const googleTestimonials = testimonials.filter((t) => t.source === "google").length;
  const manualTestimonials = testimonials.length - googleTestimonials;

  // Gutscheine & Rabattcodes
  const vouchers = await GiftVoucher.find({}).lean();
  const paidVouchers = vouchers.filter((v) => v.paid && !v.cancelled);
  const voucherRevenue = paidVouchers.reduce((sum, v) => sum + v.amount, 0);
  const redeemedVoucherCount = paidVouchers.filter((v) => v.redeemed).length;
  const openVoucherCount = paidVouchers.length - redeemedVoucherCount;
  const discountCodes = await DiscountCode.find({}).lean();
  const activeDiscountCodes = discountCodes.filter((d) => d.active).length;
  const totalDiscountUses = discountCodes.reduce((sum, d) => sum + d.usedCount, 0);

  // Conventions & Warteliste
  const conventions = await Convention.find({}).lean();
  const now = new Date();
  const upcomingConventions = conventions.filter((c) => c.visible && new Date(c.endDate) >= now);
  const waitlistEntries = await WaitlistEntry.find({}).lean();
  const notifiedWaitlistCount = waitlistEntries.filter((w) => w.notified).length;

  // Seitenaufrufe — anonymer, first-party Zähler (siehe models/PageView.ts),
  // läuft erst seit Einführung dieses Dashboards mit, also am Anfang noch
  // wenig Historie. Aggregation statt In-App-Reduce, da diese Collection
  // unbegrenzt wächst (im Gegensatz zu Aufträgen/Kunden).
  const totalPageViews = await PageView.countDocuments({});
  const thirtyDaysAgo = new Date(now.getTime() - 30 * 24 * 60 * 60 * 1000);
  const dailyViewsAgg = await PageView.aggregate<{ _id: string; count: number }>([
    { $match: { createdAt: { $gte: thirtyDaysAgo } } },
    { $group: { _id: { $dateToString: { format: "%Y-%m-%d", date: "$createdAt" } }, count: { $sum: 1 } } },
    { $sort: { _id: 1 } },
  ]);
  const dailyViewsByDay = new Map(dailyViewsAgg.map((d) => [d._id, d.count]));
  const dailyViews: { day: string; count: number }[] = [];
  for (let i = 29; i >= 0; i--) {
    const d = new Date(now.getTime() - i * 24 * 60 * 60 * 1000);
    const key = d.toISOString().slice(0, 10);
    dailyViews.push({ day: key, count: dailyViewsByDay.get(key) ?? 0 });
  }
  const viewsLast30Days = dailyViews.reduce((sum, d) => sum + d.count, 0);
  const topPagesAgg = await PageView.aggregate<{ _id: string; count: number }>([
    { $group: { _id: "$path", count: { $sum: 1 } } },
    { $sort: { count: -1 } },
    { $limit: 12 },
  ]);
  const maxTopPageCount = Math.max(1, ...topPagesAgg.map((p) => p.count));

  // Grobe, datenschutzfreundliche Konversions-Näherung: Seitenaufrufe sind
  // bewusst anonym ohne Besucher-ID (siehe models/PageView.ts) — ein echter
  // Pro-Besucher-Trichter ("hat X die Seite gesehen und dann gebucht") würde
  // Cookies/eine Sitzungs-ID erfordern, was dem bisherigen Datenschutz-
  // Ansatz widerspräche. Stattdessen: aggregierte Aufrufe der Angebote-Seite
  // vs. neue Auftragsanfragen im selben Zeitraum, als Richtwert statt echter
  // Attribution.
  const angeboteViewsLast30 = await PageView.countDocuments({
    path: { $regex: "^/(de|en)/angebote" },
    createdAt: { $gte: thirtyDaysAgo },
  });
  const newOrdersLast30 = orders.filter((o) => new Date(o.createdAt) >= thirtyDaysAgo).length;
  const angeboteConversionRate = angeboteViewsLast30 > 0 ? (newOrdersLast30 / angeboteViewsLast30) * 100 : null;

  const seo = settings.seoSettings;

  return (
    <main className="px-6 pt-4 pb-24 max-w-5xl mx-auto">
      <AdminNavLinks permissions={permissions} />
      <AdminPageHeader title="Statistiken" />

      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3 mb-4">
        <StatCard label="Aufträge" value={orders.length} />
        <StatCard label="Kunden" value={realClients.length} />
        <StatCard label="Umsatz (bezahlt)" value={formatEUR(totalRevenue)} accent="emerald" />
        <StatCard
          label={`Offene Zahlungen (${openPaymentOrders.length})`}
          value={formatEUR(openPaymentAmount)}
          accent={openPaymentOrders.length ? "red" : "muted"}
        />
      </div>
      <div className="grid grid-cols-2 sm:grid-cols-4 gap-3 mb-10">
        <StatCard label="Ø Foto-Bewertung" value={ratedPhotos.length ? `${avgPhotoStars.toFixed(1)} ★` : "—"} />
        <StatCard label="Ø Kundenstimme" value={allReviewStars.length ? `${avgReviewStars.toFixed(1)} ★` : "—"} />
        <StatCard label="Seitenaufrufe (30 Tage)" value={viewsLast30Days} accent="muted" />
        <StatCard label="Gutschein-Umsatz" value={formatEUR(voucherRevenue)} accent={voucherRevenue ? "emerald" : "muted"} />
      </div>

        <StatsTabs
          tabs={[
            {
              id: "orders",
              label: "Aufträge",
              content: (
                <>
                  <Section title="Auftrags-Funnel">
                    <DonutChart
                      segments={ORDER_TAGS.map((tag) => ({
                        label: ORDER_TAG_LABELS[tag],
                        value: tagCounts.get(tag) ?? 0,
                        color: ORDER_TAG_COLORS[tag],
                      }))}
                    />
                    <p className="mt-4 text-xs text-[var(--rk-ink-muted)]">
                      Davon abgelehnt: {rejectedCount} von {orders.length}
                      {orders.length ? ` (${Math.round((rejectedCount / orders.length) * 100)}%)` : ""}
                    </p>
                  </Section>

                  <Section title="Aufträge im Detail">
                    <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Bezahlt vs. TFP</p>
                    <DonutChart
                      segments={[
                        { label: "Bezahlt", value: compensationCounts.get("paid") ?? 0, color: "#34d399" },
                        { label: "TFP", value: compensationCounts.get("tfp") ?? 0, color: "#a3a1a6" },
                      ]}
                    />

                    {bookedServiceRows.length > 0 && (
                      <div className="mt-6 pt-5 border-t border-white/10">
                        <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">
                          Gebuchte Leistungen (über „Angebote")
                        </p>
                        <div className="flex flex-col gap-2">
                          {bookedServiceRows.map(([label, count]) => (
                            <BarRow key={label} label={label} count={count} max={maxBookedService} />
                          ))}
                        </div>
                      </div>
                    )}

                    {bookedBundleRows.length > 0 && (
                      <div className="mt-6 pt-5 border-t border-white/10">
                        <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Gebuchte Pakete</p>
                        <div className="flex flex-col gap-2">
                          {bookedBundleRows.map(([label, count]) => (
                            <BarRow key={label} label={label} count={count} max={maxBookedBundle} />
                          ))}
                        </div>
                      </div>
                    )}

                    {staffOrderRows.length > 0 && (
                      <div className="mt-6 pt-5 border-t border-white/10">
                        <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Aufträge pro Mitarbeiter</p>
                        <table className="w-full text-xs">
                          <thead>
                            <tr className="text-[var(--rk-ink-muted)] text-left">
                              <th className="font-normal pb-1">Name</th>
                              <th className="font-normal pb-1 text-right">Aufträge</th>
                              <th className="font-normal pb-1 text-right">Umsatz (bezahlt)</th>
                            </tr>
                          </thead>
                          <tbody>
                            {staffOrderRows.map((s) => (
                              <tr key={s.name} className="border-t border-white/10">
                                <td className="py-2">{s.name}</td>
                                <td className="py-2 text-right">{s.count}</td>
                                <td className="py-2 text-right">{formatEUR(s.revenue)}</td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </div>
                    )}
                  </Section>

                  <Section title="Offene Zahlungen">
                    {openPaymentOrders.length > 0 ? (
                      <div className="flex flex-col gap-2">
                        {openPaymentOrders.map((o) => {
                          const client = clientById.get(String(o.clientId));
                          const accepted = acceptedByOrderId.get(String(o._id));
                          const amount = accepted ? payableFor(accepted) : 0;
                          return (
                            <Link
                              key={String(o._id)}
                              href={`/de/admin/orders/${o._id}`}
                              className="flex items-center justify-between gap-3 text-xs border border-white/10 rounded-lg px-3 py-2 hover:border-white/30 transition-colors"
                            >
                              <span className="text-[var(--rk-ink)]">
                                {o.characterOrConcept} · {client?.name || "Unbekannt"}
                              </span>
                              <span className="flex items-center gap-3 shrink-0">
                                <span className="font-mono text-[var(--rk-ink-muted)]">{formatPaymentReference(String(o._id))}</span>
                                <span className="text-amber-400">{formatEUR(amount)}</span>
                              </span>
                            </Link>
                          );
                        })}
                      </div>
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Keine offenen Zahlungen.</p>
                    )}
                  </Section>

                  <Section title="Auslastung nach Monat">
                    {shootMonths.length > 0 ? (
                      <MonthHeatmap data={shootMonths} />
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Noch keine terminierten Shootings.</p>
                    )}
                  </Section>

                  <Section title="Ablehnungsgründe">
                    {reasonRows.length > 0 ? (
                      <div className="flex flex-col gap-2">
                        {reasonRows.map(([label, count]) => (
                          <BarRow key={label} label={label} count={count} max={maxReasonCount} />
                        ))}
                      </div>
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Noch keine Ablehnungen.</p>
                    )}
                  </Section>

                  {topCharacters.length > 0 && (
                    <Section title="Beliebteste Charaktere & Fandoms">
                      <p className="text-xs text-[var(--rk-ink-muted)] mb-4">
                        Aus dem Freitextfeld „Charakter/Konzept" bei der Auftragsanfrage — nützlich, um zu sehen, welche
                        Fandoms/Conventions sich lohnen. Leicht unterschiedliche Schreibweisen zählen als eigene Zeile.
                      </p>
                      <div className="flex flex-col gap-2">
                        {topCharacters.map((c) => (
                          <BarRow key={c.label} label={c.label} count={c.count} max={topCharacterMax} />
                        ))}
                      </div>
                    </Section>
                  )}
                </>
              ),
            },
            {
              id: "finance",
              label: "Finanzen",
              content: (
                <>
                  <Section title="Preise & Umsatz">
                    <dl className="grid grid-cols-2 sm:grid-cols-5 gap-4 text-sm mb-5">
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Umsatz (bezahlt)</dt>
                        <dd className="mt-1 text-base">{formatEUR(totalRevenue)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Offen (vereinbart, unbezahlt)</dt>
                        <dd className="mt-1 text-base">{formatEUR(openPaymentAmount)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Vereinbart gesamt</dt>
                        <dd className="mt-1 text-base">{formatEUR(totalAgreed)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Ø Preis (bezahlt)</dt>
                        <dd className="mt-1 text-base">{formatEUR(avgRevenue)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Vereinbarte Aufträge</dt>
                        <dd className="mt-1 text-base">{amounts.length}</dd>
                      </div>
                    </dl>
                    {revenueMonths.length > 0 ? (
                      <>
                        <RevenueTrendChart data={revenueMonths.map(([month, amount]) => ({ month, amount }))} />
                        <table className="w-full text-xs mt-5">
                          <tbody>
                            {revenueMonths.map(([month, amount]) => (
                              <tr key={month} className="border-t border-white/10">
                                <td className="py-2 text-[var(--rk-ink-muted)]">{month}</td>
                                <td className="py-2 text-right">{formatEUR(amount)}</td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </>
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Noch keine bezahlten Aufträge.</p>
                    )}

                    {revenueByMethodRows.length > 0 && (
                      <div className="mt-5 pt-5 border-t border-white/10">
                        <p className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em] mb-2">
                          Eingegangene Zahlungen nach Zahlungsart
                        </p>
                        <table className="w-full text-xs">
                          <tbody>
                            {revenueByMethodRows.map(([method, amount]) => (
                              <tr key={method} className="border-t border-white/10">
                                <td className="py-2 text-[var(--rk-ink-muted)]">{PAYMENT_METHOD_LABELS[method]}</td>
                                <td className="py-2 text-right">{formatEUR(amount)}</td>
                              </tr>
                            ))}
                          </tbody>
                        </table>
                      </div>
                    )}
                  </Section>

                  <Section title="Einnahmen & Ausgaben">
                    <dl className="grid grid-cols-2 sm:grid-cols-4 gap-4 text-sm mb-5">
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Einnahmen</dt>
                        <dd className="mt-1 text-base">{formatEUR(combinedIncomeTotal)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Ausgaben</dt>
                        <dd className="mt-1 text-base">{formatEUR(totalExpenses)}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Gewinn</dt>
                        <dd className={`mt-1 text-base ${combinedIncomeTotal - totalExpenses >= 0 ? "text-emerald-400" : "text-red-400"}`}>
                          {formatEUR(combinedIncomeTotal - totalExpenses)}
                        </dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">
                          Steuerrücklage (Richtwert, {settings.taxReserveSettings.percentage}%)
                        </dt>
                        <dd className="mt-1 text-base text-amber-400">
                          {formatEUR(Math.max(0, combinedIncomeTotal - totalExpenses) * (settings.taxReserveSettings.percentage / 100))}
                        </dd>
                      </div>
                    </dl>
                    <p className="text-xs text-[var(--rk-ink-muted)] mb-5">
                      Einnahmen enthalten bezahlten Auftragsumsatz plus manuell erfasste Einnahmen ({formatEUR(manualIncomeTotal)}).
                      Grober Richtwert auf Basis des Gewinns — kein Ersatz für eine steuerliche Beratung. Prozentsatz unter{" "}
                      „Einstellungen" anpassbar.
                    </p>
                    {profitMonths.length > 0 ? (
                      <table className="w-full text-xs">
                        <thead>
                          <tr className="text-[var(--rk-ink-muted)] text-left">
                            <th className="font-normal pb-1">Monat</th>
                            <th className="font-normal pb-1 text-right">Einnahmen</th>
                            <th className="font-normal pb-1 text-right">Ausgaben</th>
                            <th className="font-normal pb-1 text-right">Gewinn</th>
                          </tr>
                        </thead>
                        <tbody>
                          {profitMonths.map((m) => (
                            <tr key={m.month} className="border-t border-white/10">
                              <td className="py-2 text-[var(--rk-ink-muted)]">{m.month}</td>
                              <td className="py-2 text-right">{formatEUR(m.income)}</td>
                              <td className="py-2 text-right">{formatEUR(m.expense)}</td>
                              <td className={`py-2 text-right ${m.profit >= 0 ? "text-emerald-400" : "text-red-400"}`}>
                                {formatEUR(m.profit)}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Noch keine Daten.</p>
                    )}
                    <div className="flex items-center gap-4 mt-4">
                      <Link
                        href="/de/admin/expenses"
                        className="text-xs text-[var(--rk-ink-muted)] hover:text-[var(--rk-ink)] underline transition-colors"
                      >
                        Ausgaben verwalten →
                      </Link>
                      <Link
                        href="/de/admin/tax"
                        className="text-xs text-[var(--rk-ink-muted)] hover:text-[var(--rk-ink)] underline transition-colors"
                      >
                        EÜR-Export & Steuerrücklage →
                      </Link>
                    </div>
                  </Section>

                  {(vouchers.length > 0 || discountCodes.length > 0) && (
                    <Section title="Gutscheine & Rabattcodes">
                      <dl className="grid grid-cols-2 sm:grid-cols-4 gap-4 text-sm">
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Gutschein-Umsatz</dt>
                          <dd className="mt-1 text-base text-emerald-400">{formatEUR(voucherRevenue)}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Eingelöst / offen</dt>
                          <dd className="mt-1 text-base">
                            {redeemedVoucherCount} / {openVoucherCount}
                          </dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Aktive Rabattcodes</dt>
                          <dd className="mt-1 text-base">{activeDiscountCodes}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Rabattcode-Einlösungen</dt>
                          <dd className="mt-1 text-base">{totalDiscountUses}</dd>
                        </div>
                      </dl>
                    </Section>
                  )}
                </>
              ),
            },
            {
              id: "customers",
              label: "Kunden & Bewertungen",
              content: (
                <>
                  <Section title="Kunden & Angebote">
                    <p className="text-sm mb-4">
                      {realClients.length} Kunden insgesamt, davon {verifiedCount} verifiziert
                      {clientsWithOrders > 0 && (
                        <>
                          {" "}
                          ·{" "}
                          <span className={repeatClientCount > 0 ? "text-emerald-400" : ""}>
                            {repeatClientCount} von {clientsWithOrders} mit mehr als einem Auftrag wiedergekommen
                          </span>
                        </>
                      )}
                    </p>
                    {clientMonths.length > 0 && (
                      <table className="w-full text-xs mb-6">
                        <tbody>
                          {clientMonths.map(([month, count]) => (
                            <tr key={month} className="border-t border-white/10">
                              <td className="py-2 text-[var(--rk-ink-muted)]">{month}</td>
                              <td className="py-2 text-right">
                                {count} Neuregistrierung{count === 1 ? "" : "en"}
                              </td>
                            </tr>
                          ))}
                        </tbody>
                      </table>
                    )}
                    <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Nachgefragte Art des Shootings</p>
                    <DonutChart
                      segments={SHOOTING_TYPES.map((t) => ({
                        label: t,
                        value: shootingTypeCounts.get(t) ?? 0,
                        color: SHOOTING_TYPE_COLORS[t],
                      }))}
                    />
                  </Section>

                  {satisfactionMonths.length > 0 && (
                    <Section title="Zufriedenheit über Zeit">
                      <p className="text-xs text-[var(--rk-ink-muted)] mb-4">
                        Durchschnittliche Sternebewertung aus dem Feedback-Formular, nach Einreichungsmonat — hilft,
                        Qualitätsschwankungen früh zu erkennen.
                      </p>
                      <SatisfactionTrendChart data={satisfactionMonths} />
                    </Section>
                  )}

                  <Section title="Foto-Bewertungen">
                    <p className="text-xs text-[var(--rk-ink-muted)] mb-4">
                      Sterne, die Kunden ihren gelieferten Fotos in der Foto-Galerie geben.
                    </p>
                    <dl className="grid grid-cols-2 sm:grid-cols-3 gap-4 text-sm mb-5">
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Ø Bewertung</dt>
                        <dd className="mt-1 text-base">{ratedPhotos.length ? `${avgPhotoStars.toFixed(2)} ★` : "—"}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Bewertete Fotos</dt>
                        <dd className="mt-1 text-base">{ratedPhotos.length}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Zum Download freigegeben</dt>
                        <dd className="mt-1 text-base">{approvedPhotoCount}</dd>
                      </div>
                    </dl>
                    {ratedPhotos.length > 0 ? (
                      <div className="flex flex-col gap-2">
                        {photoStarDist.map((d) => (
                          <BarRow key={d.n} label={`${d.n} ★`} count={d.count} max={maxPhotoStarCount} />
                        ))}
                      </div>
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">Noch keine Foto-Bewertungen.</p>
                    )}
                  </Section>

                  <Section title="Kundenstimmen & Kurzbewertungen">
                    <p className="text-xs text-[var(--rk-ink-muted)] mb-4">
                      Testimonials (ausführliche Kundenstimmen, teils von Google übernommen) und die kompakten
                      Sterne-Kurzbewertungen im Startseiten-Fließband, zusammengefasst.
                    </p>
                    <dl className="grid grid-cols-2 sm:grid-cols-4 gap-4 text-sm">
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Ø Bewertung</dt>
                        <dd className="mt-1 text-base">{allReviewStars.length ? `${avgReviewStars.toFixed(2)} ★` : "—"}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Kundenstimmen</dt>
                        <dd className="mt-1 text-base">
                          {testimonials.length} <span className="text-[var(--rk-ink-muted)]">({visibleTestimonials} sichtbar)</span>
                        </dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Davon von Google</dt>
                        <dd className="mt-1 text-base">{googleTestimonials}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Kurzbewertungen</dt>
                        <dd className="mt-1 text-base">{quickReviews.length}</dd>
                      </div>
                    </dl>
                    {testimonials.length > 0 && (
                      <div className="mt-6 pt-5 border-t border-white/10">
                        <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Herkunft der Kundenstimmen</p>
                        <DonutChart
                          segments={[
                            { label: "Manuell erfasst", value: manualTestimonials, color: "#a3a1a6" },
                            { label: "Google", value: googleTestimonials, color: "#4285F4" },
                          ]}
                        />
                      </div>
                    )}
                  </Section>
                </>
              ),
            },
            {
              id: "marketing",
              label: "Marketing & Reichweite",
              content: (
                <>
                  <Section title="Seitenaufrufe & SEO">
                    <p className="text-xs text-[var(--rk-ink-muted)] mb-4">
                      Anonymer, first-party Zähler ohne Cookies/IP-Speicherung — läuft seit Einführung dieses Bereichs mit,
                      also am Anfang noch wenig Historie. Kein Ersatz für ein vollständiges Analytics-Tool, aber genug, um zu
                      sehen, welche Seiten laufen.
                    </p>
                    <dl className="grid grid-cols-2 sm:grid-cols-3 gap-4 text-sm mb-5">
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Aufrufe gesamt</dt>
                        <dd className="mt-1 text-base">{totalPageViews}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Letzte 30 Tage</dt>
                        <dd className="mt-1 text-base">{viewsLast30Days}</dd>
                      </div>
                      <div>
                        <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Indexierbar</dt>
                        <dd className={`mt-1 text-base ${seo?.indexable === false ? "text-red-400" : "text-emerald-400"}`}>
                          {seo?.indexable === false ? "Nein — Seite ist gesperrt" : "Ja"}
                        </dd>
                      </div>
                    </dl>

                    {dailyViews.some((d) => d.count > 0) ? (
                      <DayTrendChart data={dailyViews} />
                    ) : (
                      <p className="text-xs text-[var(--rk-ink-muted)]">
                        Noch keine Aufrufe erfasst — die Zählung läuft ab jetzt automatisch mit.
                      </p>
                    )}

                    {topPagesAgg.length > 0 && (
                      <div className="mt-6 pt-5 border-t border-white/10">
                        <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Meistaufgerufene Seiten</p>
                        <div className="flex flex-col gap-2">
                          {topPagesAgg.map((p) => (
                            <BarRow key={p._id} label={p._id} count={p.count} max={maxTopPageCount} />
                          ))}
                        </div>
                      </div>
                    )}

                    <div className="mt-6 pt-5 border-t border-white/10">
                      <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">
                        Conversion: Angebote-Aufrufe → Buchungen (30 Tage)
                      </p>
                      <dl className="grid grid-cols-2 sm:grid-cols-3 gap-4 text-sm">
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Angebote-Aufrufe</dt>
                          <dd className="mt-1 text-base">{angeboteViewsLast30}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Neue Anfragen</dt>
                          <dd className="mt-1 text-base">{newOrdersLast30}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Richtwert-Quote</dt>
                          <dd className="mt-1 text-base">
                            {angeboteConversionRate !== null ? `${angeboteConversionRate.toFixed(1)}%` : "—"}
                          </dd>
                        </div>
                      </dl>
                      <p className="mt-3 text-xs text-[var(--rk-ink-muted)]">
                        Bewusst nur eine grobe Näherung, kein echter Pro-Besucher-Trichter — die Seitenaufrufe sind
                        komplett anonym ohne Besucher-ID erfasst (siehe oben), lassen sich also nicht direkt einer
                        späteren Anfrage zuordnen. Zählt außerdem alle neuen Anfragen im Zeitraum, nicht nur die über
                        die Angebote-Seite gebuchten.
                      </p>
                    </div>

                    <div className="mt-6 pt-5 border-t border-white/10">
                      <p className="text-xs uppercase tracking-[0.1em] text-[var(--rk-ink-muted)] mb-3">Suchmaschinen-Status</p>
                      <dl className="grid grid-cols-2 sm:grid-cols-3 gap-4 text-sm">
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Google Search Console</dt>
                          <dd className="mt-1 text-base">{seo?.googleSiteVerification ? "Verifiziert" : "Nicht eingerichtet"}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Bing Webmaster Tools</dt>
                          <dd className="mt-1 text-base">{seo?.bingSiteVerification ? "Verifiziert" : "Nicht eingerichtet"}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Google Analytics</dt>
                          <dd className="mt-1 text-base">{seo?.googleAnalyticsId ? "Eingebunden" : "Nicht eingebunden"}</dd>
                        </div>
                      </dl>
                      <Link
                        href="/de/admin/seo"
                        className="mt-4 inline-block text-xs text-[var(--rk-ink-muted)] hover:text-[var(--rk-ink)] underline transition-colors"
                      >
                        SEO-Einstellungen →
                      </Link>
                    </div>
                  </Section>

                  {(conventions.length > 0 || waitlistEntries.length > 0) && (
                    <Section title="Conventions & Warteliste">
                      <dl className="grid grid-cols-2 sm:grid-cols-3 gap-4 text-sm">
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Anstehende Conventions</dt>
                          <dd className="mt-1 text-base">{upcomingConventions.length}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Warteliste gesamt</dt>
                          <dd className="mt-1 text-base">{waitlistEntries.length}</dd>
                        </div>
                        <div>
                          <dt className="text-xs text-[var(--rk-ink-muted)] uppercase tracking-[0.08em]">Davon benachrichtigt</dt>
                          <dd className="mt-1 text-base">{notifiedWaitlistCount}</dd>
                        </div>
                      </dl>
                    </Section>
                  )}
                </>
              ),
            },
          ]}
        />
    </main>
  );
}

function Section({ title, children }: { title: string; children: React.ReactNode }) {
  return (
    <section className="bg-[var(--rk-surface)] border border-white/10 rounded-2xl p-6">
      <h2 className="text-sm font-medium text-[var(--rk-ink)] mb-4">{title}</h2>
      {children}
    </section>
  );
}

function BarRow({ label, count, max }: { label: string; count: number; max: number }) {
  const pct = max > 0 ? Math.round((count / max) * 100) : 0;
  return (
    <div className="flex items-center gap-3 text-xs">
      <span className="w-44 shrink-0 text-[var(--rk-ink-muted)]">{label}</span>
      <div className="flex-1 h-2 bg-white/5 rounded-full overflow-hidden">
        <div className="h-full bg-white/30" style={{ width: `${pct}%` }} />
      </div>
      <span className="w-8 text-right">{count}</span>
    </div>
  );
}
