import React, { useEffect, useMemo, useState, useRef } from "react";
import {
  FiPlus,
  FiTrash2,
  FiEdit2,
  FiEye,
  FiPackage,
  FiCheckCircle,
  FiUploadCloud,
  FiDollarSign,
  FiX,
  FiSearch,
  FiCalendar,
} from "react-icons/fi";
import { getProducts, getDeliveries, createDeliveryBulk, importDeliveryInvoice, addLedgerEntry, getLedgerMe  } from "../../api";
import { createPortal } from "react-dom";

// ====== Format-/Rechen-Utils ===============================


const Th   = ({ children, className = "" }) => <th className={`text-left py-2 pr-4 ${className}`}>{children}</th>;
const Td   = ({ children, className = "" }) => <td className={`py-2 pr-4 ${className}`}>{children}</td>;
const Label= ({ children }) => <div className="text-xs text-white/60 mb-1">{children}</div>;

const inputCls = () =>
  "w-full px-3 py-2 rounded-xl border bg-white/10 text-gray-100 " +
  "border-gray-600 placeholder:text-gray-400 focus:outline-none focus:ring-2 focus:ring-gray-400/40";
const btnPrimary = (extra = "") =>
  `inline-flex items-center gap-2 px-4 py-2 rounded-xl bg-white/10 hover:bg-white/15 border border-white/10 text-white/90 ${extra}`;
const btnSecondary = (extra = "") =>
  `inline-flex items-center gap-2 px-4 py-2 rounded-xl bg-emerald-600/20 hover:bg-emerald-600/30 border border-emerald-600/30 text-emerald-200 ${extra}`;
const btnGhost = (extra = "") =>
  `inline-flex items-center gap-2 px-4 py-2 rounded-xl bg-white/5 hover:bg-white/10 border border-white/10 text-white/70 ${extra}`;
const disabledCls = (cond) => (cond ? "opacity-50 cursor-not-allowed" : "");


function euro(cents) {
  const v = (toInt(cents) / 100).toFixed(2);
  return `${v.replace(".", ",")} €`;
}
function euroInput(cents) {
  const v = (toInt(cents) / 100).toFixed(2);
  return v.replace(".", ",");
}
function centsFromInput(s) {
  if (typeof s !== "string") return toInt(s);
  const t = s.replace(/\s/g, "").replace(/,/g, ".");
  if (t === "") return 0;
  const n = Number(t);
  if (!isFinite(n)) return 0;
  return Math.round(n * 100);
}
function toInt(x) { return x == null || x === "" ? 0 : parseInt(x, 10) || 0; }
function todayISO() { return new Date().toISOString().slice(0, 10); }
function nextId(arr) { return arr.reduce((m, e) => Math.max(m, e.id || 0), 0) + 1; }

// =================================================================================================

// MwSt 19%
const VAT_NUM = 119;
const VAT_DEN = 100;
const APPLY_VAT_ON_DEPOSIT = true; // falls Pfand ohne MwSt: auf false setzen
function gross119(cents) { return Math.round(toInt(cents) * VAT_NUM / VAT_DEN); }
function netFromGross119(centsGross) { return Math.round(toInt(centsGross) * VAT_DEN / VAT_NUM); }


