"use client";

import * as React from "react";
import { Bar, BarChart, CartesianGrid, Line, LineChart, XAxis, YAxis } from "recharts";
import { ChevronRightIcon } from "lucide-react";

import { kes } from "@/components/medora/payroll";
import { seqInk, seqStep, VIZ_INK, VIZ_SEQ, VIZ_SERIES } from "@/components/medora/viz";
import { Button } from "@/components/ui/button";
import { ChartContainer, ChartTooltip, ChartTooltipContent, type ChartConfig } from "@/components/ui/chart";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import { cn } from "@/lib/utils";
import { count } from "@/lib/format";

const k = (v: number) => (v >= 1_000_000 ? `${(v / 1_000_000).toFixed(1)}M` : v >= 1000 ? `${Math.round(v / 1000)}k` : String(v));
const pct = (n: number) => `${n.toFixed(1)}%`;
const hourLabel = (h: number) => `${String(h).padStart(2, "0")}:00`;

/** Chart / Table switch. Every chart here has a table of the same figures, so nothing depends on colour. */
export function ViewSwitch({ value, onChange, label }: { value: "chart" | "table"; onChange: (v: "chart" | "table") => void; label: string }) {
  return (
    <ToggleGroup variant="outline" size="sm" spacing={0} aria-label={`${label}: view as`} value={[value]} onValueChange={(v: string[]) => v[0] && onChange(v[0] as "chart" | "table")}>
      <ToggleGroupItem value="chart">Chart</ToggleGroupItem>
      <ToggleGroupItem value="table">Table</ToggleGroupItem>
    </ToggleGroup>
  );
}

/* ---------------------------------- Expandable sales (RP-08) ---------------------------------- */

export type SaleDetail = {
  receipt: string;
  time: string;
  cashier: string;
  customer?: string;
  items: { name: string; qty: number; price: number; discount?: number }[];
  vat: number;
  payments: { method: string; ref?: string; amount: number }[];
  returns: { ref: string; item: string; qty: number; amount: number; reason: string }[];
};

const saleSubtotal = (s: SaleDetail) => s.items.reduce((t, i) => t + i.qty * (i.price - (i.discount ?? 0)), 0);
export const saleTotal = (s: SaleDetail) => saleSubtotal(s) + s.vat;
const returned = (s: SaleDetail) => s.returns.reduce((t, r) => t + r.amount, 0);

function saleStatus(s: SaleDetail) {
  const r = returned(s);
  if (!r) return "Completed";
  return r >= saleTotal(s) - 0.005 ? "Fully returned" : "Part returned";
}

