"use client";

import * as React from "react";
import { BellRingIcon, ShoppingCartIcon, XIcon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { ApprovalRecord } from "@/components/medora/approval";
import { ConfirmDialog } from "@/components/medora/confirm-dialog";
import {
  DropForm,
  kes,
  LoyaltyRedeem,
  onlineStageBadge,
  OpenShiftForm,
  DeliveryPanel,
  DIRECT_CN_REASONS,
  directCreditProblems,
  preorderBadge,
  ShiftBalanceReport,
  TillCustomerPicker,
  type DeliveryDetails,
  type ShiftBalance,
  type TillCustomer,
  PreorderForm,
  ReturnBuilder,
  RxReview,
  type OnlineOrder,
  type Preorder,
  type ReturnMode,
  type ReturnPick,
  type SoldLine,
} from "@/components/medora/pos-ops";
import { RowActions } from "@/components/medora/row-actions";
import { maskPhone } from "@/components/medora/sensitive";
import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { NativeSelect, NativeSelectOption } from "@/components/ui/native-select";
import { toast } from "@/components/ui/toast";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";

/* ------------------------------------- Returns ------------------------------------- */

const SALE_LINES: SoldLine[] = [
  { id: "l1", name: "Panadol 500 mg, strip of 10", sold: 4, returned: 0, unitPaid: 58 },
  { id: "l2", name: "Amoxil 500 mg capsules, 21s", sold: 1, returned: 0, unitPaid: 380, rx: true },
  { id: "l3", name: "Nivea Soft cream 200 ml", sold: 2, returned: 1, unitPaid: 707.6 },
  { id: "l4", name: "Surgical gloves, box of 100", sold: 1, returned: 1, unitPaid: 1102 },
];

function ReturnsDemo() {
  const [mode, setMode] = React.useState<ReturnMode>("return");
  const [picks, setPicks] = React.useState<Record<string, ReturnPick>>({});
  const [refundBy, setRefundBy] = React.useState("M-Pesa reversal to 07•• ••• 214");
  const [confirming, setConfirming] = React.useState(false);
  const total = Object.entries(picks).reduce((s, [id, p]) => s + p.qty * SALE_LINES.find((l) => l.id === id)!.unitPaid, 0);
  const switchMode = (m: ReturnMode) => {
    setMode(m);
    // Reverse sale takes every unit that hasn't been returned yet.
    setPicks(m === "reverse" ? Object.fromEntries(SALE_LINES.filter((l) => l.sold > l.returned).map((l) => [l.id, { qty: l.sold - l.returned, reason: "Wrong item" as const, restock: true }])) : {});
  };
  return (
    <Example title="Return, exchange or reverse a sale" description="SALE-005188, 18 Oct 2026, Kevin Mutua. Gloves are already fully returned. Pick Amoxil with reason Customer changed mind: an opened prescription item can't go back to stock" bare>
      <div className="flex flex-wrap items-center gap-3 border-b border-border px-4 py-3">
        <ToggleGroup variant="outline" size="sm" spacing={0} aria-label="What to do" value={[mode]} onValueChange={(v: string[]) => v[0] && switchMode(v[0] as ReturnMode)}>
          <ToggleGroupItem value="return">Return</ToggleGroupItem>
          <ToggleGroupItem value="exchange">Exchange</ToggleGroupItem>
          <ToggleGroupItem value="reverse">Reverse sale</ToggleGroupItem>
        </ToggleGroup>
        {mode === "reverse" ? <span className="text-xs text-muted-foreground">Voids every remaining line; needs a manager&apos;s approval.</span> : null}
      </div>
      <div className="space-y-4 p-4">
        <ReturnBuilder lines={SALE_LINES} mode={mode} picks={picks} onChange={setPicks} />
        <div className="flex flex-wrap items-end justify-end gap-3">
          {mode !== "exchange" ? (
            <Field className="w-72">
              <FieldLabel htmlFor="refund-by">Refund by</FieldLabel>
              <NativeSelect id="refund-by" value={refundBy} onChange={(e) => setRefundBy(e.target.value)}>
                <NativeSelectOption>M-Pesa reversal to 07•• ••• 214</NativeSelectOption>
                <NativeSelectOption>Cash from the drawer</NativeSelectOption>
                <NativeSelectOption>Credit on the customer&apos;s account</NativeSelectOption>
              </NativeSelect>
            </Field>
          ) : null}
          <Button disabled={total === 0} onClick={() => setConfirming(true)}>
            {mode === "exchange" ? "Continue to new items" : mode === "reverse" ? "Reverse sale…" : `Refund ${kes(total)}`}
          </Button>
        </div>
      </div>
      <ConfirmDialog
        open={confirming}
        onOpenChange={setConfirming}
        level={mode === "reverse" ? "B" : "A"}
        title={mode === "reverse" ? "Reverse sale SALE-005188?" : mode === "exchange" ? `Put ${kes(total)} towards new items?` : `Refund ${kes(total)}?`}
        consequences={[mode === "exchange" ? "The credit is applied to the new basket; any difference is paid or refunded at the till." : `Refunded by ${refundBy.toLowerCase()}.`, "A credit note is created and sent to KRA eTIMS.", "Items marked Back to stock return to the Front shop; the rest are written off."]}
        reasons={mode === "reverse" ? ["Wrong customer", "Rang up in error", "Payment failed after printing", "Other"] : undefined}
        approvalNote={mode === "reverse" ? "A manager approves before the sale is reversed." : undefined}
        actionLabel={mode === "reverse" ? "Request reversal" : mode === "exchange" ? "Continue" : "Refund"}
        onConfirm={async () => {
          await new Promise((r) => setTimeout(r, 600));
          toast.add({ title: mode === "reverse" ? "Reversal sent for approval" : mode === "exchange" ? "Credit applied: add the new items" : `Credit note CN-2026-0092 · ${kes(total)} refunded` });
          setPicks({});
        }}
      />
    </Example>
  );
}

/* ---------------------------------- Online orders ---------------------------------- */

const ORDER: OnlineOrder = {
  ref: "WEB-2026-0318",
  customer: "Mary Wambui",
  phone: "0712 345 678",
  placedAt: "20 Oct 2026, 13:42",
  fulfilment: "Delivery",
  address: "Riverside Drive, Nairobi",
  paid: { method: "M-Pesa", amount: 1460, status: "Paid" },
  items: [
    { name: "Augmentin 625 mg, 14s", qty: 1, rx: true },
    { name: "Panadol 500 mg, strip of 10", qty: 2 },
  ],
  prescription: { file: "prescription-mary-wambui.jpg", doctor: "Dr. A. Otieno, Nairobi Hospital" },
  stage: "rx-review",
};

function OnlineOrderDemo() {
  const [order, setOrder] = React.useState(ORDER);
  const approved = order.prescription?.decision?.approved;
  const next =
    order.stage === "packing"
      ? { label: order.fulfilment === "Delivery" ? "Hand to rider" : "Mark ready for pickup", to: order.fulfilment === "Delivery" ? "dispatched" : "ready" }
      : order.stage === "dispatched" || order.stage === "ready"
        ? { label: "Mark delivered", to: "delivered" }
        : null;
  return (
    <Example title="Online order with a prescription" description="Prescription items can't be packed until a pharmacist approves the upload; rejecting needs a reason" bare>
      <div className="flex flex-wrap items-start justify-between gap-3 border-b border-border px-4 py-3">
        <div>
          <p className="flex flex-wrap items-center gap-2 font-semibold">
            <span className="font-mono">{order.ref}</span> {onlineStageBadge(order.stage)}
          </p>
          <p className="text-sm text-muted-foreground">
            {order.customer} · <span aria-hidden>{maskPhone(order.phone)}</span>
            <span className="sr-only">phone ending {order.phone.slice(-3)}</span> · {order.fulfilment} to {order.address} · {order.paid.method} {kes(order.paid.amount)}, {order.paid.status.toLowerCase()}
          </p>
        </div>
        <div className="flex gap-2">
          {order.stage === "new" || order.stage === "rx-review" ? (
            <Button size="sm" disabled title="Approve the prescription first">
              Start packing
            </Button>
          ) : null}
          {next ? (
            <Button size="sm" onClick={() => setOrder({ ...order, stage: next.to as OnlineOrder["stage"] })}>
              {next.label}
            </Button>
          ) : null}
        </div>
      </div>
      <div className="p-4">
        <RxReview
          order={order}
          reviewer="Grace Wanjiru"
          onDecide={(d) => {
            setOrder({ ...order, stage: d.approved ? "packing" : "rx-rejected", prescription: { ...order.prescription!, decision: { approved: d.approved, by: "Grace Wanjiru", at: "20 Oct 2026, 14:05", reason: d.reason } } });
            toast.add({ title: d.approved ? "Prescription approved" : "Prescription rejected", description: d.approved ? "Packing can start." : "The customer is told why and the payment is refunded." });
          }}
        />
        {approved === false ? <p className="mt-3 text-sm text-muted-foreground">The order is closed and {kes(order.paid.amount)} refunded to M-Pesa.</p> : null}
      </div>
    </Example>
  );
}

/* ------------------------------------- Preorders ------------------------------------- */

const PREORDERS: Preorder[] = [
  { ref: "PRE-0041", customer: "John Otieno", phone: "0722 111 222", item: "Symbicort 160/4.5 inhaler", qty: 1, deposit: 2000, status: "Stock arrived", placed: "15 Oct" },
  { ref: "PRE-0042", customer: "Faith Njeri", phone: "0110 222 333", item: "Ensure vanilla 850 g", qty: 2, deposit: 0, status: "Waiting for stock", placed: "17 Oct" },
  { ref: "PRE-0038", customer: "Ali Hassan", phone: "0733 000 111", item: "Insulin glargine pen", qty: 3, deposit: 3000, status: "Collected", placed: "9 Oct" },
];

function PreordersDemo() {
  const [rows, setRows] = React.useState(PREORDERS);
  const set = (ref: string, patch: Partial<Preorder>) => setRows((xs) => xs.map((x) => (x.ref === ref ? { ...x, ...patch } : x)));
  return (
    <Example title="Preorders" description="For items out of stock. Take one with a phone number and an optional deposit; when stock arrives, tell the customer, then turn it into a sale with the deposit already counted" bare>
      <div className="border-b border-border p-4">
        <PreorderForm
          items={[
            { name: "Symbicort 160/4.5 inhaler", price: 4200 },
            { name: "Ensure vanilla 850 g", price: 3650 },
            { name: "Insulin glargine pen", price: 1980 },
          ]}
          onSave={(p) => {
            const ref = `PRE-00${43 + rows.length - 3}`;
            setRows((xs) => [{ ref, ...p, status: "Waiting for stock", placed: "20 Oct" }, ...xs]);
            toast.add({ title: `Preorder ${ref} saved`, description: `${p.customer} is texted when ${p.item} arrives.` });
          }}
        />
      </div>
      <div className="overflow-x-auto">
        <table className="w-full border-collapse text-sm">
          <thead className="bg-[var(--color-bg-surface-subtle)] text-left text-xs text-muted-foreground">
            <tr>
              {["Order", "Customer", "Item", "Deposit", "Status", ""].map((h, i) => (
                <th key={i} scope="col" className={`px-3 py-2 font-medium ${h === "Deposit" ? "text-right" : ""}`}>
                  {h || <span className="sr-only">Actions</span>}
                </th>
              ))}
            </tr>
          </thead>
          <tbody className="divide-y divide-[var(--color-border-subtle)]">
            {rows.map((p) => (
              <tr key={p.ref}>
                <td className="px-3 py-2 font-mono text-xs">
                  {p.ref}
                  <span className="block font-sans text-muted-foreground">{p.placed}</span>
                </td>
                <td className="px-3 py-2">{p.customer}</td>
                <td className="px-3 py-2">
                  {p.item} × {p.qty}
                </td>
                <td className="px-3 py-2 text-right tabular-nums">{p.deposit ? kes(p.deposit) : "–"}</td>
                <td className="px-3 py-2">
                  {preorderBadge(p.status)}
                  {p.notified ? <span className="mt-0.5 block text-xs text-muted-foreground">Told by SMS {p.notified}</span> : null}
                </td>
                <td className="px-2 py-2 text-right">
                  <RowActions
                    label={p.ref}
                    actions={
                      p.status === "Stock arrived"
                        ? [
                            { label: "Tell the customer (SMS)", icon: BellRingIcon, onSelect: () => (set(p.ref, { notified: "14:10" }), toast.add({ title: `SMS sent to ${p.customer}` })) },
                            { label: "Turn into a sale", icon: ShoppingCartIcon, onSelect: () => (set(p.ref, { status: "Collected" }), toast.add({ title: `${p.ref} opened at the till`, description: p.deposit ? `${kes(p.deposit)} deposit already paid.` : undefined })) },
                            { label: "Cancel and refund deposit", icon: XIcon, destructive: true, onSelect: () => set(p.ref, { status: "Cancelled" }) },
                          ]
                        : p.status === "Waiting for stock"
                          ? [{ label: "Cancel and refund deposit", icon: XIcon, destructive: true, onSelect: () => set(p.ref, { status: "Cancelled" }) }]
                          : []
                    }
                  />
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </Example>
  );
}

/* --------------------------- Drops, open shift, loyalty --------------------------- */

function TillMoneyDemo() {
  const [balances, setBalances] = React.useState({ Cash: 48250, "M-Pesa": 64300 });
  const [shiftOpen, setShiftOpen] = React.useState(false);
  const [points, setPoints] = React.useState(0);
  return (
    <div className="grid gap-4 lg:grid-cols-2">
      <Example title="Cash and M-Pesa drops" description="Money out of the drawer or till to an account. Can't exceed what's there; a cash drop needs a witness">
        <DropForm
          balances={balances}
          accounts={[
            { code: "1040", name: "Equity Bank", kind: "Cash" },
            { code: "1005", name: "Head-office safe", kind: "Cash" },
            { code: "1040", name: "Equity Bank (sweep)", kind: "M-Pesa" },
          ]}
          onSubmit={(d) => {
            setBalances((b) => ({ ...b, [d.kind]: Math.round((b[d.kind] - d.amount) * 100) / 100 }));
            toast.add({ title: `Drop DRP-2026-0142 recorded`, description: `${kes(d.amount)} to ${d.to}.` });
          }}
        />
      </Example>
      <div className="space-y-4">
        <Example title="Open a shift" description="Cash counted and the M-Pesa till balance; a difference from the last close needs a note">
          {shiftOpen ? (
            <p className="text-sm">
              Shift open. <button type="button" className="cursor-pointer text-primary underline-offset-2 hover:underline" onClick={() => setShiftOpen(false)}>Reset demo</button>
            </p>
          ) : (
            <OpenShiftForm
              lastClose={{ cashLeft: 5000, mpesa: 0, by: "Kevin Mutua", at: "19 Oct 2026, 21:04" }}
              onOpen={(o) => {
                setShiftOpen(true);
                toast.add({ title: "Shift opened", description: `${kes(o.cash)} in the drawer${o.note ? `; note: ${o.note}` : ""}.` });
              }}
            />
          )}
        </Example>
        <Example title="Loyalty points at the till" description="Mary Wambui, 1,240 points at KES 1 each, used in blocks of 100. Basket KES 1,189.00">
          <LoyaltyRedeem points={1240} kesPerPoint={1} block={100} basket={1189} applied={points} onApply={(p) => (setPoints(p), toast.add({ title: p ? `${kes(p)} taken off with ${p} points` : "Points removed" }))} />
        </Example>
      </div>
    </div>
  );
}

/* -------------------- Customer, delivery, credit note, shift balances -------------------- */

const TILL_CUSTOMERS: TillCustomer[] = [
  { id: 1, name: "Mary Wambui", phone: "0712 345 678", memberNo: "AAR-449120-01", priceGroup: { name: "Insurance", discountPct: 5 }, points: 1240, creditHeadroom: 16702.8, scheme: "AAR Outpatient Gold", allergy: "Penicillin" },
  { id: 2, name: "Aga Khan Hospital", phone: "0720 366 200", priceGroup: { name: "Corporate", discountPct: 8 }, vatExempt: true, creditHeadroom: 115700 },
  { id: 3, name: "John Otieno", phone: "0722 111 222", points: 310 },
];

function TillCustomerDemo() {
  const [customers, setCustomers] = React.useState(TILL_CUSTOMERS);
  const [selected, setSelected] = React.useState<TillCustomer | null>(null);
  return (
    <Example title="Customer at the till" description="Search by name, phone or member number; or add with just a name and phone. Try typing 0712 345 678 in Add new: it offers Mary instead of a duplicate">
      <div className="max-w-md">
        <TillCustomerPicker
          customers={customers}
          selected={selected}
          onSelect={setSelected}
          onAdd={(c) => {
            const added = { id: customers.length + 1, ...c, points: 0 };
            setCustomers((xs) => [...xs, added]);
            toast.add({ title: `${c.name} added`, description: "Enrolled in loyalty from this sale." });
            return added;
          }}
        />
      </div>
    </Example>
  );
}

function DeliveryDemo() {
  const [d, setD] = React.useState<DeliveryDetails>({ on: true, zone: "Westlands", fee: "200", destination: "", pickup: "Westlands Main", by: "Own rider", rider: "Ali Hassan", riderPhone: "0733 000 111", company: "", cost: "150" });
  const [basket, setBasket] = React.useState(1189);
  return (
    <Example title="Delivery" description="The zone fills in the fee; free above KES 3,000. Records who carries it and what it costs, for delivery margin">
      <div className="space-y-2">
        <label className="flex items-center gap-2 text-sm">
          Basket
          <NativeSelect size="sm" aria-label="Basket total" value={String(basket)} onChange={(e) => setBasket(Number(e.target.value))}>
            <NativeSelectOption value="1189">KES 1,189.00</NativeSelectOption>
            <NativeSelectOption value="3450">KES 3,450.00</NativeSelectOption>
          </NativeSelect>
        </label>
        <DeliveryPanel value={d} onChange={setD} basket={basket} freeAbove={3000} zones={[{ name: "Westlands", fee: 200 }, { name: "Kilimani", fee: 300 }, { name: "Karen", fee: 500 }]} />
      </div>
    </Example>
  );
}

function DirectCreditDemo() {
  const [f, setF] = React.useState({ customer: "", amount: "", reason: "", details: "" });
  const [tried, setTried] = React.useState(false);
  const [sent, setSent] = React.useState(false);
  const problems = directCreditProblems({ ...f, customer: f.customer || undefined }, 5000);
  if (sent)
    return (
      <Example title="Direct credit note" description="Sent for approval; nothing reaches the customer's account until it's approved">
        <ApprovalRecord request={{ id: "DCN-2026-0012", action: "refund", title: `Credit ${kes(Number(f.amount.replace(/,/g, "")))} to ${f.customer}`, why: `${f.reason}${f.details ? `: ${f.details}` : ""}`, requestedBy: "Kevin Mutua (Cashier)", requestedAt: new Date(`${"2026-10-20"}T14:40:00`) }} />
      </Example>
    );
  return (
    <Example title="Direct credit note" description="A credit for a customer without a sale: registered customers only, with a reason, and approved before it applies">
      <div className="space-y-3">
        <div className="grid gap-3 sm:grid-cols-2">
          <Field>
            <FieldLabel htmlFor="dcn-cust">Customer</FieldLabel>
            <NativeSelect id="dcn-cust" value={f.customer} onChange={(e) => setF({ ...f, customer: e.target.value })}>
              <NativeSelectOption value="">Choose a customer</NativeSelectOption>
              {TILL_CUSTOMERS.map((c) => (
                <NativeSelectOption key={c.id}>{c.name}</NativeSelectOption>
              ))}
            </NativeSelect>
          </Field>
          <Field>
            <FieldLabel htmlFor="dcn-amount">Amount (KES)</FieldLabel>
            <Input id="dcn-amount" inputMode="decimal" className="tabular-nums" value={f.amount} onChange={(e) => setF({ ...f, amount: e.target.value })} />
          </Field>
          <Field>
            <FieldLabel htmlFor="dcn-reason">Reason</FieldLabel>
            <NativeSelect id="dcn-reason" value={f.reason} onChange={(e) => setF({ ...f, reason: e.target.value })}>
              <NativeSelectOption value="">Choose a reason</NativeSelectOption>
              {DIRECT_CN_REASONS.map((r) => (
                <NativeSelectOption key={r}>{r}</NativeSelectOption>
              ))}
            </NativeSelect>
          </Field>
          <Field>
            <FieldLabel htmlFor="dcn-details">Details{f.reason === "Other" ? "" : " (optional)"}</FieldLabel>
            <Input id="dcn-details" value={f.details} onChange={(e) => setF({ ...f, details: e.target.value })} />
          </Field>
        </div>
        {tried && problems.length ? (
          <ul role="alert" className="list-disc rounded-md border border-status-error-border bg-status-error-bg py-2 pr-3 pl-8 text-sm text-status-error-text">
            {problems.map((p) => (
              <li key={p}>{p}</li>
            ))}
          </ul>
        ) : null}
        <div className="flex justify-end">
          <Button
            onClick={() => {
              setTried(true);
              if (!problems.length) setSent(true);
            }}
          >
            Send for approval
          </Button>
        </div>
      </div>
    </Example>
  );
}

const SHIFTS: ShiftBalance[] = [
  {
    id: "z1",
    date: "20 Oct",
    till: "Till 1",
    cashier: "Kevin Mutua",
    tenders: [
      { tender: "Cash", opening: 5000, system: 48250, counted: 48050 },
      { tender: "M-Pesa", opening: 0, system: 64300, counted: 64300 },
      { tender: "Card", opening: 0, system: 12800, counted: 12800 },
    ],
  },
  {
    id: "z2",
    date: "19 Oct",
    till: "Till 1",
    cashier: "Faith Njeri",
    tenders: [
      { tender: "Cash", opening: 5000, system: 39120, counted: 39150 },
      { tender: "M-Pesa", opening: 0, system: 51900, counted: 51900 },
      { tender: "Card", opening: 0, system: 8400, counted: 8400 },
    ],
  },
];

export function PosOpsSection() {
  return (
    <Section
      id="pos-ops"
      title="Returns, online orders, preorders and till money"
      description="Till work beyond selling. Returns pick lines from the original sale, can't return more than was sold, and decide stock by reason. Online orders wait for a pharmacist to approve the uploaded prescription. Preorders turn into sales when stock arrives. Drops, opening a shift and loyalty points each check the amount against what's actually there."
    >
      <ReturnsDemo />
      <OnlineOrderDemo />
      <PreordersDemo />
      <TillMoneyDemo />
      <div className="grid gap-4 lg:grid-cols-2">
        <TillCustomerDemo />
        <DeliveryDemo />
      </div>
      <DirectCreditDemo />
      <Example title="Opening and closing balances" description="Each shift against what the system expected, per tender. A difference over KES 100 is a mismatch">
        <ShiftBalanceReport shifts={SHIFTS} tolerance={100} />
      </Example>
    </Section>
  );
}
