// Reports — Loyverse-style admin reporting (summary, by item/category/employee/
// payment, receipts, shifts) with a date-range filter and bar chart.

function AdminReports() {
  const { db } = usePOS();
  const [section, setSection] = React.useState("summary");
  const [range, setRange] = React.useState(() => {
    const to = new Date();
    const from = new Date(); from.setDate(from.getDate() - 6);
    return { from: from.toISOString().slice(0, 10), to: to.toISOString().slice(0, 10) };
  });
  const [orders, setOrders] = React.useState([]);
  const [shifts, setShifts] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  // Fetch once per range change.
  React.useEffect(() => {
    let cancelled = false;
    setLoading(true);
    Promise.all([
      db.collection("orders")
        .where("dateKey", ">=", range.from)
        .where("dateKey", "<=", range.to).get(),
      db.collection("shifts")
        .where("dateKey", ">=", range.from)
        .where("dateKey", "<=", range.to).get(),
    ]).then(([o, s]) => {
      if (cancelled) return;
      setOrders(o.docs.map((d) => ({ id: d.id, ...d.data() })));
      setShifts(s.docs.map((d) => ({ id: d.id, ...d.data() })));
      setLoading(false);
    });
    return () => { cancelled = true; };
  }, [range.from, range.to]);

  // Only paid orders count as "sales"; unpaid open bills are excluded.
  const paid = orders.filter((o) => o.paid !== false);

  const grossSales = paid.reduce((s, o) =>
    s + o.items.reduce((a, i) => a + (i.price + (i.modPrice || 0)) * i.qty, 0), 0);
  const discounts = paid.reduce((s, o) => s + (o.discount || 0) + (o.depositApplied || 0), 0);
  const refunds = paid.reduce((s, o) => s + (o.refundedAmount || 0), 0);
  const netSales = paid.reduce((s, o) => s + (o.total || 0), 0) - refunds;
  const cogsTotal = paid.reduce((s, o) =>
    s + o.items.reduce((a, i) => a + (i.cogs || 0) * i.qty, 0), 0);
  const grossProfit = netSales - cogsTotal;

  const presetRange = (days) => {
    const to = new Date();
    const from = new Date(); from.setDate(from.getDate() - (days - 1));
    setRange({ from: from.toISOString().slice(0, 10), to: to.toISOString().slice(0, 10) });
  };

  const SECTIONS = [
    { id: "summary",  label: "Sales summary" },
    { id: "byItem",   label: "Sales by item" },
    { id: "byCat",    label: "Sales by category" },
    { id: "byEmp",    label: "Sales by employee" },
    { id: "byPay",    label: "Sales by payment type" },
    { id: "byMod",    label: "Sales by modifier" },
    { id: "receipts", label: "Receipts" },
    { id: "shifts",   label: "Shifts" },
  ];

  return (
    <div className="admin-pane reports-pane">
      <header className="pane-head">
        <div>
          <div className="eyebrow mono">REPORTS · {range.from} → {range.to}</div>
          <h2>{SECTIONS.find((s) => s.id === section).label}</h2>
        </div>
        <div className="row" style={{ gap: 6, flexWrap: "wrap", justifyContent: "flex-end" }}>
          {[
            { label: "Today",     d: 1 },
            { label: "Last 7d",   d: 7 },
            { label: "Last 30d",  d: 30 },
            { label: "Last 90d",  d: 90 },
          ].map((p) => <button key={p.d} className="btn-ghost-sm" onClick={() => presetRange(p.d)}>{p.label}</button>)}
          <input type="date" value={range.from} max={range.to} onChange={(e) => setRange({ ...range, from: e.target.value })} style={{ maxWidth: 160 }} />
          <input type="date" value={range.to} min={range.from} onChange={(e) => setRange({ ...range, to: e.target.value })} style={{ maxWidth: 160 }} />
        </div>
      </header>

      <div className="reports-layout">
        <aside className="reports-rail">
          {SECTIONS.map((s) => (
            <button key={s.id} className={"reports-tab" + (section === s.id ? " active" : "")}
              onClick={() => setSection(s.id)}>{s.label}</button>
          ))}
        </aside>

        <main className="reports-main">
          {loading && <div className="muted mono" style={{ padding: 24 }}>Loading…</div>}

          {!loading && section === "summary" && (
            <SummaryView paid={paid} range={range}
              grossSales={grossSales} refunds={refunds} discounts={discounts}
              netSales={netSales} grossProfit={grossProfit} />
          )}
          {!loading && section === "byItem"   && <ByItemView   paid={paid} />}
          {!loading && section === "byCat"    && <ByCategoryView paid={paid} />}
          {!loading && section === "byEmp"    && <ByEmployeeView paid={paid} />}
          {!loading && section === "byPay"    && <ByPaymentView paid={paid} />}
          {!loading && section === "byMod"    && <ByModifierView paid={paid} />}
          {!loading && section === "receipts" && <ReceiptsView orders={orders} />}
          {!loading && section === "shifts"   && <ShiftsView shifts={shifts} />}
        </main>
      </div>
    </div>
  );
}