function ProductSelect({
  products = [],
  value,
  onChange,
  placeholder = "— Produkt wählen —",
  disabled = false,
}) {
  const [open, setOpen] = React.useState(false);
  const [q, setQ] = React.useState("");
  const [hi, setHi] = React.useState(0);
  const [pos, setPos] = React.useState({ top: 0, left: 0, width: 0 });
  const btnRef = React.useRef(null);
  const popRef = React.useRef(null);

  const fmt = new Intl.NumberFormat("de-DE", { minimumFractionDigits: 2, maximumFractionDigits: 2 });

  const options = React.useMemo(() => {
    const needle = q.trim().toLowerCase();
    const list = Array.isArray(products) ? products : [];
    if (!needle) return list;
    return list.filter(p => {
      const s = `${p.name || ""} ${p.category || ""} ${p.supplier_number || ""}`.toLowerCase();
      return s.includes(needle);
    });
  }, [products, q]);

  const selected = React.useMemo(
    () => (products || []).find(p => p.id === value),
    [products, value]
  );

  React.useEffect(() => {
    function onDoc(e) {
      if (!open) return;
      if (popRef.current?.contains(e.target)) return;
      if (btnRef.current?.contains(e.target)) return;
      setOpen(false);
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, [open]);

  // Position des Popovers relativ zum Button berechnen
  const measure = React.useCallback(() => {
    if (!btnRef.current) return;
    const r = btnRef.current.getBoundingClientRect();
    const vw = window.innerWidth;
    const left = Math.min(Math.max(8, r.left), Math.max(8, vw - r.width - 8));
    setPos({ top: r.bottom + 8, left, width: r.width });
  }, []);
  React.useLayoutEffect(() => {
    if (open) measure();
  }, [open, measure]);
  React.useEffect(() => {
    if (!open) return;
    const onResize = () => measure();
    const onScroll = () => measure();
    window.addEventListener("resize", onResize);
    window.addEventListener("scroll", onScroll, true);
    return () => {
      window.removeEventListener("resize", onResize);
      window.removeEventListener("scroll", onScroll, true);
    };
  }, [open, measure]);

  function onKey(e) {
    if (!open) return;
    if (e.key === "ArrowDown") {
      e.preventDefault(); setHi(i => Math.min(i + 1, Math.max(0, options.length - 1)));
    } else if (e.key === "ArrowUp") {
      e.preventDefault(); setHi(i => Math.max(i - 1, 0));
    } else if (e.key === "Enter") {
      e.preventDefault();
      const pick = options[hi];
      if (pick) { onChange?.(pick.id); setOpen(false); }
    } else if (e.key === "Escape") {
      e.preventDefault(); setOpen(false);
    }
  }

  return (
    <div className="relative" onKeyDown={onKey}>
      <button
        type="button"
        ref={btnRef}
        disabled={disabled}
        onClick={() => setOpen(o => !o)}
        className="w-full bg-black/40 text-white rounded-xl border border-white/20 px-3 py-2 text-left flex items-center justify-between hover:bg-white/5 disabled:opacity-50"
        aria-haspopup="listbox"
        aria-expanded={open}
      >
        <span className="truncate">
          {selected ? selected.name : <span className="text-white/50">{placeholder}</span>}
        </span>
        <span className="text-white/50">▾</span>
      </button>

      {open && createPortal(
        <div
          ref={popRef}
          className="fixed z-[1000]"
          style={{ top: pos.top, left: pos.left, width: pos.width }}
        >
          <div className="rounded-xl border border-white/15 bg-black/85 backdrop-blur p-2 shadow-2xl">
            <input
              autoFocus
              value={q}
              onChange={(e) => { setQ(e.target.value); setHi(0); }}
              placeholder="Produkt suchen…"
              className="w-full mb-2 bg-black/40 text-white rounded-lg border border-white/20 px-3 py-2"
            />

            <ul role="listbox" className="max-h-64 overflow-auto">
              {options.map((p, idx) => (
                <li
                  key={p.id}
                  role="option"
                  aria-selected={p.id === value}
                  onMouseEnter={() => setHi(idx)}
                  onMouseDown={(e) => { e.preventDefault(); onChange?.(p.id); setOpen(false); }}
                  className={`px-3 py-2 rounded-lg cursor-pointer grid grid-cols-[1fr_auto] gap-2
                    ${idx === hi ? "bg-white/10" : "hover:bg-white/5"}`}
                >
                  <div className="min-w-0">
                    <div className="truncate">{p.name}</div>
                    <div className="text-xs text-white/60 truncate">
                      {(p.category || "—")} • {p.volume_ml ? `${p.volume_ml} ml` : "—"} • Pack {p.pack_size ?? "—"}
                    </div>
                  </div>
                  <div className="text-right text-xs text-white/70">
                    {p.purchase_price_cents != null && (
                      <div>EK: {fmt.format((p.purchase_price_cents || 0)/100)} €</div>
                    )}
                    {p.price_cents != null && (
                      <div className="text-white/50">VK: {fmt.format((p.price_cents || 0)/100)} €</div>
                    )}
                  </div>
                </li>
              ))}
              {!options.length && <li className="px-3 py-2 text-white/60">Keine Treffer</li>}
            </ul>
          </div>
        </div>,
        document.body
      )}
    </div>
  );
}

// tolerant für "YYYY-MM-DD HH:MM:SS(.mmm)" etc.
function toISOish(s) {
  if (typeof s !== "string") return s;
  return s
    .replace(" ", "T")
    .replace(/(\.\d{3})\d+([Z+-])/, "$1$2")
    .replace(/([+-]\d{2})$/, "$1:00");
}
function parseTs(s) {
  const d = new Date(toISOish(s));
  return isNaN(d) ? null : d;
}
function fmtDate(x) {
  if (x instanceof Date) return x.toLocaleDateString();
  if (typeof x === "number") {
    // Sekunden → ms heuristisch
    const ms = x < 1e12 ? x * 1000 : x;
    const d = new Date(ms);
    return isNaN(d) ? "—" : d.toLocaleDateString();
  }
  if (typeof x === "string") {
    const d = parseTs(x);
    return d ? d.toLocaleDateString() : (x || "—");
  }
  return "—";
}
// 1) Utility einmalig ins File (z. B. unter den Date-Utils)
function normalizeLedger(raw) {
  const arr = Array.isArray(raw) ? raw : (raw?.items ?? []);
  return arr.map((e, i) => ({
    id: e.id ?? i,
    ts: e.ts || e.created_at || e.inserted_at || e.date, // <- Datum vereinheitlichen
    type: e.type || e.kind || e.entry_type || "booking",
    note: e.note ?? e.description ?? "",
    amount_cents: Number(e.amount_cents ?? e.amount ?? 0),
  }));
}

function packSizeOf(products, productId) {
  return (products.find(p => p.id === productId)?.pack_size ?? 1) | 0;
}
function lineUnits(it, products) {
  return (it.quantity_units | 0) * packSizeOf(products, it.product_id);
}
function lineSumCents(it, products) {
  return lineUnits(it, products) * (it.unit_cost_cents | 0);
}

export default function DeliveriesPage() {
  // Produkte aus Backend
  const [products, setProducts] = useState([]);
  useEffect(() => {
    (async () => {
      try {
        const data = await getProducts();
        setProducts(
          (data || []).map((p) => ({
            ...p,
            pack_size: Number(p.pack_size ?? 1),
            purchase_price_cents: Number(p.purchase_price_cents ?? 0),
            stock: Number(p.stock ?? 0),
          }))
        );
      } catch (e) {
        console.error(e);
        alert("Produkte konnten nicht geladen werden.");
      }
    })();
  },[]);

  useEffect(() => { if (products.length) loadHistory(); }, [products.length]);

  async function loadHistory() {
    try {
      const rows = await getDeliveries({ limit: 500, offset: 0 });
    
      const keyOf = (r) => {
        const date = (r.delivered_at || r.date || "").slice(0, 10);
        const inv  = r.invoice_number || r.invoice_no || r.invoice || "";
        const sup  = r.supplier || r.vendor || "";
        return `${date}|${sup}|${inv}`;
      };
    
      const byKey = new Map();
      for (const r of rows || []) {
        const key = keyOf(r);
        const g = byKey.get(key) || {
          // Gruppenkopf
          id: r.id, // irgendeine ID aus der Gruppe
          supplier: r.supplier || r.vendor || "",
          invoice_no: r.invoice_number || r.invoice_no || r.invoice || "",
          note: r.note || r.notes || r.comment || "",
          date: r.delivered_at || r.date || r.created_at || null,
          status: r.status || (r.paid_at ? "paid" : r.stored_at ? "stored" : "recorded"),
          deposit_return_cents: 0, // im aktuellen Backend nicht speicherbar
          items: [],
        };
      
        // Einzelzeile → Item bauen
        const pid = (r.product_id ?? r.pid) | 0;
        const ps  = (products.find(p => p.id === pid)?.pack_size | 0) || 1;
        const units = (r.amount | 0);                  // Stück gesamt (aus Backend)
        const qty   = Math.max(1, Math.round(units / ps)); // Menge in Packs schätzen
        const price = (r.price_cents | 0);             // Preis pro Stück (so legst du ihn an)
      
        g.items.push({
          product_id: pid,
          quantity_units: qty,
          unit_cost_cents: price,
        });
      
        byKey.set(key, g);
      }
    
      const groups = Array.from(byKey.values()).sort((a,b) => {
        const da = new Date(a.date || 0).getTime();
        const db = new Date(b.date || 0).getTime();
        return db - da;
      });
      setDeliveries(groups);
    } catch (e) {
      console.error(e);
    }
  }
  


  // Ledger / Kassenstand
  const [ledger, setLedger] = useState([]);
  useEffect(() => {
    (async () => {
      try {
        const raw = await getLedgerMe({ limit: 100 });
        setLedger(normalizeLedger(raw));
      } catch (err) {
        console.error("Ledger initial load failed:", err);
      }
    })();
  }, []);

  const walletBalance = React.useMemo(
  () => (ledger || []).reduce((s, e) => s + (e.amount_cents || 0), 0),
  [ledger]
  );

  // Lieferungen (Client-seitig als Liste für Historie)
  const [deliveries, setDeliveries] = useState([]);
  const [detailId, setDetailId] = useState(null);
  const [detailOpen, setDetailOpen] = useState(false);
  const detail = useMemo(
    () => deliveries.find((d) => d.id === detailId) || null,
    [deliveries, detailId]
  );
  useEffect(() => { if (detailId != null) setDetailOpen(true); }, [detailId]);

  // Formular Neue Lieferung
  const [form, setForm] = useState({
    supplier: "",
    date: todayISO(),
    invoice_no: "",
    note: "",
    // Neu: Pfand ist frei einzugeben (positiv oder negativ) und wird zum Gesamt addiert.
    deposit_return_cents: 0, // Netto in Cent; UI kann Brutto-Eingabe erlauben.
    items: [emptyItem()],
  });

  const sumItemsCents = useMemo(
    () => form.items.reduce((s, it) => s + (Number(it.quantity_units||0) * Number(it.unit_cost_cents||0)), 0),
    [form.items]
  );
  

  

  // Helpers ----------------------------------------------------------------------------------------

  function emptyItem() {
    return { product_id: null, quantity_units: 1, unit_cost_cents: 0 };
  }
  function productById(id) { return products.find((p) => p.id === id) || null; }
  function setItemField(idx, key, val) {
    setForm((prev) => ({
      ...prev,
      items: prev.items.map((it, i) => (i === idx ? { ...it, [key]: val } : it)),
    }));
  }
  function addItemRow() { setForm((prev) => ({ ...prev, items: [...prev.items, emptyItem()] })); }
  function removeItemRow(idx) {
    setForm((prev) => ({ ...prev, items: prev.items.filter((_, i) => i !== idx) }));
  }
  function onSelectProduct(idx, prodId) {
    const p = productById(toInt(prodId));
    setItemField(idx, "product_id", p?.id || null);
    if (p) setItemField(idx, "unit_cost_cents", toInt(p.purchase_price_cents));
  }

  // Speichern
  function resetForm() {
    setForm({
      supplier: "",
      date: todayISO(),
      invoice_no: "",
      note: "",
      deposit_return_cents: 0,
      items: [emptyItem()],
    });
  }

  async function saveDelivery() {
    if (!form.supplier.trim()) return alert("Lieferant fehlt");
    if (!form.items.length)    return alert("Mindestens eine Position erforderlich");

    for (const it of form.items) {
      if (!it.product_id)                return alert("Produkt wählen");
      if (toInt(it.quantity_units) < 1)  return alert("Menge ≥ 1");
      if (toInt(it.unit_cost_cents) < 0) return alert("Preis ≥ 0");
    }

    const payload = {
      supplier: form.supplier.trim(),
      date: form.date,
      invoice_no: form.invoice_no.trim(),
      note: form.note.trim(),
      // frei +/−; wird brutto in Summen berücksichtigt
      deposit_return_cents: toInt(form.deposit_return_cents),
      items: form.items.map(it => ({
        product_id: it.product_id,
        quantity_units: toInt(it.quantity_units),
        unit_cost_cents: toInt(it.unit_cost_cents),
      })),
    };

    try {
      // wichtig: products mitgeben → API rechnet Stück (packs×pack_size)
      await createDeliveryBulk(payload, products);   // 405/404? → api.js fällt automatisch auf Einzel-POSTs zurück
      await loadHistory();                           // echte Historie vom Backend
      resetForm();
    } catch (err) {
      console.error(err);
      alert(err.message || "Speichern fehlgeschlagen");
    }
  }


  // Einlagern: Bestand lokal erhöhen (Menge × pack_size)
  function storeDelivery(id) {
    setDeliveries((prev) =>
      prev.map((d) => (d.id === id ? { ...d, status: d.status === "recorded" ? "stored" : d.status } : d))
    );
    const d = deliveries.find((x) => x.id === id);
    if (!d || d.status !== "recorded") return;
    const deltas = aggregatedPiecesByProduct(d.items, products);
    setProducts((prev) => prev.map((p) => (deltas[p.id] ? { ...p, stock: toInt(p.stock) + deltas[p.id] } : p)));
  }

  async function payDelivery(deliveryId, totalCents) {
    try {
      const cents = Math.abs(Number(totalCents) | 0);
      await addLedgerEntry(-cents, `Lieferung #${deliveryId}`);
      const fresh = await getLedgerMe();
      setLedger(normalizeLedger(fresh));  
      setDeliveries(prev =>
        prev.map(d => (d.id === deliveryId ? { ...d, status: "paid" } : d))
      );
    } catch (e) {
      console.error(e);
      alert("Kassenbuchung fehlgeschlagen.");
    }
  }
  
  

  // ====================================== Render ================================================
  return (
    <div className="p-4 md:p-6 space-y-6">
      <header className="flex items-end justify-between">
        <div>
          <h1 className="text-xl md:text-2xl font-semibold text-white/90">Lieferungen </h1>
        </div>
      </header>

      {/* TOP: Neue Lieferung (links) + Kassenstand (rechts) */}
      <div className="grid grid-cols-1 lg:grid-cols-3 gap-5">
        <div className="lg:col-span-2 space-y-5">
          <Card>
            <CardHeader
              icon={<FiPlus />}
              title="Neue Lieferung"
              subtitle="Einheiten (Kisten/Packs) erfassen · Pfand wird addiert (Anzeige inkl. 19% MwSt)"
              right={<UploadInvoiceButton onImported={(draft) => applyDraftToForm(draft, setForm)} />}
            />
            <NewDeliveryForm
              products={products}
              form={form}
              setForm={setForm}
              sumItemsCents={sumItemsCents}
              onSave={saveDelivery}
            />
          </Card>
        </div>

        <div className="space-y-5">
          <Card>
            <CardHeader icon={<FiDollarSign />} title="Kassenstand" subtitle="Automatisch durch Zahlungen/Korrekturen" />
            <WalletCard
              balanceCents={walletBalance}
              ledger={ledger}
              onAdjust={async (amtCents, note) => {
                await addLedgerEntry(Number(amtCents) | 0, note || "Korrektur");
                const fresh = await getLedgerMe();
                setLedger(normalizeLedger(fresh));
              }}
            />
          </Card>
        </div>
      </div>

      {/* BOTTOM: Historie */}
      <Card>
        <CardHeader
          icon={<FiPackage />}
          title="Lieferungs-Historie"
          subtitle="Zuletzt erfasst – Recorded / Stored / Paid (Beträge inkl. 19% MwSt)"
        />
        <DeliveriesTable deliveries={deliveries} products={products} onView={(id) => setDetailId(id)} />
      </Card>

      {detail && (
        <Modal open={detailOpen} onClose={() => { setDetailOpen(false); setDetailId(null); }}>
          <DeliveryDetail
            delivery={detail}
            products={products}
            onStore={() => { storeDelivery(detail.id); }}
            onPay={(amountCents) => { payDelivery(detail.id, amountCents); }}   // ← geändert
          />
        </Modal>
      )}
      
    </div>
  );


// ======= Komponenten =====================================================================

function Card({ children }) {
  return (
    <div className="rounded-2xl bg-gradient-to-br from-white/5 to-white/10 border border-white/10 shadow-[0_8px_30px_rgba(0,0,0,0.25)]">
      {children}
    </div>
  );
}
function CardHeader({ icon, title, subtitle, right }) {
  return (
    <div className="flex items-center justify-between px-5 py-3 border-b border-white/10">
      <div className="flex items-center gap-3">
        <div className="p-2 rounded-xl bg-white/5 border border-white/10 text-white/80">{icon}</div>
        <div>
          <div className="text-white/90 font-semibold">{title}</div>
          {subtitle && <div className="text-xs text-white/60">{subtitle}</div>}
        </div>
      </div>
      {right}
    </div>
  );
}

function DeliveriesTable({ deliveries, products, onView }) {
  return (
    <div className="p-5 overflow-x-auto">
      <table className="min-w-full text-sm text-white/80">
        <thead className="text-white/60">
          <tr>
            <Th>Datum</Th>
            <Th>Lieferant</Th>
            <Th>Rechnungsnr.</Th>
            <Th className="text-right">Warensumme (inkl. MwSt)</Th>
            <Th className="text-right">Pfand (inkl. MwSt)</Th>
            <Th className="text-right">Gesamt</Th>
            <Th className="!text-center">Status</Th>
            <Th></Th>
          </tr>
        </thead>
        <tbody>
          {deliveries.length === 0 && (
            <tr>
              <td colSpan={8} className="py-10">
                <div className="flex flex-col items-center justify-center gap-2 text-white/60">
                  <div className="text-xl">Noch keine Lieferungen erfasst</div>
                  <div className="text-xs">Lege oben eine neue Lieferung an, sie erscheint dann hier.</div>
                </div>
              </td>
            </tr>
          )}
          {deliveries.map((d) => {
            const { sumItemsGross, depositGross, totalDue } = computeDeliverySums(d, products);
            return (
              <tr key={d.id} className="border-t border-white/10">
                <Td>{fmtDate(d.date)}</Td>
                <Td>{d.supplier || "—"}</Td>
                <Td>{d.invoice_no || "—"}</Td>
                <Td className="text-right font-mono">{euro(sumItemsGross)}</Td>
                <Td className="text-right font-mono">{euro(depositGross)}</Td>
                <Td className={`text-right font-mono ${totalDue < 0 ? "text-emerald-300" : ""}`}>{euro(totalDue)}</Td>
                <Td className="!text-center"><StatusPill status={d.status} /></Td>
                <Td className="text-right">
                  <button
                    onClick={() => onView(d.id)}
                    className="px-3 py-1.5 rounded-lg bg-white/10 hover:bg-white/15 text-white/80 inline-flex items-center gap-2"
                  >
                    <FiEye /> Anzeigen
                  </button>
                </Td>
              </tr>
            );
          })}
        </tbody>
      </table>
    </div>
  );
}

function StatusPill({ status }) {
  const map = {
    recorded: { label: "Erstellt", cls: "bg-yellow-500/15 text-yellow-200 border-yellow-500/30" },
    stored:   { label: "Eingelagert",   cls: "bg-blue-500/15 text-blue-200 border-blue-500/30" },
    paid:     { label: "Bezahlt",     cls: "bg-emerald-500/15 text-emerald-200 border-emerald-500/30" },
  };
  const s = map[status] || { label: String(status), cls: "bg-white/10 text-white/70 border-white/20" };
  return (
    <span className={`block w-fit mx-auto px-2.5 py-1 rounded-full text-xs border ${s.cls}`}>
      {s.label}
    </span>
  );
}

function NewDeliveryForm({ products, form, setForm, sumItemsCents, onSave }) {
  // Brutto (19%) – auf Warensumme UND Pfand
  const grossItems = gross119(sumItemsCents);

  // Pfand: frei einzugeben (±), Anzeige kann Brutto/Netto toggeln
  const [depositIsGross, setDepositIsGross] = useState(false);
  const displayDepositCents = depositIsGross ? gross119(form.deposit_return_cents) : toInt(form.deposit_return_cents);
  const grossDepositAdded = APPLY_VAT_ON_DEPOSIT ? gross119(form.deposit_return_cents) : toInt(form.deposit_return_cents);

  // Gesamt = Waren (brutto) + Pfand (brutto, kann negativ sein)
  const totalGross = grossItems + grossDepositAdded;
  const isCreditGross = totalGross < 0;

  return (
    <div className="p-5 space-y-4">
      <div className="grid md:grid-cols-2 gap-4">
        <LabeledInput
          label="Lieferant"
          value={form.supplier}
          onChange={(v) => setForm((prev) => ({ ...prev, supplier: v }))}
          placeholder="z. B. Getränke Mayer"
        />
        <DateField
          label="Datum"
          value={form.date}
          onChange={(v) => setForm((prev) => ({ ...prev, date: v }))}
        />
        <LabeledInput
          label="Rechnungsnr."
          value={form.invoice_no}
          onChange={(v) => setForm((prev) => ({ ...prev, invoice_no: v }))}
          placeholder="z. B. 2025-0812"
        />
        <LabeledMoney
          label="Pfand Summe"
          valueCents={displayDepositCents}
          onChangeCents={(typedCents) => {
            const net = depositIsGross ? netFromGross119(typedCents) : typedCents;
            setForm((prev) => ({ ...prev, deposit_return_cents: toInt(net) })); // kein Clamping -> auch negativ möglich
          }}
          allowNegative={true}
          hint={depositIsGross ? "Eingabe brutto – wird intern netto gespeichert (−19%)" : "Eingabe netto – Anzeige & Summen inkl. 19% MwSt"}
          rightToggle={{
            labelOn: "Brutto",
            labelOff: "Netto",
            value: depositIsGross,
            onChange: setDepositIsGross,
          }}
        />
      </div>

      <div className="rounded-xl border border-white/10 overflow-hidden">
        <div className="px-4 py-2 text-white/70 bg-white/5 border-b border-white/10">Produkte</div>
        <div className="divide-y divide-white/10">
          {form.items.map((it, idx) => {
            const p = products.find((pp) => pp.id === it.product_id) || null;
            const pieces = p ? toInt(it.quantity_units) * toInt(p.pack_size) : 0;
            return (
              <div key={idx} className="p-4 grid grid-cols-1 md:grid-cols-12 gap-3 items-end">
                <div className="md:col-span-4">
                  <label className="block text-xs text-white/60 mb-1">Produkt</label>
                  <ProductSelect
                    products={products}           
                    value={it.product_id}
                    onChange={(id) => {
                      const p = products.find(pp => pp.id === id);
                      const patch = { product_id: id };
                      if (!(it.unit_cost_cents > 0) && p?.purchase_price_cents != null) {
                        patch.unit_cost_cents = p.purchase_price_cents;
                      }
                      updateItemField(idx, patch, setForm); 
                    }}
                    placeholder="— Produkt wählen —"
                  />
                </div>
                <div className="md:col-span-2">
                  <Label>Menge (Einheiten)</Label>
                  <input
                    type="number"
                    min={1}
                    value={it.quantity_units}
                    onChange={(e) =>
                      updateItemField(idx, { quantity_units: toInt(e.target.value) }, setForm)
                    }
                    className={inputCls()}
                  />
                </div>
                <div className="md:col-span-3">
                  <Label>Einzelpreis/Einheit (€)</Label>
                  <input
                    inputMode="decimal"
                    value={euroInput(it.unit_cost_cents)}
                    onChange={(e) =>
                      updateItemField(idx, { unit_cost_cents: centsFromInput(e.target.value) }, setForm)
                    }
                    className={inputCls()}
                  />
                </div>
                <div className="md:col-span-2 text-right">
                  <div className="text-xs text-white/50 mb-1">Stück gesamt</div>
                  <div className="font-mono text-white/80">{pieces}</div>
                </div>
                <div className="md:col-span-12 flex justify-between items-center">
                  <div className="text-xs text-white/50">
                    Zeilensumme:{" "}
                    <span className="font-mono text-white/80">
                      {euro((toInt(it.quantity_units)) * toInt(it.unit_cost_cents))}
                    </span>
                  </div>
                  <button
                    onClick={() => removeItemRowHandler(idx, setForm)}
                    className="px-2 py-1.5 rounded-lg bg-white/10 hover:bg-white/15 text-red-300 inline-flex items-center gap-2"
                  >
                    <FiTrash2 /> entfernen
                  </button>
                </div>
              </div>
            );
          })}
        </div>
        <div className="p-4 border-t border-white/10 bg-white/5">
          <button
            onClick={() => addItemRowHandler(setForm)}
            className="px-3 py-2 rounded-lg bg-white/10 hover:bg-white/15 text-white/80 inline-flex items-center gap-2"
          >
            <FiPlus /> Produkte hinzufügen
          </button>
        </div>
      </div>

      <div className="grid md:grid-cols-2 gap-4 items-start">
        <LabeledTextArea
          label="Notiz"
          value={form.note}
          onChange={(v) => setForm((prev) => ({ ...prev, note: v }))}
          placeholder="optional"
          rows={3}
        />

        <div className="rounded-xl border border-white/10 p-4 bg-gradient-to-b from-white/5 to-transparent">
          <div className="text-white/60 text-sm mb-2">Summen</div>
          <div className="flex justify-between py-1 text-white/80">
            <span>Warensumme (inkl. MwSt)</span>
            <span className="font-mono">{euro(grossItems)}</span>
          </div>
          <div className="flex justify-between py-1 text-white/80">
            <span>Pfand (inkl. MwSt)</span>
            <span className="font-mono">{euro(grossDepositAdded)}</span>
          </div>
          <div className={`flex justify-between py-1 border-t border-white/10 mt-2 pt-2 ${isCreditGross ? "text-emerald-300" : "text-white"}`}>
            <span>{isCreditGross ? "Gutschrift (Gesamt)" : "Gesamtbetrag"}</span>
            <span className="font-mono">{euro(totalGross)}</span>
          </div>
          <div className="mt-3 flex items-center justify-end gap-2">
            <button onClick={onSave} className={btnPrimary()}>
              <FiCheckCircle /> Speichern
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

function WalletCard({ balanceCents, ledger, onAdjust }) {
  const [adj, setAdj] = useState({ amount: "", note: "" });
  const [showAdj, setShowAdj] = useState(false);
  const [range, setRange] = useState("7d"); // "7d" | "30d" | "all"

  const series = useMemo(() => computeBalanceSeries(ledger, range), [ledger, range]);

  return (
    <div className="p-5 space-y-4">
      <div className="flex items-center justify-between">
        <div>
          <div className="text-white/60 text-sm">Aktueller Kassenstand</div>
          <div className="text-3xl font-semibold tracking-tight text-white">{euro(balanceCents)}</div>
        </div>
        <div className="flex items-center gap-2">
          <RangeSwitch value={range} onChange={setRange} />
          <button
            onClick={() => setShowAdj((v) => !v)}
            className="p-2 rounded-xl bg-white/5 hover:bg-white/10 border border-white/10 text-white/80"
            aria-label="Korrektur buchen ein-/ausklappen"
            aria-expanded={showAdj}
            title="Korrektur buchen"
          >
            <FiEdit2 />
          </button>
        </div>
      </div>

      {/* Chart */}
      <div className="rounded-xl border border-white/10 p-3 bg-white/5">
        <BalanceChart series={series} />
      </div>

      {showAdj && (
        <div className="rounded-xl border border-white/10 p-3 bg-white/5">
          <div className="text-white/70 text-sm mb-2">Korrektur buchen</div>
          <div className="grid grid-cols-1 gap-2">
            <input
              placeholder="Betrag in € (z. B. 12,34 oder −5)"
              value={adj.amount}
              onChange={(e) => setAdj((v) => ({ ...v, amount: e.target.value }))}
              className={inputCls()}
            />
            <input
              placeholder="Notiz (Pflicht)"
              value={adj.note}
              onChange={(e) => setAdj((v) => ({ ...v, note: e.target.value }))}
              className={inputCls()}
            />
            <button
              onClick={() => {
                const c = centsFromInput(adj.amount);
                if (!adj.note.trim()) return alert("Notiz erforderlich");
                onAdjust(c, adj.note.trim());
                setAdj({ amount: "", note: "" });
                setShowAdj(false);
              }}
              className="px-3 py-2 rounded-lg bg-white/10 hover:bg-white/15 text-white/80 inline-flex items-center gap-2"
            >
              <FiEdit2 /> Buchen
            </button>
          </div>
        </div>
      )}

      <div>
        <div className="text-white/60 text-sm mb-2">Letzte Buchungen</div>
        <div className="rounded-xl border border-white/10 overflow-hidden">
          <table className="min-w-full text-sm text-white/80">
            <thead className="bg-white/5 text-white/60">
              <tr>
                <Th>Datum</Th>
                <Th>Typ</Th>
                <Th>Notiz</Th>
                <Th className="text-right">Betrag</Th>
              </tr>
            </thead>
            <tbody>
              {ledger.slice(0, 5).map((e) => (
                <tr key={e.id} className="border-t border-white/10">
                  <Td className="whitespace-nowrap">{fmtDate(e.ts)}</Td>
                  <Td>{ledgerTypeLabel(e.type)}</Td>
                  <Td>{e.note || "—"}</Td>
                  <Td
                    className={`text-right font-mono ${
                      e.amount_cents < 0 ? "text-red-300" : e.amount_cents > 0 ? "text-emerald-300" : ""
                    }`}
                  >
                    {euro(e.amount_cents)}
                  </Td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function DeliveryDetail({ delivery, products, onStore, onPay }) {
  const { sumItemsGross, depositGross, totalDue } = computeDeliverySums(delivery, products);

  const rows = (delivery.items || []).map((it) => {
    const p     = products.find((pp) => pp.id === it.product_id) || { name: it.product_id, pack_size: 1 };
    const qty   = toInt(it.quantity_units);      // Einheiten (Kisten/Packs)
    const unit  = toInt(it.unit_cost_cents);     // Preis pro Einheit (Cent)
    const pieces= qty * toInt(p.pack_size);      // Stück gesamt (Flaschen/Dosen)
    const line  = qty * unit;                    // Zeilensumme (Cent)
    return { p, qty, pieces, unit, line };
  });


  return (
    <div className="w-full">
      <div className="rounded-2xl border border-white/10 overflow-hidden bg-slate-900">
        {/* Header */}
        <div className="px-5 py-3 bg-white/5 border-b border-white/10 flex items-center justify-between">
          <div className="min-w-0">
            <div className="text-white/90 font-semibold truncate">Lieferung #{delivery.id}</div>
            <div className="text-xs text-white/60 truncate">
              {fmtDate(delivery.date)} · {delivery.supplier || "—"} · RG {delivery.invoice_no || "—"}
            </div>
          </div>
          <StatusPill status={delivery.status} />
        </div>

        {/* Body */}
        <div className="p-5 space-y-4">
          <div className="rounded-xl border border-white/10 overflow-hidden">
            <div className="overflow-x-auto">
              <table className="min-w-[760px] w-full table-fixed text-sm text-white/80">
                <colgroup>
                  <col className="w-[40%]" />
                  <col className="w-[10%]" />
                  <col className="w-[14%]" />
                  <col className="w-[14%]" />
                  <col className="w-[11%]" />
                  <col className="w-[11%]" />
                </colgroup>
                <thead className="bg-white/5 text-white/60">
                  <tr>
                    <Th>Produkt</Th>
                    <Th className="text-right">Pack</Th>
                    <Th className="text-right">Menge</Th>
                    <Th className="text-right">Stück gesamt</Th>
                    <Th className="text-right">Einzelpreis (€)</Th>
                    <Th className="text-right">Zeilensumme</Th>
                  </tr>
                </thead>
                <tbody>
                  {rows.map((r, i) => (
                    <tr key={i} className="border-t border-white/10">
                      <Td className="truncate">{r.p.name}</Td>
                      <Td className="text-right font-mono">{r.p.pack_size}</Td>
                      <Td className="text-right font-mono">{r.qty}</Td>
                      <Td className="text-right font-mono">{r.pieces}</Td>
                      <Td className="text-right font-mono">{euro(r.unit)}</Td>
                      <Td className="text-right font-mono">{euro(r.line)}</Td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          <div className="grid md:grid-cols-2 gap-4 items-start">
            <div className="rounded-xl border border-white/10 p-4 bg-white/5 min-h-[92px]">
              <div className="text-white/60 text-sm mb-1">Notiz</div>
              <div className="text-white/80 text-sm whitespace-pre-wrap">{delivery.note || "—"}</div>
            </div>
            <div className="rounded-xl border border-white/10 p-4 bg-gradient-to-b from-white/5 to-transparent">
              <div className="flex justify-between py-1 text-white/80">
                <span>Warensumme (inkl. MwSt)</span>
                <span className="font-mono">{euro(sumItemsGross)}</span>
              </div>
              <div className="flex justify-between py-1 text-white/80">
                <span>Pfand (inkl. MwSt)</span>
                <span className="font-mono">{euro(depositGross)}</span>
              </div>
              <div
                className={`flex justify-between py-1 border-t border-white/10 mt-2 pt-2 ${
                  totalDue < 0 ? "text-emerald-300" : "text-white"
                }`}
              >
                <span>{totalDue < 0 ? "Gutschrift (Gesamt)" : "Gesamtbetrag"}</span>
                <span className="font-mono">{euro(totalDue)}</span>
              </div>
            </div>
          </div>
        </div>

        {/* Footer */}
        <div className="px-5 py-3 bg-white/5 border-t border-white/10 flex flex-wrap gap-3 justify-end">
          <button
            disabled={delivery.status !== "recorded"}
            onClick={onStore}
            className={btnPrimary(disabledCls(delivery.status !== "recorded"))}
          >
            <FiPackage /> Einlagern
          </button>
          <button
            disabled={delivery.status === "paid"}
            onClick={() => onPay(totalDue)}
            className={btnSecondary(disabledCls(delivery.status === "paid"))}
          >
            <FiCheckCircle /> Als bezahlt markieren
          </button>
        </div>
      </div>
    </div>
  );
}

// ======= UI-/Format-Helper ========================================================================

function Modal({ open, onClose, children }) {
  useEffect(() => {
    if (!open) return;
    const prev = document.body.style.overflow;
    document.body.style.overflow = "hidden";
    const onKey = (e) => e.key === "Escape" && onClose?.();
    window.addEventListener("keydown", onKey);
    return () => {
      document.body.style.overflow = prev;
      window.removeEventListener("keydown", onKey);
    };
  }, [open, onClose]);
  if (!open) return null;
  return (
    <div className="fixed inset-0 z-[9999]">
      <div className="absolute inset-0 bg-black/60" onClick={onClose} />
      <div className="absolute inset-0 p-4 md:p-6 flex items-center justify-center">
        <div className="relative w-full max-w-[920px] rounded-2xl bg-slate-900 border border-cyan-400/20 shadow-xl">
          <button
            onClick={onClose}
            className="absolute right-2 top-2 p-2 rounded hover:bg-white/10 text-white/70"
            aria-label="Schließen"
          >
            <FiX />
          </button>
          <div className="p-5">{children}</div>
        </div>
      </div>
    </div>
  );
}

function LabeledInput({ label, type = "text", value, onChange, placeholder }) {
  return (
    <div>
      <Label>{label}</Label>
      <input
        type={type}
        value={value}
        placeholder={placeholder}
        onChange={(e) => onChange(e.target.value)}
        className={inputCls()}
      />
    </div>
  );
}
function LabeledTextArea({ label, value, onChange, placeholder, rows = 3 }) {
  return (
    <div>
      <Label>{label}</Label>
      <textarea
        value={value}
        placeholder={placeholder}
        rows={rows}
        onChange={(e) => onChange(e.target.value)}
        className={inputCls()}
      />
    </div>
  );
}

// Geld-Eingabe mit optionaler Brutto/Netto-Umschaltung
function LabeledMoney({ label, valueCents, onChangeCents, allowNegative = false, hint, rightToggle }) {
  const clamp = (n) => (allowNegative ? n : Math.max(0, n));
  return (
    <div>
      <div className="flex items-center justify-between mb-1">
        <Label>{label}</Label>
        {rightToggle && (
          <ToggleSwitch
            value={!!rightToggle.value}
            onChange={rightToggle.onChange}
            onLabel={rightToggle.labelOn || "An"}
            offLabel={rightToggle.labelOff || "Aus"}
          />
        )}
      </div>
      <input
        inputMode="decimal"
        value={euroInput(valueCents)}
        onChange={(e) => onChangeCents(clamp(centsFromInput(e.target.value)))}
        className={inputCls()}
        placeholder="0,00"
      />
      {hint && <div className="text-[11px] text-white/50 mt-1">{hint}</div>}
    </div>
  );
}

function ToggleSwitch({ value, onChange, onLabel = "An", offLabel = "Aus" }) {
  return (
    <button
      type="button"
      onClick={() => onChange(!value)}
      className={`text-xs px-2 py-1 rounded-full border ${value ? "bg-white/15 border-white/25 text-white/90" : "bg-white/5 border-white/15 text-white/60"}`}
      aria-pressed={value}
    >
      {value ? onLabel : offLabel}
    </button>
  );
}

// Vereinfachte Date-UI ohne Links/Rechts-Buttons
function DateField({ label, value, onChange }) {
  return (
    <div>
      <Label>{label}</Label>
      <div className="relative">
        <input
          type="date"
          value={value}
          onChange={(e) => onChange(e.target.value)}
          className={`${inputCls()} pr-10`}
        />
        <FiCalendar className="absolute right-3 top-1/2 -translate-y-1/2 text-white/50 pointer-events-none" />
      </div>
    </div>
  );
}

// Durchsuchbare Produktauswahl (Combobox)
function ProductCombo({ products, valueId, onChangeId }) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState("");
  const wrapRef = useRef(null);

  useEffect(() => {
    const sel = products.find((p) => p.id === valueId);
    setQ(sel ? sel.name : "");
  }, [valueId, products]);

  useEffect(() => {
    function onDoc(e) {
      if (!wrapRef.current) return;
      if (!wrapRef.current.contains(e.target)) setOpen(false);
    }
    document.addEventListener("mousedown", onDoc);
    return () => document.removeEventListener("mousedown", onDoc);
  }, []);

  const normalized = (s) => String(s || "").toLowerCase();
  const items = useMemo(() => {
    const s = normalized(q);
    const base = products || [];
    if (!s) return base.slice(0, 50);
    return base
      .filter((p) =>
        [p.name, p.category, p.supplier_number, p.pack_size]
          .map(normalized)
          .some((v) => v.includes(s))
      )
      .slice(0, 50);
  }, [q, products]);

  return (
    <div className="relative" ref={wrapRef}>
      <div className="relative">
        <input
          value={q}
          onChange={(e) => { setQ(e.target.value); setOpen(true); }}
          onFocus={() => setOpen(true)}
          placeholder="Produkt suchen…"
          className={`${inputCls()} pl-9`}
        />
        <FiSearch className="absolute left-3 top-1/2 -translate-y-1/2 text-white/50 pointer-events-none" />
      </div>
      {open && (
        <div className="absolute z-50 mt-1 w-full max-h-56 overflow-auto rounded-xl border border-white/10 bg-slate-900 shadow-xl">
          {items.length === 0 ? (
            <div className="px-3 py-2 text-sm text-white/50">Kein Treffer</div>
          ) : (
            items.map((p) => (
              <button
                key={p.id}
                type="button"
                onClick={() => { onChangeId(p.id); setOpen(false); }}
                className="w-full text-left px-3 py-2 text-sm hover:bg-white/10 text-white/80"
                title={`Pack ${p.pack_size}${p.category ? ` · ${p.category}` : ""}`}
              >
                <div className="flex items-baseline justify-between gap-3">
                  <span className="truncate">{p.name}</span>
                  <span className="text-xs text-white/50 shrink-0">Pack {p.pack_size}</span>
                </div>
              </button>
            ))
          )}
        </div>
      )}
    </div>
  );
}

// Kassenstand-Chart & Series
function RangeSwitch({ value, onChange }) {
  const opt = [
    { v: "7d", label: "7T" },
    { v: "30d", label: "30T" },
    { v: "all", label: "Immer" },
  ];
  return (
    <div className="inline-flex rounded-xl border border-white/10 bg-white/5 overflow-hidden">
      {opt.map((o, i) => (
        <button
          key={o.v}
          onClick={() => onChange(o.v)}
          className={`px-3 py-1.5 text-sm ${value === o.v ? "bg-white/15 text-white/90" : "text-white/70 hover:bg-white/10"} ${i>0?"border-l border-white/10":""}`}
        >
          {o.label}
        </button>
      ))}
    </div>
  );
}

function BalanceChart({ series }) {
  if (!series || series.length === 0) {
    return <div className="text-white/50 text-sm">Keine Daten für den Zeitraum.</div>;
  }
  const W = 600, H = 160, PAD = 18;

  const ys = series.map((p) => p.y);
  let minY = Math.min(...ys);
  let maxY = Math.max(...ys);
  if (minY === maxY) {
    const pad = Math.max(100, Math.abs(maxY) * 0.05);
    minY -= pad; maxY += pad;
  } else {
    const span = maxY - minY;
    const pad = Math.max(50, span * 0.1);
    minY -= pad; maxY += pad;
  }

  const x = (i) => PAD + (i * (W - 2 * PAD)) / (series.length - 1 || 1);
  const y = (v) => PAD + (H - 2 * PAD) * (1 - (v - minY) / (maxY - minY));

  const path = series.reduce((acc, p, i) => {
    const cmd = `${i === 0 ? "M" : "L"} ${x(i).toFixed(2)} ${y(p.y).toFixed(2)}`;
    return acc + (i ? " " : "") + cmd;
  }, "");
  const area = `${path} L ${x(series.length - 1).toFixed(2)} ${y(minY).toFixed(2)} L ${x(0).toFixed(2)} ${y(minY).toFixed(2)} Z`;

  const zeroInRange = minY < 0 && maxY > 0;
  const zeroY = y(0);
  const first = series[0];
  const last = series[series.length - 1];

  return (
    <div className="w-full">
      <svg viewBox={`0 0 ${W} ${H}`} className="w-full h-[180px]">
        <defs>
          <linearGradient id="balGrad" x1="0" y1="0" x2="0" y2="1">
            <stop offset="0%" stopOpacity="0.35" stopColor="currentColor" />
            <stop offset="100%" stopOpacity="0.02" stopColor="currentColor" />
          </linearGradient>
        </defs>

        {zeroInRange && (
          <line x1={PAD} x2={W - PAD} y1={zeroY} y2={zeroY} stroke="currentColor" opacity="0.25" strokeDasharray="4 4" />
        )}

        <path d={area} fill="url(#balGrad)" className="text-white" />
        <path d={path} fill="none" stroke="currentColor" strokeWidth="2" className="text-white/80" />
        <circle cx={x(series.length - 1)} cy={y(last.y)} r="3.5" className="text-white" fill="currentColor" />

        <text x={PAD} y={H - 4} fontSize="10" fill="currentColor" opacity="0.6">{fmtDateShort(first.date)}</text>
        <text x={W - PAD} y={H - 4} fontSize="10" fill="currentColor" opacity="0.6" textAnchor="end">
          {fmtDateShort(last.date)}
        </text>
        <text x={W - PAD} y={PAD + 10} fontSize="10" fill="currentColor" opacity="0.6" textAnchor="end">
          {euro(maxY)}
        </text>
        <text x={W - PAD} y={H - PAD + 10} fontSize="10" fill="currentColor" opacity="0.6" textAnchor="end">
          {euro(minY)}
        </text>
      </svg>
    </div>
  );
}

function computeDeliverySums(delivery, products) {
  const VAT = 0.19;
  const gross119 = (c) => Math.round(c * (1 + VAT));

  // Netto Warensumme: Einheiten × Preis/Einheit
  const sumItemsNet = (delivery.items || [])
    .reduce((s, it) => s + Number(it.quantity_units||0) * Number(it.unit_cost_cents||0), 0);

  const sumItemsGross = gross119(sumItemsNet);
  const depositGross  = gross119(Number(delivery.deposit_return_cents||0));
  const totalDue      = sumItemsGross + depositGross;

  return { sumItemsGross, depositGross, totalDue };
}


function aggregatedPiecesByProduct(items, products) {
  const map = {};
  for (const it of items) {
    const p = products.find((pp) => pp.id === it.product_id);
    if (!p) continue;
    const pieces = toInt(it.quantity_units) * toInt(p.pack_size);
    map[p.id] = (map[p.id] || 0) + pieces;
  }
  return map;
}
function ledgerTypeLabel(t) {
  switch (t) {
    case "adjustment": return "Korrektur";
    case "delivery_payment": return "Lieferung bezahlt";
    case "topup": return "Aufladung";
    case "booking": return "Buchung";
    default: return t;
  }
}

// Date-Utils
function fmtDateShort(d) {
  try {
    const dt = new Date(d);
    return dt.toLocaleDateString(undefined, { day: "2-digit", month: "2-digit" });
  } catch { return String(d || ""); }
}
function startOfDay(d) { const x = new Date(d); x.setHours(0,0,0,0); return x; }
function endOfDay(d) { const x = new Date(d); x.setHours(23,59,59,999); return x; }
function addDays(d, n) { const x = new Date(d); x.setDate(x.getDate() + n); return x; }

// Baut eine Tages-Zeitreihe des Kassenstands aus dem Ledger
function computeBalanceSeries(ledger, range = "7d") {
  const entries = (ledger || [])
    .map(e => ({ ...e, dt: new Date(e.ts || e.created_at || e.inserted_at || e.date || Date.now()) }))
    .filter(e => !isNaN(e.dt.getTime()))
    .sort((a, b) => a.dt - b.dt);

  if (entries.length === 0) return [];

  const today = startOfDay(new Date());
  let start;
  if (range === "7d") start = addDays(today, -6);        // inkl. heute -> 7 Punkte
  else if (range === "30d") start = addDays(today, -29); // inkl. heute -> 30 Punkte
  else start = startOfDay(entries[0].dt);                // "all": ab der ersten Buchung

  // Startsaldo: alle Buchungen vor dem Start aufsummieren
  let balance = entries.reduce((s, e) => (e.dt < start ? s + (e.amount_cents || 0) : s), 0);

  // Index auf erste relevante Buchung schieben
  let i = 0;
  while (i < entries.length && entries[i].dt < start) i++;

  const series = [];
  for (let d = new Date(start); d <= today; d = addDays(d, 1)) {
    const dayEnd = endOfDay(d);
    // alle Buchungen dieses Tages addieren
    while (i < entries.length && entries[i].dt <= dayEnd) {
      balance += entries[i].amount_cents || 0;
      i++;
    }
    series.push({ date: new Date(d), y: balance });
  }

  return series;
}


// Form-Handler ausgelagert
function onSelectProductHandlerId(id, idx, products, setForm) {
  const p = products.find((pp) => pp.id === toInt(id));
  setForm((prev) => ({
    ...prev,
    items: prev.items.map((it, i) =>
      i === idx
        ? {
            ...it,
            product_id: p ? p.id : null,
            unit_cost_cents: p ? toInt(p.purchase_price_cents) : 0,
          }
        : it
    ),
  }));
}

function updateItemField(idx, patch, setForm) {
  setForm(prev => ({
    ...prev,
    items: prev.items.map((x, i) => (i === idx ? { ...x, ...patch } : x)),
  }));
}
function addItemRowHandler(setForm) {
  setForm(prev => ({ ...prev, items: [...prev.items, { product_id: null, quantity_units: 1, unit_cost_cents: 0 }] }));
}
function removeItemRowHandler(idx, setForm) {
  setForm(prev => ({ ...prev, items: prev.items.filter((_, i) => i !== idx) }));
}


function UploadInvoiceButton({ onImported }) {
  const [busy, setBusy] = useState(false);
  const inputId = "invoicePdfInput";

  async function onFile(e) {
    const file = e.target.files?.[0];
    if (!file) return;
    try {
      setBusy(true);
      const draft = await importDeliveryInvoice(file);
      onImported?.(draft);
    } catch (err) {
      console.error(err);
      alert("PDF-Import fehlgeschlagen.");
    } finally {
      setBusy(false);
      e.target.value = "";
    }
  }

  return (
    <div className="flex items-center">
      <input id={inputId} type="file" accept="application/pdf" className="hidden" onChange={onFile} />
      <label
        htmlFor={inputId}
        className={`inline-flex items-center gap-2 px-3 py-2 rounded-xl border border-white/10
                    ${busy ? "opacity-60 cursor-wait" : "cursor-pointer bg-white/10 hover:bg-white/15 text-white/80"}`}
      >
        <FiUploadCloud />
        {busy ? "Importiere…" : "PDF importieren"}
      </label>
    </div>
  );
}

// Draft → Formular übernehmen
  function applyDraftToForm(draft, setForm) {
    setForm((prev) => ({
      ...prev,
      supplier: (draft?.supplier ?? prev.supplier) || "",
      date: draft?.date ?? todayISO(),
      invoice_no: (draft?.invoice_no ?? prev.invoice_no) || "",
      note: draft?.note ?? prev.note ?? "",
      deposit_return_cents: toInt(draft?.deposit_return_cents),
      items:
        Array.isArray(draft?.items) && draft.items.length
          ? draft.items.map((it) => ({
              product_id: it.product_id ?? null,
              quantity_units: toInt(it.quantity_units) || 1,
              unit_cost_cents: toInt(it.unit_cost_cents) || 0,
            }))
          : prev.items,
    }));
  }
}