"use client";

import * as React from "react";
import { PrinterIcon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { EditableGrid, gridErrors } from "@/components/medora/editable-grid";
import { Stepper } from "@/components/medora/stepper";
import { Wizard } from "@/components/medora/wizard";
import { Button } from "@/components/ui/button";
import { Field, FieldDescription, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { Table, TableBody, TableCell, TableFooter, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { toast } from "@/components/ui/toast";
import { formatDate } from "@/lib/mock-data";
import { cn } from "@/lib/utils";

import { grnColumns, grnRows, useGridData } from "./grid-demo";

const POS = [
  { id: "PO-2041", supplier: "Dawa Distributors Ltd", lines: 4, ordered: "18 Oct 2026", value: 16110 },
  { id: "PO-2044", supplier: "Harleys Ltd", lines: 7, ordered: "19 Oct 2026", value: 48250 },
];

const kes = (n: number) => `KES ${n.toLocaleString("en-US", { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;

function ReceivingWizard({ onRestart }: { onRestart: () => void }) {
  const [po, setPo] = React.useState<string>("");
  const [invoice, setInvoice] = React.useState("");
  const [deliveryNote, setDeliveryNote] = React.useState("");
  const g = useGridData(grnRows);

  const merged = g.rows.map((r) => ({ row: r, v: { ...r.values, ...(g.draft[r.id] ?? {}) } }));
  const received = merged.filter((m) => Number(m.v.received || 0) > 0);
  const units = received.reduce((s, m) => s + Number(m.v.received), 0);
  const value = received.reduce((s, m) => s + Number(m.v.received) * Number(m.v.cost || 0), 0);
  const dirty = !!po || !!invoice || Object.keys(g.draft).length > 0;
  const chosen = POS.find((p) => p.id === po);

  return (
    <Wizard
      title="Receive goods"
      steps={[
        {
          label: "Purchase order",
          sub: "and supplier invoice",
          heading: "Which order is this delivery for?",
          validate: () => [
            ...(po ? [] : ["Choose the purchase order this delivery is for."]),
            ...(invoice.trim() ? (/^[A-Za-z0-9\-/]{3,}$/.test(invoice.trim()) ? [] : ["The supplier invoice number can only have letters, numbers, - and /."]) : ["Enter the supplier invoice number from the paperwork."]),
          ],
          content: (
            <div className="space-y-4">
              <div role="radiogroup" aria-label="Purchase order" className="grid gap-2 sm:grid-cols-2">
                {POS.map((p) => (
                  <button
                    key={p.id}
                    type="button"
                    role="radio"
                    aria-checked={po === p.id}
                    onClick={() => setPo(p.id)}
                    className={cn("cursor-pointer rounded-lg border p-3 text-left outline-none focus-visible:ring-2 focus-visible:ring-ring", po === p.id ? "border-primary bg-accent" : "border-border hover:bg-muted/60")}
                  >
                    <span className="flex items-baseline justify-between gap-2">
                      <span className="font-mono text-sm font-semibold">{p.id}</span>
                      <span className="text-sm tabular-nums">{kes(p.value)}</span>
                    </span>
                    <span className="block text-sm">{p.supplier}</span>
                    <span className="block text-xs text-muted-foreground">
                      {p.lines} lines · ordered {p.ordered}
                    </span>
                  </button>
                ))}
              </div>
              <div className="grid gap-3 sm:grid-cols-2">
                <Field>
                  <FieldLabel htmlFor="grn-invoice">Supplier invoice number</FieldLabel>
                  <Input id="grn-invoice" value={invoice} onChange={(e) => setInvoice(e.target.value)} placeholder="e.g. INV-783" />
                  <FieldDescription>Links the delivery to the supplier&apos;s bill in payables.</FieldDescription>
                </Field>
                <Field>
                  <FieldLabel htmlFor="grn-dn">Delivery note number (optional)</FieldLabel>
                  <Input id="grn-dn" value={deliveryNote} onChange={(e) => setDeliveryNote(e.target.value)} />
                </Field>
              </div>
            </div>
          ),
        },
        {
          label: "Receive lines",
          sub: "quantity, batch, expiry",
          heading: `What arrived on ${po || "this order"}?`,
          wide: true,
          validate: () => {
            const errs = gridErrors(grnColumns, g.rows, g.draft, true);
            return [
              ...(received.length ? [] : ["Enter the received quantity for at least one line."]),
              ...(errs.size ? [`${errs.size} ${errs.size === 1 ? "cell needs" : "cells need"} attention in the lines below.`] : []),
            ];
          },
          content: (
            <EditableGrid
              caption={`Lines received on ${po}`}
              columns={grnColumns}
              rows={g.rows}
              draft={g.draft}
              updating={g.updating}
              saving={g.saving}
              onDraftChange={g.onDraftChange}
              onSaveDraft={g.saveDraft}
              onDiscard={g.discard}
            />
          ),
        },
        {
          label: "Review",
          heading: "Check before receiving",
          wide: true,
          content: ({ goTo }) => (
            <div className="space-y-4">
              <dl className="grid gap-px overflow-hidden rounded-lg border border-border bg-border text-sm sm:grid-cols-4">
                {[
                  ["Order", chosen ? `${chosen.id} · ${chosen.supplier}` : "–", 0],
                  ["Supplier invoice", invoice || "–", 0],
                  ["Lines received", `${received.length} of ${g.rows.length}`, 1],
                  ["Value at cost", kes(value), 1],
                ].map(([k, v, step]) => (
                  <div key={k as string} className="bg-card px-3 py-2.5">
                    <dt className="flex items-center justify-between text-xs text-muted-foreground">
                      {k}
                      <button type="button" className="cursor-pointer font-medium text-primary underline-offset-2 hover:underline" onClick={() => goTo(step as number)} aria-label={`Edit ${(k as string).toLowerCase()}`}>
                        Edit
                      </button>
                    </dt>
                    <dd className="mt-0.5 font-semibold tabular-nums">{v}</dd>
                  </div>
                ))}
              </dl>
              <Table className="text-sm">
                <TableHeader>
                  <TableRow>
                    <TableHead>Item</TableHead>
                    <TableHead>Batch</TableHead>
                    <TableHead>Expiry</TableHead>
                    <TableHead className="text-right">Received</TableHead>
                    <TableHead className="text-right">Unit cost</TableHead>
                    <TableHead className="text-right">Value</TableHead>
                  </TableRow>
                </TableHeader>
                <TableBody>
                  {received.map(({ row, v }) => (
                    <TableRow key={row.id}>
                      <TableCell className="font-medium">{row.header}</TableCell>
                      <TableCell className="font-mono text-xs">{v.batch}</TableCell>
                      <TableCell>{v.expiry ? formatDate(v.expiry) : "–"}</TableCell>
                      <TableCell className="text-right tabular-nums">
                        {Number(v.received).toLocaleString("en-US")} of {v.ordered}
                      </TableCell>
                      <TableCell className="text-right tabular-nums">{Number(v.cost).toFixed(2)}</TableCell>
                      <TableCell className="text-right tabular-nums">{kes(Number(v.received) * Number(v.cost))}</TableCell>
                    </TableRow>
                  ))}
                </TableBody>
                <TableFooter>
                  <TableRow>
                    <TableCell colSpan={3}>Total, {received.length} lines</TableCell>
                    <TableCell className="text-right tabular-nums">{units.toLocaleString("en-US")} units</TableCell>
                    <TableCell />
                    <TableCell className="text-right font-semibold tabular-nums">{kes(value)}</TableCell>
                  </TableRow>
                </TableFooter>
              </Table>
              {received.length < g.rows.length ? (
                <p className="text-sm text-muted-foreground">
                  {g.rows.length - received.length} {g.rows.length - received.length === 1 ? "line stays" : "lines stay"} open on {po} for a later delivery.
                </p>
              ) : null}
            </div>
          ),
        },
      ]}
      dirty={dirty}
      onDiscard={() => {
        setPo("");
        setInvoice("");
        setDeliveryNote("");
        g.discard();
      }}
      commitLabel={`Receive ${units.toLocaleString("en-US")} units`}
      busyLabel="Receiving…"
      confirm={{
        level: "A",
        title: `Receive goods against ${po}?`,
        consequences: [`${units.toLocaleString("en-US")} units in ${received.length} new batches are added to stock at Westlands Main.`, `Supplier invoice ${invoice} for ${kes(value)} is added to ${chosen?.supplier ?? "the supplier"}'s balance.`],
      }}
      onCommit={async () => {
        await new Promise((r) => setTimeout(r, 1100));
        return {
          title: "Goods received",
          reference: "GRN-2026-0187",
          lines: [
            `${units.toLocaleString("en-US")} units added to stock in ${received.length} batches.`,
            `Supplier invoice ${invoice} (${kes(value)}) added to ${chosen?.supplier}'s payables.`,
            received.length < g.rows.length ? `${po} is now Partly received; ${g.rows.length - received.length} lines stay open.` : `${po} is now Received.`,
          ],
          actions: (
            <Button onClick={() => toast.add({ title: "Printing GRN-2026-0187", description: "Design-system preview." })}>
              <PrinterIcon data-icon="inline-start" />
              Print GRN
            </Button>
          ),
        };
      }}
      onCancel={() => toast.add({ title: "Receiving cancelled", description: "Nothing was saved." })}
      onRestart={onRestart}
    />
  );
}