function KPI2({ label, value, sub, accent }) {
  return (
    <div className={"kpi-card" + (accent ? " accent" : "")}>
      <div className="kpi-label mono">{label.toUpperCase()}</div>
      <Mono className="kpi-value">{value}</Mono>
      {sub && <div className="kpi-delta mono">{sub}</div>}
    </div>
  );
}

function SummaryView({ paid, range, grossSales, refunds, discounts, netSales, grossProfit }) {
  // Bucket by date for the bar chart
  const days = [];
  const start = new Date(range.from), end = new Date(range.to);
  for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) {
    days.push(d.toISOString().slice(0, 10));
  }
  const byDay = Object.fromEntries(days.map((d) => [d, { h: d.slice(5), orders: 0, revenue: 0 }]));
  paid.forEach((o) => { if (byDay[o.dateKey]) { byDay[o.dateKey].orders++; byDay[o.dateKey].revenue += (o.total || 0); } });
  const chartData = days.map((d) => byDay[d]);
  const marginPct = netSales > 0 ? Math.round(grossProfit / netSales * 100) : 0;

  return (
    <React.Fragment>
      <div className="kpis kpis-5">
        <KPI2 label="Gross sales" value={money(grossSales)} sub={`${paid.length} orders`} />
        <KPI2 label="Refunds" value={money(refunds)} sub="—" />
        <KPI2 label="Discounts" value={money(discounts)} sub="deposits & promos" />
        <KPI2 label="Net sales" value={money(netSales)} sub={`avg ${paid.length ? money(Math.round(netSales / paid.length)) : "—"}`} accent />
        <KPI2 label="Gross profit" value={money(grossProfit)} sub={`${marginPct}% margin`} />
      </div>

      <section className="panel-card" style={{ marginTop: 16 }}>
        <h3>Net sales · per day</h3>
        {paid.length === 0
          ? <div className="muted mono" style={{ padding: 24 }}>No paid orders in this range.</div>
          : <BarChart data={chartData} />}
      </section>
    </React.Fragment>
  );
}

function aggregateItems(paid, keyFn) {
  const m = {};
  paid.forEach((o) => o.items.forEach((i) => {
    const k = keyFn(i, o); if (!k) return;
    const row = m[k] || (m[k] = { key: k, qty: 0, gross: 0, cogs: 0 });
    row.qty += i.qty;
    row.gross += (i.price + (i.modPrice || 0)) * i.qty;
    row.cogs += (i.cogs || 0) * i.qty;
  }));
  return Object.values(m).map((r) => ({ ...r, margin: r.gross - r.cogs, marginPct: r.gross > 0 ? Math.round((r.gross - r.cogs) / r.gross * 100) : 0 }))
    .sort((a, b) => b.gross - a.gross);
}

function ByItemView({ paid }) {
  const rows = aggregateItems(paid, (i) => i.name);
  return <DataReport columns={["Item", "Qty", "Gross", "COGS", "Margin"]} rows={rows.map((r) => [
    r.key, r.qty, money(r.gross), money(r.cogs), `${money(r.margin)} · ${r.marginPct}%`,
  ])} totalRow={["Total", rows.reduce((s, r) => s + r.qty, 0),
    money(rows.reduce((s, r) => s + r.gross, 0)),
    money(rows.reduce((s, r) => s + r.cogs, 0)),
    money(rows.reduce((s, r) => s + r.margin, 0))]} />;
}