/** RP-08: sales list where each sale opens in place to its items, payments and returns. */
export function ExpandableSales({ sales, onOpenSale }: { sales: SaleDetail[]; onOpenSale?: (receipt: string) => void }) {
  const [open, setOpen] = React.useState<Set<string>>(new Set());
  const all = open.size === sales.length && sales.length > 0;
  const flip = (r: string) => setOpen((s) => (s.has(r) ? (s.delete(r), new Set(s)) : new Set(s).add(r)));
  const totals = sales.reduce((t, s) => ({ gross: t.gross + saleTotal(s), ret: t.ret + returned(s) }), { gross: 0, ret: 0 });

  return (
    <div className="space-y-2">
      <div className="flex justify-end">
        <Button size="sm" variant="ghost" onClick={() => setOpen(all ? new Set() : new Set(sales.map((s) => s.receipt)))}>
          {all ? "Collapse all" : "Expand all"}
        </Button>
      </div>
      <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
        <table className="w-full min-w-[640px] text-sm">
          <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
            <tr>
              <th className="w-8 px-2 py-2">
                <span className="sr-only">Expand</span>
              </th>
              <th className="px-3 py-2 font-medium">Receipt</th>
              <th className="px-3 py-2 font-medium">Cashier and customer</th>
              <th className="px-3 py-2 font-medium">Status</th>
              <th className="px-3 py-2 text-right font-medium">Total</th>
              <th className="px-3 py-2 text-right font-medium">Returned</th>
            </tr>
          </thead>
          {sales.map((s) => {
            const isOpen = open.has(s.receipt);
            const st = saleStatus(s);
            const paid = s.payments.reduce((t, p) => t + p.amount, 0);
            return (
              <tbody key={s.receipt} className="border-t border-[var(--color-border-subtle)]">
                <tr className={cn("hover:bg-muted/40", isOpen && "bg-muted/30")}>
                  <td className="px-2 py-2">
                    <Button size="icon-sm" variant="ghost" aria-expanded={isOpen} aria-controls={`sale-${s.receipt}`} aria-label={`${isOpen ? "Hide" : "Show"} ${s.receipt} details`} onClick={() => flip(s.receipt)}>
                      <ChevronRightIcon className={cn("transition-transform", isOpen && "rotate-90")} />
                    </Button>
                  </td>
                  <td className="px-3 py-2 whitespace-nowrap">
                    <span className="font-mono text-xs">{s.receipt}</span>
                    <span className="block text-xs text-muted-foreground">{s.time}</span>
                  </td>
                  <td className="px-3 py-2">
                    {s.cashier}
                    <span className="block text-xs text-muted-foreground">{s.customer ?? "Walk-in"}</span>
                  </td>
                  <td className={cn("px-3 py-2 text-xs font-medium", st === "Completed" ? "text-status-success-text" : "text-status-warning-text")}>{st}</td>
                  <td className="px-3 py-2 text-right tabular-nums">{kes(saleTotal(s))}</td>
                  <td className="px-3 py-2 text-right tabular-nums">{returned(s) ? kes(returned(s)) : "–"}</td>
                </tr>
                {isOpen ? (
                  <tr id={`sale-${s.receipt}`}>
                    <td />
                    <td colSpan={5} className="px-3 pt-1 pb-4">
                      <div className="grid gap-4 lg:grid-cols-3">
                        <div>
                          <h4 className="mb-1 text-xs font-semibold text-muted-foreground uppercase">Items</h4>
                          <ul className="space-y-1 text-xs">
                            {s.items.map((i) => (
                              <li key={i.name} className="flex justify-between gap-3">
                                <span>
                                  {i.qty} × {i.name}
                                  {i.discount ? <span className="text-muted-foreground"> (less {kes(i.discount)} each)</span> : null}
                                </span>
                                <span className="tabular-nums">{kes(i.qty * (i.price - (i.discount ?? 0)))}</span>
                              </li>
                            ))}
                            <li className="flex justify-between border-t border-[var(--color-border-subtle)] pt-1 text-muted-foreground">
                              <span>VAT</span>
                              <span className="tabular-nums">{kes(s.vat)}</span>
                            </li>
                          </ul>
                        </div>
                        <div>
                          <h4 className="mb-1 text-xs font-semibold text-muted-foreground uppercase">Payments</h4>
                          <ul className="space-y-1 text-xs">
                            {s.payments.map((p, i) => (
                              <li key={i} className="flex justify-between gap-3">
                                <span>
                                  {p.method}
                                  {p.ref ? <span className="font-mono text-muted-foreground"> {p.ref}</span> : null}
                                </span>
                                <span className="tabular-nums">{kes(p.amount)}</span>
                              </li>
                            ))}
                            {Math.abs(paid - saleTotal(s)) > 0.005 ? (
                              <li className="text-status-warning-text">
                                {paid < saleTotal(s) ? `${kes(saleTotal(s) - paid)} on account` : `${kes(paid - saleTotal(s))} change given`}
                              </li>
                            ) : null}
                          </ul>
                        </div>
                        <div>
                          <h4 className="mb-1 text-xs font-semibold text-muted-foreground uppercase">Returns</h4>
                          {s.returns.length ? (
                            <ul className="space-y-1 text-xs">
                              {s.returns.map((r) => (
                                <li key={r.ref}>
                                  <span className="flex justify-between gap-3">
                                    <span>
                                      <span className="font-mono">{r.ref}</span> · {r.qty} × {r.item}
                                    </span>
                                    <span className="tabular-nums">{kes(r.amount)}</span>
                                  </span>
                                  <span className="text-muted-foreground">{r.reason}</span>
                                </li>
                              ))}
                            </ul>
                          ) : (
                            <p className="text-xs text-muted-foreground">Nothing returned.</p>
                          )}
                        </div>
                      </div>
                      {onOpenSale ? (
                        <Button size="sm" variant="link" className="mt-2 px-0" onClick={() => onOpenSale(s.receipt)}>
                          Open {s.receipt}
                        </Button>
                      ) : null}
                    </td>
                  </tr>
                ) : null}
              </tbody>
            );
          })}
          <tfoot className="border-t-2 border-[var(--color-border-panel)] bg-muted/30 font-semibold">
            <tr>
              <td colSpan={4} className="px-3 py-2">
                {sales.length} {sales.length === 1 ? "sale" : "sales"} · net of returns {kes(totals.gross - totals.ret)}
              </td>
              <td className="px-3 py-2 text-right tabular-nums">{kes(totals.gross)}</td>
              <td className="px-3 py-2 text-right tabular-nums">{kes(totals.ret)}</td>
            </tr>
          </tfoot>
        </table>
      </div>
    </div>
  );
}

