"use client";

/**
 * Cashier balances and Open and close shift (PRD 2.5, 2.8, 2.9; split into two pages and permissions by plan E to match
 * the sitemap: `view="shift"` opens and closes a shift with its Z-report, `view="balances"` is the live balance, drops,
 * the balances report and past Z-reports). Originally Cashier balances (PRD 2.5, 2.8, 2.9), on the Medora design system (Stage 7, 24 Oct 2026) and the Shifts API plan:
 * open a shift with cash and M-Pesa (PS-19), the live drawer and till balance, cash and M-Pesa drops (PS-15), the
 * cashier's own sales by method and hour (PS-21), close with every tender counted and the Z-report (PS-20), and the
 * opening/closing balance report (PS-16).
 *
 * Named, not faked: drops go to Bank or Safe until branch money accounts exist (ST-02); there's no float limit and any
 * difference is a mismatch until a setting goes through the workflow (DECISIONS.md, Q3); there are no tills yet, so a
 * shift is the cashier's at a branch.
 */

import * as React from "react";
import Link from "next/link";
import { RefreshCwIcon } from "lucide-react";

import { MedoraPageHeader } from "@/components/medora/page-header";
import {
  DropForm,
  OpenShiftForm,
  ShiftBalanceReport,
  kes,
  type ShiftBalance,
} from "@/components/medora/pos-ops";
import {
  CloseShiftForm,
  ZReport,
  closeProblems,
  expectedByTender,
  type CloseCount,
  type ShiftFigures,
} from "@/components/medora/shift-close";
import { ShiftSales, type PayMethod } from "@/components/medora/sales-reports";
import { PrintButton } from "@/components/medora/print";
import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Spinner } from "@/components/ui/spinner";
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "@/components/ui/table";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { toast } from "@/components/ui/toast";
import { ShiftsApi } from "@/lib/api";
import { addDays, localToday } from "@/lib/format";
import { useMenuPermissions } from "@/lib/permissions";
import { Surface } from "@/components/medora/surface";
import { Loading } from "@/components/medora/loading";

/* ------------------------------------ API shapes ------------------------------------ */

type Money3 = { cash: number; mpesa: number; card: number };
type Drop = {
  id: number;
  amount: number | string;
  type: string;
  destination: string;
  reference?: string | null;
  witness?: string | null;
  createdAt: string;
};
type ApiShift = {
  id: number;
  cashier?: { name?: string; username?: string };
  branch?: { name?: string } | null;
  startTime: string;
  endTime: string | null;
  startBalance: number | string;
  openingMpesa?: number;
  openingNote?: string | null;
  cashLeft?: number | null;
  expectedCash: number | string;
  expectedMpesa: number | string;
  expectedCard: number | string;
  actualCash: number | string | null;
  actualMpesa: number | string | null;
  actualCard: number | string | null;
  notes: string | null;
};
type ActiveShift = ApiShift & {
  salesByTender: Money3;
  cashRefunds: number;
  mpesaRefunds: number;
  cardRefunds: number;
  cashDrops: number;
  mpesaDrops: number;
  drops: Drop[];
  byMethod: Record<PayMethod, { amount: number; count: number }>;
  byHour: { hour: number; amount: number; count: number }[];
  transactions: number;
  voids: number;
  returns: number;
};
type ZData = {
  shift: ApiShift;
  salesByTender: Money3;
  byMethod: Record<PayMethod, { amount: number; count: number }>;
  dropTotals: { cash: number; mpesa: number };
  cashRefunds: number;
  mpesaRefunds: number;
  cardRefunds: number;
  salesCount: number;
  returnsCount: number;
  voidsCount: number;
};
type LastClose = {
  shiftId: number;
  cashLeft: number | null;
  mpesa: number | null;
  by: string;
  at: string | null;
};

const n = (v: number | string | null | undefined) => Number(v) || 0;
const when = (iso: string | null | undefined) =>
  iso
    ? new Date(iso).toLocaleString("en-GB", {
        day: "numeric",
        month: "short",
        year: "numeric",
        hour: "2-digit",
        minute: "2-digit",
      })
    : "";
const hhmm = (iso: string) =>
  new Date(iso).toLocaleTimeString("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
  });
const nameOf = (s: ApiShift) =>
  s.cashier?.name || s.cashier?.username || "Unknown";
const apiError = (e: unknown, fallback: string): string => {
  const m = (e as { response?: { data?: { message?: string | string[] } } })
    ?.response?.data?.message;
  return Array.isArray(m) ? m.join(" ") : m || fallback;
};