function ByCategoryView({ paid }) {
  const { products } = usePOS();
  const catByProductId = Object.fromEntries(products.map((p) => [p.id, p.category]));
  const rows = aggregateItems(paid, (i) => catByProductId[i.id] || "Uncategorised");
  return <DataReport columns={["Category", "Qty", "Gross", "COGS", "Margin"]} rows={rows.map((r) => [
    r.key, r.qty, money(r.gross), money(r.cogs), `${money(r.margin)} · ${r.marginPct}%`,
  ])} totalRow={["Total", rows.reduce((s, r) => s + r.qty, 0),
    money(rows.reduce((s, r) => s + r.gross, 0)),
    money(rows.reduce((s, r) => s + r.cogs, 0)),
    money(rows.reduce((s, r) => s + r.margin, 0))]} />;
}

function ByEmployeeView({ paid }) {
  const m = {};
  paid.forEach((o) => {
    const k = o.cashierEmail || "(unknown)";
    const row = m[k] || (m[k] = { key: k, orders: 0, gross: 0 });
    row.orders++;
    row.gross += (o.total || 0);
  });
  const rows = Object.values(m).sort((a, b) => b.gross - a.gross);
  return <DataReport columns={["Cashier", "Orders", "Net sales", "Avg ticket"]}
    rows={rows.map((r) => [r.key, r.orders, money(r.gross), money(Math.round(r.gross / Math.max(1, r.orders)))])}
    totalRow={["Total",
      rows.reduce((s, r) => s + r.orders, 0),
      money(rows.reduce((s, r) => s + r.gross, 0)),
      ""]} />;
}

function ByPaymentView({ paid }) {
  const m = {};
  paid.forEach((o) => {
    const splits = (o.payments && o.payments.length) ? o.payments : [{ method: o.paymentMethod || "—", amount: o.total }];
    splits.forEach((p) => {
      const k = (p.method || "—").toUpperCase();
      const row = m[k] || (m[k] = { key: k, count: 0, total: 0 });
      row.count++; row.total += Number(p.amount) || 0;
    });
  });
  const rows = Object.values(m).sort((a, b) => b.total - a.total);
  const grand = rows.reduce((s, r) => s + r.total, 0) || 1;
  return <DataReport columns={["Payment", "Count", "Total", "Share"]}
    rows={rows.map((r) => [r.key, r.count, money(r.total), `${Math.round(r.total / grand * 100)}%`])}
    totalRow={["Total", rows.reduce((s, r) => s + r.count, 0), money(grand), "100%"]} />;
}

function ByModifierView({ paid }) {
  const m = {};
  paid.forEach((o) => o.items.forEach((i) => (i.mods || []).forEach((mod) => {
    const row = m[mod] || (m[mod] = { key: mod, qty: 0, revenue: 0 });
    row.qty += i.qty;
    row.revenue += (i.modPrice || 0) * i.qty;
  })));
  const rows = Object.values(m).sort((a, b) => b.qty - a.qty);
  return <DataReport columns={["Modifier", "Times used", "Modifier revenue"]}
    rows={rows.length ? rows.map((r) => [r.key, r.qty, money(r.revenue)]) : []}
    totalRow={rows.length ? ["Total", rows.reduce((s, r) => s + r.qty, 0), money(rows.reduce((s, r) => s + r.revenue, 0))] : null} />;
}