/* ------------------------------------ Peak times (RP-11) ------------------------------------ */

/** RP-11 peak days: sales by weekday and hour on one teal scale. Hover or focus a cell to read it. */
export function PeakHeatmap({ days, hours, counts }: { days: string[]; hours: number[]; counts: number[][] }) {
  const [view, setView] = React.useState<"chart" | "table">("chart");
  const [hover, setHover] = React.useState<{ d: number; h: number } | null>(null);
  const max = Math.max(0, ...counts.flat());
  let peak = { d: 0, h: 0, v: -1 };
  counts.forEach((row, d) => row.forEach((v, h) => v > peak.v && (peak = { d, h, v })));
  const dayTotals = counts.map((r) => r.reduce((s, v) => s + v, 0));
  const busiestDay = dayTotals.indexOf(Math.max(...dayTotals));
  const read = (d: number, h: number) => `${days[d]} ${hourLabel(hours[h])}–${hourLabel(hours[h] + 1)}: ${count(counts[d][h], "sale")}`;

  return (
    <div className="space-y-3">
      <div className="flex flex-wrap items-center justify-between gap-2">
        <p className="text-sm">
          Busiest hour: <strong>{days[peak.d]}, {hourLabel(hours[peak.h])}</strong> ({peak.v} {peak.v === 1 ? "sale" : "sales"}). Busiest day: <strong>{days[busiestDay]}</strong> ({dayTotals[busiestDay]} {dayTotals[busiestDay] === 1 ? "sale" : "sales"}).
        </p>
        <ViewSwitch value={view} onChange={setView} label="Peak times" />
      </div>
      {view === "chart" ? (
        <>
          <p className="h-4 text-xs text-muted-foreground tabular-nums" aria-live="polite">
            {hover ? read(hover.d, hover.h) : "Point at a square to read it."}
          </p>
          <div className="overflow-x-auto">
            <div className="grid min-w-[560px] gap-[2px]" style={{ gridTemplateColumns: `3rem repeat(${hours.length}, minmax(0, 1fr))` }} onMouseLeave={() => setHover(null)}>
              <span />
              {hours.map((h, i) => (
                <span key={h} className="text-center text-[10px] text-muted-foreground tabular-nums">
                  {i % 2 === 0 ? String(h).padStart(2, "0") : ""}
                </span>
              ))}
              {days.map((day, d) => (
                <React.Fragment key={day}>
                  <span className="self-center text-xs text-muted-foreground">{day.slice(0, 3)}</span>
                  {hours.map((h, hi) => {
                    const v = counts[d][hi];
                    const step = seqStep(v, max);
                    const isPeak = d === peak.d && hi === peak.h;
                    return (
                      <span
                        key={h}
                        tabIndex={0}
                        role="img"
                        aria-label={read(d, hi)}
                        onMouseEnter={() => setHover({ d, h: hi })}
                        onFocus={() => setHover({ d, h: hi })}
                        onBlur={() => setHover(null)}
                        className={cn("flex aspect-square min-h-6 items-center justify-center rounded-[3px] text-[10px] tabular-nums outline-none focus-visible:ring-2 focus-visible:ring-ring", step < 0 && "border border-dashed border-[var(--color-border-subtle)]", isPeak && "ring-2 ring-[var(--mdr-ink)] ring-offset-1")}
                        style={step >= 0 ? { backgroundColor: VIZ_SEQ[step], color: seqInk(step) } : undefined}
                      >
                        {isPeak ? v : ""}
                      </span>
                    );
                  })}
                </React.Fragment>
              ))}
            </div>
          </div>
          <div className="flex items-center gap-2 text-xs text-muted-foreground">
            <span>Fewer</span>
            {VIZ_SEQ.map((c, i) => (
              <span key={c} className="h-3 w-6 rounded-[2px]" style={{ backgroundColor: c }} aria-hidden title={`Up to ${Math.round(((i + 1) / VIZ_SEQ.length) * max)} sales`} />
            ))}
            <span>More (up to {max} sales an hour)</span>
            <span className="ml-3 inline-flex items-center gap-1">
              <span className="size-3 rounded-[2px] border border-dashed border-[var(--color-border-subtle)]" aria-hidden /> None
            </span>
          </div>
        </>
      ) : (
        <div className="overflow-x-auto">
          <table className="w-full text-xs tabular-nums">
            <caption className="sr-only">Sales by weekday and hour</caption>
            <thead className="text-muted-foreground">
              <tr>
                <th className="px-1 py-1 text-left font-medium">Day</th>
                {hours.map((h) => (
                  <th key={h} className="px-1 py-1 text-right font-medium">
                    {String(h).padStart(2, "0")}
                  </th>
                ))}
                <th className="px-1 py-1 text-right font-medium">Total</th>
              </tr>
            </thead>
            <tbody>
              {days.map((day, d) => (
                <tr key={day} className="border-t border-[var(--color-border-subtle)]">
                  <th className="px-1 py-1 text-left font-medium">{day}</th>
                  {counts[d].map((v, h) => (
                    <td key={h} className={cn("px-1 py-1 text-right", d === peak.d && h === peak.h && "font-bold")}>
                      {v || "–"}
                    </td>
                  ))}
                  <td className="px-1 py-1 text-right font-semibold">{dayTotals[d]}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

/* ------------------------------------- Rx vs OTC (RP-11) ------------------------------------- */

/**
 * RP-11 Rx vs OTC: revenue split by the product's "prescription required" box, ex-VAT and net of discounts,
 * so it reconciles with per-product revenue, not with VAT-inclusive sales. When no product is marked Rx the
 * split is a data-entry gap, not a 0% trading fact, and the chart says so instead of drawing it.
 */
export function RxOtcSplit({ rx, otc, rxProducts, products }: { rx: number; otc: number; rxProducts: number; products: number }) {
  const total = rx + otc;
  if (!rxProducts)
    return (
      <div className="rounded-md border border-dashed border-[var(--color-border-panel)] p-4 text-sm">
        <p className="font-medium">No split to show yet</p>
        <p className="mt-1 text-muted-foreground">None of the {products.toLocaleString("en-US")} products is marked “Prescription required”, so every sale would count as over the counter. Mark Rx products in Inventory and the split appears here.</p>
      </div>
    );
  const parts = [
    { label: "Prescription (Rx)", value: rx, color: VIZ_SERIES[0] },
    { label: "Over the counter", value: otc, color: VIZ_SERIES[1] },
  ];
  return (
    <div className="space-y-3">
      <div className="flex h-8 w-full gap-[2px]" role="img" aria-label={parts.map((p) => `${p.label} ${pct((p.value / total) * 100)}`).join(", ")}>
        {parts.map((p, i) => (
          <span key={p.label} className={cn("h-full", i === 0 ? "rounded-l-[4px]" : "rounded-r-[4px]")} style={{ width: `${(p.value / total) * 100}%`, backgroundColor: p.color }} />
        ))}
      </div>
      <ul className="grid gap-2 sm:grid-cols-2">
        {parts.map((p) => (
          <li key={p.label} className="flex items-start gap-2 text-sm">
            <span className="mt-1 size-3 shrink-0 rounded-[2px]" style={{ backgroundColor: p.color }} aria-hidden />
            <span>
              <span className="font-medium">{p.label}</span> {pct((p.value / total) * 100)}
              <span className="block text-xs text-muted-foreground tabular-nums">{kes(p.value)}</span>
            </span>
          </li>
        ))}
      </ul>
      <p className="text-xs text-muted-foreground">
        Ex-VAT and after discounts, from {rxProducts} of {products} products marked Rx. Matches per-product revenue, not the VAT-inclusive sales total.
      </p>
    </div>
  );
}

/* --------------------------------- Monthly trend (RP-12) --------------------------------- */

export const PAY_METHODS = ["M-Pesa", "Cash", "Card", "Credit"] as const;
export type PayMethod = (typeof PAY_METHODS)[number];
export type MonthSales = { label: string; net: number; byMethod: Record<PayMethod, number>; partial?: boolean };

const methodKey = (m: PayMethod) => m.replace(/[^A-Za-z]/g, "").toLowerCase();
const methodConfig = Object.fromEntries(PAY_METHODS.map((m, i) => [methodKey(m), { label: m, color: VIZ_SERIES[i] }])) satisfies ChartConfig;

/**
 * RP-12: net sales trend, then the same months split by payment method. Two charts on their own axes, never
 * one chart with two scales. A month still in progress is labelled and drawn as a hollow point.
 */
export function MonthlyTrend({ months }: { months: MonthSales[] }) {
  const [view, setView] = React.useState<"chart" | "table">("chart");
  const data = months.map((m) => ({ label: m.partial ? `${m.label}*` : m.label, net: m.net, partial: !!m.partial, ...Object.fromEntries(PAY_METHODS.map((p) => [methodKey(p), m.byMethod[p]])) }));
  const last = months.at(-1);
  return (
    <div className="space-y-4">
      <div className="flex justify-end">
        <ViewSwitch value={view} onChange={setView} label="Monthly trend" />
      </div>
      {view === "chart" ? (
        <div className="grid gap-4 lg:grid-cols-2">
          <figure>
            <figcaption className="mb-1 text-xs font-medium">Net sales (ex-VAT) per month</figcaption>
            <ChartContainer config={{ net: { label: "Net sales", color: VIZ_INK } }} className="aspect-auto h-52 w-full" initialDimension={{ width: 420, height: 208 }}>
              <LineChart data={data} margin={{ left: 0, right: 12, top: 16 }}>
                <CartesianGrid vertical={false} strokeOpacity={0.5} />
                <XAxis dataKey="label" tickLine={false} axisLine={false} tickMargin={8} />
                <YAxis tickLine={false} axisLine={false} width={40} tickFormatter={k} />
                <ChartTooltip content={<ChartTooltipContent formatter={(v) => `${kes(Number(v))}`} />} />
                <Line
                  dataKey="net"
                  type="linear"
                  stroke="var(--color-net)"
                  strokeWidth={2}
                  isAnimationActive={false}
                  dot={(p: { cx?: number; cy?: number; index?: number; payload?: { partial: boolean } }) => (
                    <circle key={p.index} cx={p.cx} cy={p.cy} r={4} stroke="var(--color-net)" strokeWidth={2} fill={p.payload?.partial ? "var(--background, #fff)" : "var(--color-net)"} />
                  )}
                />
              </LineChart>
            </ChartContainer>
          </figure>
          <figure>
            <figcaption className="mb-1 flex flex-wrap items-center justify-between gap-x-3 gap-y-1 text-xs">
              <span className="font-medium">Takings by payment method (VAT-inclusive)</span>
              <span className="flex flex-wrap gap-3 text-muted-foreground">
                {PAY_METHODS.map((m, i) => (
                  <span key={m} className="flex items-center gap-1.5">
                    <span className="size-2.5 rounded-[2px]" style={{ backgroundColor: VIZ_SERIES[i] }} aria-hidden />
                    {m}
                  </span>
                ))}
              </span>
            </figcaption>
            <ChartContainer config={methodConfig} className="aspect-auto h-52 w-full" initialDimension={{ width: 420, height: 208 }}>
              <BarChart data={data} margin={{ left: 0, right: 12, top: 16 }}>
                <CartesianGrid vertical={false} strokeOpacity={0.5} />
                <XAxis dataKey="label" tickLine={false} axisLine={false} tickMargin={8} />
                <YAxis tickLine={false} axisLine={false} width={40} tickFormatter={k} />
                <ChartTooltip content={<ChartTooltipContent formatter={(v, n) => `${methodConfig[String(n) as keyof typeof methodConfig]?.label ?? n}: ${kes(Number(v))}`} />} />
                {PAY_METHODS.map((m, i) => (
                  <Bar key={m} dataKey={methodKey(m)} stackId="pay" fill={`var(--color-${methodKey(m)})`} stroke="var(--background, #fff)" strokeWidth={2} radius={i === PAY_METHODS.length - 1 ? [4, 4, 0, 0] : 0} isAnimationActive={false} />
                ))}
              </BarChart>
            </ChartContainer>
          </figure>
        </div>
      ) : (
        <div className="overflow-x-auto">
          <table className="w-full min-w-[560px] text-sm tabular-nums">
            <thead className="bg-[var(--color-bg-surface-subtle)] text-xs text-muted-foreground">
              <tr>
                <th className="px-2 py-1 text-left font-medium">Month</th>
                <th className="px-2 py-1 text-right font-medium">Net sales</th>
                {PAY_METHODS.map((m) => (
                  <th key={m} className="px-2 py-1 text-right font-medium">
                    {m}
                  </th>
                ))}
              </tr>
            </thead>
            <tbody>
              {months.map((m) => (
                <tr key={m.label} className="border-t border-[var(--color-border-subtle)]">
                  <th className="px-2 py-1 text-left font-medium">
                    {m.label}
                    {m.partial ? <span className="font-normal text-muted-foreground"> (so far)</span> : null}
                  </th>
                  <td className="px-2 py-1 text-right">{kes(m.net)}</td>
                  {PAY_METHODS.map((p) => (
                    <td key={p} className="px-2 py-1 text-right">
                      {kes(m.byMethod[p])}
                    </td>
                  ))}
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      )}
      {last?.partial ? <p className="text-xs text-muted-foreground">* {last.label} is still in progress (hollow point), so it will rise. Don&apos;t read its drop as a fall in trade.</p> : null}
    </div>
  );
}

/* ---------------------------------- My shift (PS-21) ---------------------------------- */

/**
 * PS-21: the cashier's own shift, by payment method and by hour. Only this cashier's sales, never the
 * branch's, so it can sit on the till without exposing anyone else's figures.
 */
/** `sales`: the number of sales, when a sale can be paid by more than one method (PS-06); otherwise the methods' counts are summed. */
export function ShiftSales({ cashier, opened, byMethod, byHour, sales }: { cashier: string; opened: string; byMethod: Record<PayMethod, { amount: number; count: number }>; byHour: { hour: number; amount: number; count: number }[]; sales?: number }) {
  const [view, setView] = React.useState<"chart" | "table">("chart");
  const total = PAY_METHODS.reduce((s, m) => s + byMethod[m].amount, 0);
  const count = sales ?? PAY_METHODS.reduce((s, m) => s + byMethod[m].count, 0);
  const best = byHour.reduce((a, b) => (b.amount > a.amount ? b : a), byHour[0]);
  const data = byHour.map((h) => ({ ...h, label: hourLabel(h.hour) }));
  return (
    <div className="space-y-4">
      <div className="flex flex-wrap items-baseline justify-between gap-2">
        <p className="text-sm">
          <strong>{cashier}</strong>, shift opened {opened}: <strong className="tabular-nums">{kes(total)}</strong> from {count} {count === 1 ? "sale" : "sales"}
        </p>
        <ViewSwitch value={view} onChange={setView} label="My shift" />
      </div>
      <ul className="grid grid-cols-2 gap-2 sm:grid-cols-4">
        {PAY_METHODS.map((m, i) => (
          <li key={m} className="rounded-md border border-[var(--color-border-panel)] p-2 bg-card">
            <span className="flex items-center gap-1.5 text-xs text-muted-foreground">
              <span className="size-2.5 rounded-[2px]" style={{ backgroundColor: VIZ_SERIES[i] }} aria-hidden />
              {m}
            </span>
            <span className="block font-semibold tabular-nums">{kes(byMethod[m].amount)}</span>
            <span className="text-xs text-muted-foreground">
              {byMethod[m].count} {byMethod[m].count === 1 ? "sale" : "sales"} · {total ? pct((byMethod[m].amount / total) * 100) : "0%"}
            </span>
          </li>
        ))}
      </ul>
      {view === "chart" ? (
        <figure>
          <figcaption className="mb-1 text-xs font-medium">
            Sales per hour · best hour {hourLabel(best.hour)} ({kes(best.amount)})
          </figcaption>
          <ChartContainer config={{ amount: { label: "Sales", color: VIZ_SERIES[0] } }} className="aspect-auto h-40 w-full" initialDimension={{ width: 480, height: 160 }}>
            <BarChart data={data} margin={{ left: 0, right: 8, top: 16 }}>
              <CartesianGrid vertical={false} strokeOpacity={0.5} />
              <XAxis dataKey="label" tickLine={false} axisLine={false} tickMargin={6} />
              <YAxis tickLine={false} axisLine={false} width={36} tickFormatter={k} />
              <ChartTooltip content={<ChartTooltipContent formatter={(v, _n, item) => `${kes(Number(v))} · ${(item.payload as { count: number }).count} sales`} />} />
              <Bar dataKey="amount" fill="var(--color-amount)" radius={[4, 4, 0, 0]} isAnimationActive={false} />
            </BarChart>
          </ChartContainer>
        </figure>
      ) : (
        <table className="w-full text-sm tabular-nums">
          <thead className="bg-[var(--color-bg-surface-subtle)] text-xs text-muted-foreground">
            <tr>
              <th className="px-2 py-1 text-left font-medium">Hour</th>
              <th className="px-2 py-1 text-right font-medium">Sales</th>
              <th className="px-2 py-1 text-right font-medium">Amount</th>
            </tr>
          </thead>
          <tbody>
            {byHour.map((h) => (
              <tr key={h.hour} className="border-t border-[var(--color-border-subtle)]">
                <td className="px-2 py-1">
                  {hourLabel(h.hour)}–{hourLabel(h.hour + 1)}
                </td>
                <td className="px-2 py-1 text-right">{h.count}</td>
                <td className="px-2 py-1 text-right">{kes(h.amount)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      )}
    </div>
  );
}