/** ST-02 (plan C): drops go to the branch's own accounts, its safe and banks for cash and its banks for M-Pesa. */
type DropAccount = { id: number; code: string; name: string; kind: "Cash" | "M-Pesa" };

/** The design's Z-report figures from a shift and what it took. */
function figuresOf(
  s: ApiShift,
  t: {
    taken: Money3;
    credit: number;
    refunds: Money3;
    drops: { cash: number; mpesa: number };
    transactions: number;
    voids: number;
    returns: number;
  },
  closedAt?: string | null,
): ShiftFigures {
  return {
    shiftNo: `SH-${s.id}`,
    till: "Till",
    branch: s.branch?.name ?? "",
    cashier: nameOf(s),
    opened: when(s.startTime),
    closed: closedAt ? when(closedAt) : "Open",
    openingCash: n(s.startBalance),
    openingMpesa: n(s.openingMpesa),
    sales: {
      cash: t.taken.cash,
      mpesa: t.taken.mpesa,
      card: t.taken.card,
      credit: t.credit,
    },
    cashRefunds: t.refunds.cash,
    mpesaRefunds: t.refunds.mpesa,
    cardRefunds: t.refunds.card,
    drops: t.drops,
    transactions: t.transactions,
    voids: t.voids,
    returns: t.returns,
  };
}

const emptyCount: CloseCount = {
  cash: "",
  leftInDrawer: "",
  mpesa: "",
  card: "",
  note: "",
};
const money = (s: string) => Number(s.replace(/,/g, ""));

/* ------------------------------------- Page ------------------------------------- */