function ReceiptsView({ orders }) {
  const [refundFor, setRefundFor] = React.useState(null);
  const list = [...orders].sort((a, b) => (b.createdAt?.seconds || 0) - (a.createdAt?.seconds || 0));
  return (
    <React.Fragment>
      <div className="panel-card no-pad">
        <table className="data-table">
          <thead><tr>
            <th>When</th><th>#</th><th>Customer</th><th>Table</th><th>Items</th><th>Payment</th><th>Status</th><th>Total</th><th>Refunded</th><th></th>
          </tr></thead>
          <tbody>
            {list.length === 0 && <tr><td colSpan="10" className="muted mono" style={{ textAlign: "center", padding: 24 }}>No receipts in range.</td></tr>}
            {list.map((o) => (
              <tr key={o.id}>
                <td><Mono>{o.createdAt?.toDate ? o.createdAt.toDate().toLocaleString("en-GB") : "—"}</Mono></td>
                <td><Mono>{o.shortId}</Mono></td>
                <td>{o.customer || "—"}</td>
                <td><Mono>{o.table || "—"}</Mono></td>
                <td><Mono>{o.items.reduce((a, i) => a + i.qty, 0)}</Mono></td>
                <td><Mono>{(o.paymentMethod || "—").toUpperCase()}</Mono></td>
                <td><Mono>{o.paid === false ? "OPEN" : (o.status || "open").toUpperCase()}</Mono></td>
                <td><Mono>{money(o.total)}</Mono></td>
                <td><Mono className={o.refundedAmount ? "stock-low" : "muted"}>{o.refundedAmount ? "−" + money(o.refundedAmount) : "—"}</Mono></td>
                <td>{o.paid !== false && o.status !== "refunded" && <button className="btn-ghost-sm" onClick={() => setRefundFor(o)}>Refund</button>}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
      {refundFor && <RefundSheet order={refundFor} onClose={() => setRefundFor(null)} />}
    </React.Fragment>
  );
}

function ShiftsView({ shifts }) {
  const list = [...shifts].sort((a, b) => (b.openedAt?.seconds || 0) - (a.openedAt?.seconds || 0));
  return <DataReport columns={["Date", "Cashier", "Opened", "Closed", "Float", "Cash sales", "Expected", "Counted", "Variance"]}
    rows={list.map((s) => [
      s.dateKey, s.cashierEmail || "—",
      s.openedAt?.toDate ? s.openedAt.toDate().toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" }) : "—",
      s.closedAt?.toDate ? s.closedAt.toDate().toLocaleTimeString("en-GB", { hour: "2-digit", minute: "2-digit" }) : "—",
      money(s.openingCash || 0),
      money(s.cashSales || 0),
      money(s.expectedCash || 0),
      s.status === "closed" ? money(s.closingCash || 0) : "—",
      s.status === "closed" ? `${s.variance >= 0 ? "+" : "−"}${money(Math.abs(s.variance || 0))}` : "—",
    ])} />;
}

function DataReport({ columns, rows, totalRow }) {
  const exportCSV = () => {
    const lines = [columns.join(",")];
    rows.forEach((r) => lines.push(r.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(",")));
    if (totalRow) lines.push(totalRow.map((v) => `"${String(v).replace(/"/g, '""')}"`).join(","));
    const blob = new Blob([lines.join("\n")], { type: "text/csv" });
    const a = document.createElement("a"); a.href = URL.createObjectURL(blob);
    a.download = "report-" + Date.now() + ".csv"; a.click();
    URL.revokeObjectURL(a.href);
  };
  return (
    <div className="panel-card no-pad" style={{ marginTop: 8 }}>
      <div className="row" style={{ justifyContent: "flex-end", padding: "10px 14px", gap: 8 }}>
        <button className="btn-ghost-sm" onClick={exportCSV} disabled={!rows.length}>Export CSV</button>
      </div>
      <table className="data-table">
        <thead><tr>{columns.map((c) => <th key={c}>{c}</th>)}</tr></thead>
        <tbody>
          {rows.length === 0 && <tr><td colSpan={columns.length} className="muted mono" style={{ textAlign: "center", padding: 24 }}>No data in range.</td></tr>}
          {rows.map((r, i) => (
            <tr key={i}>{r.map((v, j) => <td key={j}><Mono>{v}</Mono></td>)}</tr>
          ))}
          {totalRow && (
            <tr style={{ fontWeight: 600, background: "var(--paper-soft)" }}>
              {totalRow.map((v, j) => <td key={j}><Mono>{v}</Mono></td>)}
            </tr>
          )}
        </tbody>
      </table>
    </div>
  );
}

Object.assign(window, { AdminReports });