export function WizardSection() {
  const [run, setRun] = React.useState(0);
  return (
    <Section
      id="wizard"
      title="Wizard and stepper"
      description="For tasks done in order and committed once at the end: goods receiving, returns, shift close, stock take, payroll. Next checks the step and lists what to fix; you can't skip ahead, but finished steps can be revisited. The last step is always a review with Edit links. The commit button names the outcome, can't be pressed twice, and confirms first when it can't be undone. The result shows the reference and what happens next. Narrow screens get the compact stepper."
    >
      <Example title="Receive goods (GRN)" description="Try Next with nothing filled; receive two lines in the grid; Edit from the review; Cancel with data entered" bare>
        <div className="px-4 pt-4">
          <ReceivingWizard key={run} onRestart={() => setRun((r) => r + 1)} />
        </div>
      </Example>
      <div className="space-y-4">
        <Example title="Stepper states" description="Done (can go back), needs attention, done, current (compact below about 576 px wide)">
          <Stepper
            steps={[{ label: "Find sale" }, { label: "Choose items" }, { label: "Refund" }, { label: "Review" }]}
            current={3}
            done={new Set([0, 2])}
            errors={new Set([1])}
            onStepClick={(i) => toast.add({ title: `Back to step ${i + 1}` })}
          />
        </Example>
        <Example title="Compact" description="Narrow screens and the till">
          <div className="max-w-xs">
            <Stepper steps={[{ label: "Count cash" }, { label: "M-Pesa and card" }, { label: "Review variance" }]} current={1} done={new Set([0])} />
          </div>
        </Example>
      </div>
    </Section>
  );
}