export function ShiftScreen({ view }: { view: "shift" | "balances" }) {
  const { can, loaded } = useMenuPermissions();
  const may = (action: string) => loaded && can("POS/Cashier balances", action);
  const isShift = view === "shift";

  const [loading, setLoading] = React.useState(true);
  const [active, setActive] = React.useState<ActiveShift | null>(null);
  const [lastClose, setLastClose] = React.useState<LastClose | null>(null);
  const [busy, setBusy] = React.useState(false);
  const [dropKey, setDropKey] = React.useState(0);
  const [dropAccounts, setDropAccounts] = React.useState<DropAccount[]>([]);
  const [count, setCount] = React.useState<CloseCount>(emptyCount);
  const [tried, setTried] = React.useState(false);
  const [closedZ, setClosedZ] = React.useState<ZData | null>(null);

  const [from, setFrom] = React.useState(addDays(localToday(), -6));
  const [to, setTo] = React.useState(localToday());
  const [history, setHistory] = React.useState<ApiShift[] | null>(null);
  const [viewing, setViewing] = React.useState<ZData | null>(null);

  const zRef = React.useRef<HTMLDivElement>(null);
  const histRef = React.useRef<HTMLDivElement>(null);

  const loadActive = React.useCallback(async () => {
    try {
      const a = await ShiftsApi.getActive();
      setActive(a?.id ? a : null);
      if (!a?.id) setLastClose(await ShiftsApi.lastClose().catch(() => null));
      else setDropAccounts(await ShiftsApi.dropAccounts().catch(() => []));
    } catch (e) {
      toast.add({
        type: "error",
        title: "Couldn't load your shift",
        description: apiError(e, "Try again."),
      });
    } finally {
      setLoading(false);
    }
  }, []);

  const loadHistory = React.useCallback(async () => {
    setHistory(null);
    try {
      setHistory(
        await ShiftsApi.getHistory(from || undefined, to || undefined),
      );
    } catch (e) {
      setHistory([]);
      toast.add({
        type: "error",
        title: "Couldn't load shift history",
        description: apiError(e, "Try again."),
      });
    }
  }, [from, to]);

  React.useEffect(() => {
    void loadActive();
  }, [loadActive]);
  // A boolean, not `can`: the hook makes a new function every render, which would refetch forever
  const canRead = !isShift && may("Read");
  React.useEffect(() => {
    if (canRead) void loadHistory();
  }, [loadHistory, canRead]);

  const openZ = async (id: number, set: (z: ZData) => void) => {
    try {
      set(await ShiftsApi.getZReport(id));
    } catch (e) {
      toast.add({
        type: "error",
        title: "Couldn't load the Z-report",
        description: apiError(e, "Try again."),
      });
    }
  };

  /* ── The open shift's figures, as the design's Z-report and close form compute them ── */
  const figures = active
    ? figuresOf(active, {
        taken: active.salesByTender,
        credit: active.byMethod.Credit.amount,
        refunds: {
          cash: active.cashRefunds,
          mpesa: active.mpesaRefunds,
          card: active.cardRefunds,
        },
        drops: { cash: active.cashDrops, mpesa: active.mpesaDrops },
        transactions: active.transactions,
        voids: active.voids,
        returns: active.returns,
      })
    : null;
  const expected = figures ? expectedByTender(figures) : null;
  const problems = figures ? closeProblems(count, figures, Infinity) : {};

  const close = async () => {
    setTried(true);
    if (!active || Object.keys(problems).length) return;
    setBusy(true);
    try {
      await ShiftsApi.close({
        actualCash: money(count.cash),
        actualMpesa: money(count.mpesa),
        actualCard: money(count.card),
        leftInDrawer: money(count.leftInDrawer),
        notes: count.note.trim() || undefined,
      });
      await openZ(active.id, setClosedZ);
      toast.add({
        title: "Shift closed",
        description: "Print the Z-report and sign it with your supervisor.",
      });
      setActive(null);
      setCount(emptyCount);
      setTried(false);
      setLastClose(await ShiftsApi.lastClose().catch(() => null));
      void loadHistory();
    } catch (e) {
      toast.add({
        type: "error",
        title: "Shift not closed",
        description: apiError(e, "Try again."),
      });
    } finally {
      setBusy(false);
    }
  };

  const zFigures = (z: ZData) =>
    figuresOf(
      z.shift,
      {
        taken: z.salesByTender,
        credit: z.byMethod.Credit.amount,
        refunds: {
          cash: z.cashRefunds,
          mpesa: z.mpesaRefunds,
          card: z.cardRefunds,
        },
        drops: z.dropTotals,
        transactions: z.salesCount,
        voids: z.voidsCount,
        returns: z.returnsCount,
      },
      z.shift.endTime,
    );
  const zCount = (s: ApiShift) => ({
    cash: n(s.actualCash),
    leftInDrawer: n(s.cashLeft),
    mpesa: n(s.actualMpesa),
    card: n(s.actualCard),
    note: s.notes ?? undefined,
  });
  const ZBlock = ({
    z,
    target,
  }: {
    z: ZData;
    target: React.RefObject<HTMLDivElement | null>;
  }) => {
    // The reprint is rebuilt from today's sales; the close was checked against what was stored then
    const now = expectedByTender(zFigures(z));
    const stored = {
      cash: n(z.shift.expectedCash),
      mpesa: n(z.shift.expectedMpesa),
      card: n(z.shift.expectedCard),
    };
    const changed = (["cash", "mpesa", "card"] as const).filter(
      (k) => Math.abs(now[k] - stored[k]) > 0.005,
    );
    return (
      <div className="space-y-3">
        {z.shift.endTime && changed.length ? (
          <p className="rounded-md border border-status-warning-border bg-status-warning-bg p-2 text-xs text-status-warning-text">
            Sales or refunds in this shift changed after it closed, so this
            reprint differs from the close. At the close the system expected{" "}
            {changed
              .map(
                (k) =>
                  `${{ cash: "cash", mpesa: "M-Pesa", card: "card" }[k]} ${kes(stored[k])}`,
              )
              .join(", ")}
            ; the balances report shows those figures.
          </p>
        ) : null}
        <div className="flex flex-wrap items-center justify-between gap-2">
          {z.shift.cashLeft == null ? (
            <p className="text-xs text-muted-foreground">
              Cash left in the drawer wasn&apos;t recorded for this shift, so it
              prints as 0.
            </p>
          ) : (
            <span />
          )}
          <PrintButton
            target={target}
            paper="receipt-80"
            label="Print Z-report"
          />
        </div>
        <ZReport
          ref={target}
          figures={zFigures(z)}
          count={zCount(z.shift)}
          printedAt={when(new Date().toISOString())}
        />
      </div>
    );
  };

  const balances: ShiftBalance[] = (history ?? []).map((s) => ({
    id: String(s.id),
    date: when(s.endTime),
    till: `SH-${s.id}`,
    cashier: `${nameOf(s)}${s.branch?.name ? ` · ${s.branch.name}` : ""}`,
    tenders: [
      {
        tender: "Cash",
        opening: n(s.startBalance),
        system: n(s.expectedCash),
        counted: n(s.actualCash),
      },
      {
        tender: "M-Pesa",
        opening: n(s.openingMpesa),
        system: n(s.expectedMpesa),
        counted: n(s.actualMpesa),
      },
      {
        tender: "Card",
        opening: 0,
        system: n(s.expectedCard),
        counted: n(s.actualCard),
      },
    ],
  }));

  const myShift = (
    <>
          {loading ? (
            <Loading what="your shift" shape="detail" rows={6} />
          ) : !active && !isShift ? (
            <p className="rounded-lg border border-border bg-card p-6 text-center text-sm text-muted-foreground">
              No shift open. {loaded && (can("POS/Open and close shift", "Create") || can("POS/POS sales", "Create")) ? (
                <Link className="font-medium text-foreground underline" href="/shift">Open one on Open and close shift</Link>
              ) : "Ask someone who can open shifts."}
            </p>
          ) : !active ? (
            <div className="grid gap-4 xl:grid-cols-[1fr_auto]">
              <section className="space-y-3 rounded-lg border border-[var(--color-border-panel)] bg-card p-4">
                <h2 className="text-base font-semibold">Open a shift</h2>
                <OpenShiftForm
                  busy={busy}
                  lastClose={
                    lastClose
                      ? {
                          cashLeft: lastClose.cashLeft,
                          mpesa: lastClose.mpesa,
                          by: lastClose.by,
                          at: when(lastClose.at),
                        }
                      : null
                  }
                  onOpen={async (o) => {
                    setBusy(true);
                    try {
                      await ShiftsApi.open(o.cash, {
                        startMpesa: o.mpesa,
                        note: o.note,
                      });
                      setClosedZ(null);
                      await loadActive();
                      toast.add({
                        title: "Shift opened",
                        description: `${kes(o.cash)} in the drawer, M-Pesa till at ${kes(o.mpesa)}.`,
                      });
                    } catch (e) {
                      toast.add({
                        type: "error",
                        title: "Shift not opened",
                        description: apiError(e, "Try again."),
                      });
                    } finally {
                      setBusy(false);
                    }
                  }}
                />
              </section>
              {closedZ ? (
                <section className="space-y-2 rounded-lg border border-[var(--color-border-panel)] bg-muted/40 p-4">
                  <h2 className="text-base font-semibold">
                    Z-report for the shift you just closed
                  </h2>
                  <ZBlock z={closedZ} target={zRef} />
                </section>
              ) : null}
            </div>
          ) : (
            <>
              <div className="grid gap-4 lg:grid-cols-2">
                <section className="space-y-3 rounded-lg border border-[var(--color-border-panel)] bg-card p-4">
                  <h2 className="text-base font-semibold">
                    Should be there now
                  </h2>
                  <dl className="grid grid-cols-3 gap-3 text-sm tabular-nums">
                    {(
                      [
                        ["Cash drawer", expected!.cash],
                        ["M-Pesa till", expected!.mpesa],
                        ["Card batch", expected!.card],
                      ] as const
                    ).map(([k, v]) => (
                      <div
                        key={k}
                        className="rounded-md border border-border bg-card p-3"
                      >
                        <dt className="text-xs text-muted-foreground">{k}</dt>
                        <dd className="mt-1 text-lg font-semibold">{kes(v)}</dd>
                      </div>
                    ))}
                  </dl>
                  <p className="text-xs text-muted-foreground">
                    Opening {kes(figures!.openingCash)} cash and{" "}
                    {kes(figures!.openingMpesa)} M-Pesa, plus what the till
                    took, less drops and refunds.
                    {active.openingNote
                      ? ` Opening note: ${active.openingNote}`
                      : ""}
                  </p>
                </section>
                <section className="rounded-lg border border-[var(--color-border-panel)] bg-card p-4">
                  <ShiftSales
                    cashier={nameOf(active)}
                    opened={hhmm(active.startTime)}
                    byMethod={active.byMethod}
                    byHour={active.byHour}
                    sales={active.transactions}
                  />
                </section>
              </div>

              {!isShift && may("Create") ? (
                <section className="space-y-3 rounded-lg border border-[var(--color-border-panel)] bg-card p-4">
                  <h2 className="text-base font-semibold">
                    Cash and M-Pesa drops
                  </h2>
                  <DropForm
                    key={dropKey}
                    balances={{
                      Cash: expected!.cash,
                      "M-Pesa": expected!.mpesa,
                    }}
                    accounts={dropAccounts}
                    onSubmit={async (d) => {
                      // The form gives back "code name"; the account is found by its code and kind
                      const account = dropAccounts.find((a) => a.kind === d.kind && `${a.code} ${a.name}` === d.to);
                      try {
                        await ShiftsApi.recordDrop({
                          amount: d.amount,
                          type: d.kind,
                          accountId: account?.id,
                          reference: d.reference,
                          witness: d.witness,
                        });
                        toast.add({
                          title: "Drop recorded",
                          description: `${kes(d.amount)} to ${d.to.trim()}.`,
                        });
                        setDropKey((k) => k + 1);
                        await loadActive();
                      } catch (e) {
                        toast.add({
                          type: "error",
                          title: "Drop not recorded",
                          description: apiError(e, "Try again."),
                        });
                      }
                    }}
                  />
                  {active.drops.length ? (
                    <Table>
                      <TableHeader>
                        <TableRow>
                          <TableHead>Time</TableHead>
                          <TableHead>From</TableHead>
                          <TableHead>To</TableHead>
                          <TableHead>Reference</TableHead>
                          <TableHead>Witness</TableHead>
                          <TableHead className="text-right">Amount</TableHead>
                        </TableRow>
                      </TableHeader>
                      <TableBody>
                        {active.drops.map((d) => (
                          <TableRow key={d.id}>
                            <TableCell>{hhmm(d.createdAt)}</TableCell>
                            <TableCell>
                              {d.type === "Cash"
                                ? "Cash drawer"
                                : "M-Pesa till"}
                            </TableCell>
                            <TableCell>{d.destination}</TableCell>
                            <TableCell className="font-mono">
                              {d.reference || "–"}
                            </TableCell>
                            <TableCell>{d.witness || "–"}</TableCell>
                            <TableCell className="text-right tabular-nums">
                              {kes(n(d.amount))}
                            </TableCell>
                          </TableRow>
                        ))}
                      </TableBody>
                    </Table>
                  ) : null}
                </section>
              ) : null}

              {isShift ? (
              <div className="grid gap-4 xl:grid-cols-[1fr_auto]">
                <section className="space-y-4 rounded-lg border border-[var(--color-border-panel)] bg-card p-4">
                  <h2 className="text-base font-semibold">Close shift</h2>
                  <CloseShiftForm
                    figures={figures!}
                    count={count}
                    onChange={setCount}
                    problems={problems}
                    show={tried}
                  />
                  <div className="flex justify-end">
                    <Button disabled={busy} onClick={() => void close()}>
                      {busy ? <Spinner /> : null}
                      Close shift
                    </Button>
                  </div>
                </section>
                <section className="space-y-2 rounded-lg border border-[var(--color-border-panel)] bg-muted/40 p-4">
                  <h2 className="text-base font-semibold">Z-report preview</h2>
                  <ZReport
                    ref={zRef}
                    figures={figures!}
                    count={{
                      cash: money(count.cash) || 0,
                      leftInDrawer: money(count.leftInDrawer) || 0,
                      mpesa: money(count.mpesa) || 0,
                      card: money(count.card) || 0,
                      note: count.note,
                    }}
                    printedAt={when(new Date().toISOString())}
                  />
                </section>
              </div>
              ) : null}
            </>
          )}
    </>
  );

  return (
    <div className="medora mx-auto w-full max-w-6xl space-y-4">
      <MedoraPageHeader
        title={isShift ? "Open and close shift" : "Cashier balances"}
        description={isShift ? "Open the register with its balances; close it counted, with the Z-report." : "What should be in the drawer and the M-Pesa till, drops and past shifts."}
        meta={
          active
            ? [
                `Shift SH-${active.id} open since ${hhmm(active.startTime)}`,
                active.branch?.name ?? "",
              ].filter(Boolean)
            : []
        }
        more={[
          {
            label: "Refresh",
            icon: RefreshCwIcon,
            onSelect: () => (void loadActive(), canRead && void loadHistory()),
          },
        ]}
      />

      {isShift ? <div className="space-y-4">{myShift}</div> : (
      <Tabs defaultValue="shift">
        <TabsList
          variant="line"
          className="w-full justify-start border-b border-border"
        >
          <TabsTrigger value="shift" className="flex-none">
            My shift
          </TabsTrigger>
          <TabsTrigger value="balances" className="flex-none">
            Opening and closing balances
          </TabsTrigger>
          <TabsTrigger value="history" className="flex-none">
            Z-reports
          </TabsTrigger>
        </TabsList>

        {/* ── My shift ── */}
        <TabsContent value="shift" className="space-y-4 pt-4">
          {myShift}
        </TabsContent>

        {/* ── PS-16 ── */}
        <TabsContent value="balances" className="space-y-3 pt-4">
          <DateRange from={from} to={to} setFrom={setFrom} setTo={setTo} />
          {history === null ? (
            <Loading what="balances" columns={7} rows={5} numeric={[2, 3, 4, 5, 6]} />
          ) : balances.length ? (
            <ShiftBalanceReport shifts={balances} tolerance={0} />
          ) : (
            <p className="py-12 text-center text-sm text-muted-foreground">
              No shifts closed in these dates
            </p>
          )}
          <p className="text-xs text-muted-foreground">
            Any difference is flagged. Shifts closed before 24 Oct 2026 have no
            opening M-Pesa balance, so it shows as 0.
          </p>
        </TabsContent>

        {/* ── Z-reports of closed shifts ── */}
        <TabsContent value="history" className="space-y-3 pt-4">
          <DateRange from={from} to={to} setFrom={setFrom} setTo={setTo} />
          <div className="grid gap-4 xl:grid-cols-[1fr_auto]">
            <div className="overflow-x-auto rounded-md border border-[var(--color-border-panel)] bg-card">
              <Table>
                <TableHeader>
                  <TableRow>
                    <TableHead>Shift</TableHead>
                    <TableHead>Cashier</TableHead>
                    <TableHead>Opened</TableHead>
                    <TableHead>Closed</TableHead>
                    <TableHead className="text-right">Cash difference</TableHead>
                    <TableHead />
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {(history ?? []).map((s) => {
                    const d =
                      Math.round((n(s.actualCash) - n(s.expectedCash)) * 100) /
                      100;
                    return (
                      <TableRow
                        key={s.id}
                        data-state={
                          viewing?.shift.id === s.id ? "selected" : undefined
                        }
                      >
                        <TableCell className="font-medium">SH-{s.id}</TableCell>
                        <TableCell>{nameOf(s)}</TableCell>
                        <TableCell>{when(s.startTime)}</TableCell>
                        <TableCell>{when(s.endTime)}</TableCell>
                        <TableCell
                          className={
                            d === 0
                              ? "text-right text-status-success-text"
                              : "text-right font-medium text-status-error-text"
                          }
                        >
                          {d === 0
                            ? "Balanced"
                            : `${d > 0 ? "Over" : "Short"} ${kes(Math.abs(d))}`}
                        </TableCell>
                        <TableCell className="text-right">
                          <Button
                            size="xs"
                            variant="outline"
                            onClick={() => void openZ(s.id, setViewing)}
                          >
                            Z-report
                          </Button>
                        </TableCell>
                      </TableRow>
                    );
                  })}
                  {history && !history.length ? (
                    <TableRow>
                      <TableCell
                        colSpan={6}
                        className="py-10 text-center text-muted-foreground"
                      >
                        No shifts closed in these dates
                      </TableCell>
                    </TableRow>
                  ) : null}
                </TableBody>
              </Table>
            </div>
            {viewing ? (
              <section className="space-y-2 rounded-lg border border-[var(--color-border-panel)] bg-muted/40 p-4">
                <h2 className="text-base font-semibold">
                  Z-report SH-{viewing.shift.id}
                </h2>
                <ZBlock z={viewing} target={histRef} />
              </section>
            ) : null}
          </div>
        </TabsContent>
      </Tabs>
      )}
    </div>
  );
}

function DateRange({
  from,
  to,
  setFrom,
  setTo,
}: {
  from: string;
  to: string;
  setFrom: (v: string) => void;
  setTo: (v: string) => void;
}) {
  return (
    <Surface className="flex flex-wrap items-end gap-3">
      <Field className="w-auto">
        <FieldLabel htmlFor="sh-from">Closed from</FieldLabel>
        <Input
          id="sh-from"
          type="date"
          value={from}
          max={to}
          onChange={(e) => setFrom(e.target.value)}
        />
      </Field>
      <Field className="w-auto">
        <FieldLabel htmlFor="sh-to">to</FieldLabel>
        <Input
          id="sh-to"
          type="date"
          value={to}
          min={from}
          onChange={(e) => setTo(e.target.value)}
        />
      </Field>
    </Surface>
  );
}
