import type { Metadata } from "next";

import { Example } from "@/components/design-system/example";
import { OnThisPage } from "@/components/design-system/on-this-page";
import { PageHeader } from "@/components/design-system/page-header";
import { OnlineOrdersSection } from "@/components/design-system/sections/orders-bonuses-demo";
import { SalesListSection } from "@/components/design-system/sections/sales-lists-demo";
import { CloseShiftSection } from "@/components/design-system/sections/lists-demo";
import { TillBasketSection } from "@/components/design-system/sections/lists-demo";
import { HeldOrdersSection } from "@/components/design-system/sections/records-more-demo";
import { Section } from "@/components/design-system/section";
import { ApprovalDemos } from "@/components/design-system/sections/approval-demo";
import { BatchPickerDemos } from "@/components/design-system/sections/batch-picker-demo";
import { PosOpsSection } from "@/components/design-system/sections/pos-ops-demo";
import { PosTillPattern } from "@/components/design-system/sections/layout-patterns/pos-till";
import { ShiftsSection } from "@/components/design-system/sections/operations/workflow";
import { ShiftSalesSection } from "@/components/design-system/sections/shift-sales-demo";
import { CompactCartDemos } from "@/components/design-system/sections/cart-compact";
import { PosBarDemos } from "@/components/design-system/sections/pos-bar-demo";
import { UnitsDemos } from "@/components/design-system/sections/units-demo";
import { BarcodeScanInput } from "@/components/medora/barcode-scan-input";
import { CurrencyInput, Money, NumberInput, PhoneInput, QuantityStepper } from "@/components/medora/money";
import { PasscodeInput } from "@/components/medora/passcode-input";
import { CardPayment, MpesaPayment } from "@/components/medora/payments";
import { ProductRow, ProductTile } from "@/components/medora/product";
import { CartLine, CartSummary, HeldSalesList, MpesaStatus, Receipt, TenderPanel, type CartItem } from "@/components/medora/sale";
import { Field, FieldDescription, FieldError, FieldLabel } from "@/components/ui/field";
import { addDays, customers, products, recentSales, TODAY } from "@/lib/mock-data";

export const metadata: Metadata = { title: "Point of sale | Medora Design System" };

const byName = (n: string) => products.find((p) => p.name === n) ?? products[0];
const panadol = byName("Panadol");
const tramadol = byName("Tramadol");
const consult = byName("Medical Consultation");
const outOfStock = { ...byName("Brufen"), stock: 0 };
const lowItem = { ...byName("Amoxil"), stock: 40, minStock: 200 };

const cart: CartItem[] = [
  { id: 1, name: "Panadol 500 mg", strength: "Tablet", unitPrice: 5, qty: 20 },
  { id: 2, name: "Amoxil 500 mg", strength: "Capsule", unitPrice: 15, qty: 21, discount: 1 },
  { id: 3, name: "Medical Consultation", unitPrice: 500, qty: 1, type: "Service" },
];

const heldSales = recentSales.filter((s) => s.status === "Held");
const customerNames = Object.fromEntries(customers.map((c) => [c.id, c.name]));

const receiptData = {
  receiptNo: "RCP-005200",
  date: TODAY,
  time: "14:32",
  cashier: "Kevin Mutua",
  branch: "Westlands Main",
  items: cart,
  deliveryFee: 0,
  method: "Cash" as const,
  tendered: 2000,
};

export default function PosPage() {
  return (
    <>
      <PageHeader
        title="Point of sale"
        description="The till: entering money and quantities, product tiles, the cart, packs and batches, payments, manager approval, returns and online orders, receipts, held sales and the shift. All amounts are KES with tabular numerals. Bright teal appears once: the Pay button."
      />
      <OnThisPage />

      <Section id="pos" title="POS till" description="The whole till screen. Bright teal is a fill with dark text and is reserved for the Pay button.">
        <Example title="POS till" bare>
          <PosTillPattern />
        </Example>
      </Section>

      <Section id="money" title="Money and number entry" description="Display at four sizes, plus the inputs a cashier types into all day.">
        <Example title="Money display" description="sm, md, lg, till" className="flex flex-wrap items-baseline gap-8">
          <Money amount={1250} size="sm" />
          <Money amount={1250} size="md" />
          <Money amount={1250} size="lg" />
          <Money amount={1250} size="till" />
          <Money amount={380} size="md" negative />
        </Example>
        <div className="grid gap-4 md:grid-cols-2">
          <Example title="Currency input" description="Grouped to 2 decimals on blur">
            <div className="grid gap-3">
              <Field>
                <FieldLabel>Default</FieldLabel>
                <CurrencyInput aria-label="Price" defaultValue={1250} />
              </Field>
              <Field>
                <FieldLabel>Empty</FieldLabel>
                <CurrencyInput aria-label="Empty price" />
              </Field>
              <Field>
                <FieldLabel>Error</FieldLabel>
                <CurrencyInput aria-label="Price with error" invalid defaultValue={0} />
                <FieldError>Price must be greater than zero.</FieldError>
              </Field>
              <Field>
                <FieldLabel>Disabled</FieldLabel>
                <CurrencyInput aria-label="Locked price" disabled defaultValue={1250} />
              </Field>
              <Field>
                <FieldLabel>Till size</FieldLabel>
                <CurrencyInput aria-label="Tendered" size="till" defaultValue={2000} />
              </Field>
            </div>
          </Example>
          <Example title="Number input and quantity stepper">
            <div className="grid gap-3">
              <Field>
                <FieldLabel>Reorder level</FieldLabel>
                <NumberInput aria-label="Reorder level" defaultValue={200} unit="units" />
                <FieldDescription>Digits only; clamped to min and max on blur.</FieldDescription>
              </Field>
              <Field>
                <FieldLabel>Error</FieldLabel>
                <NumberInput aria-label="Quantity error" invalid unit="units" />
                <FieldError>Enter a whole number.</FieldError>
              </Field>
              <Field>
                <FieldLabel>Disabled</FieldLabel>
                <NumberInput aria-label="Locked" disabled defaultValue={12} />
              </Field>
              <div className="flex flex-wrap items-center gap-4 pt-1">
                <div className="space-y-1">
                  <p className="text-xs text-muted-foreground">Default</p>
                  <QuantityStepper defaultValue={3} />
                </div>
                <div className="space-y-1">
                  <p className="text-xs text-muted-foreground">At maximum (stock 5)</p>
                  <QuantityStepper defaultValue={5} max={5} />
                </div>
                <div className="space-y-1">
                  <p className="text-xs text-muted-foreground">Compact</p>
                  <QuantityStepper size="sm" defaultValue={1} />
                </div>
                <div className="space-y-1">
                  <p className="text-xs text-muted-foreground">Disabled</p>
                  <QuantityStepper defaultValue={2} disabled />
                </div>
              </div>
            </div>
          </Example>
        </div>
        <div className="grid gap-4 md:grid-cols-2">
          <Example title="Phone input (+254)" description="Accepts 0712..., +254712... or 712...">
            <div className="grid gap-3">
              <Field>
                <FieldLabel>Default</FieldLabel>
                <PhoneInput defaultValue="0712345678" />
              </Field>
              <Field>
                <FieldLabel>Empty</FieldLabel>
                <PhoneInput aria-label="Empty phone" />
              </Field>
              <Field>
                <FieldLabel>Error</FieldLabel>
                <PhoneInput aria-label="Short phone" invalid defaultValue="71234" />
                <FieldError>Enter all 9 digits after +254.</FieldError>
              </Field>
              <Field>
                <FieldLabel>Disabled</FieldLabel>
                <PhoneInput aria-label="Locked phone" disabled defaultValue="712345678" />
              </Field>
            </div>
          </Example>
          <Example title="Passcode input" description="Dots plus on-screen keypad" className="grid gap-6 sm:grid-cols-2">
            <div className="space-y-1">
              <p className="text-center text-xs text-muted-foreground">Default, 2 of 4 entered</p>
              <PasscodeInput defaultValue="24" />
            </div>
            <div className="space-y-1">
              <p className="text-center text-xs text-muted-foreground">Error</p>
              <PasscodeInput defaultValue="2468" error="Incorrect passcode. 2 attempts left." />
            </div>
          </Example>
        </div>
      </Section>

      <Section id="products" title="Product tile and row" description="The POS grid tile and the denser list row. Out of stock disables the tile; services show a SERVICE badge and ignore stock.">
        <Example title="Product tile" description="default, Rx, near expiry, low, out of stock, service, selected, loading" className="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
          <ProductTile today={TODAY} product={panadol} expiryDate={addDays(TODAY, 400)} />
          <ProductTile today={TODAY} product={tramadol} expiryDate={addDays(TODAY, 24)} />
          <ProductTile today={TODAY} product={lowItem} expiryDate={addDays(TODAY, 70)} />
          <ProductTile today={TODAY} product={outOfStock} />
          <ProductTile today={TODAY} product={consult} />
          <ProductTile today={TODAY} product={panadol} selected />
          <ProductTile today={TODAY} product={panadol} loading />
        </Example>
        <Example title="Product list row" bare>
          <ProductRow today={TODAY} product={panadol} expiryDate={addDays(TODAY, 400)} />
          <ProductRow today={TODAY} product={tramadol} expiryDate={addDays(TODAY, 24)} />
          <ProductRow today={TODAY} product={lowItem} expiryDate={addDays(TODAY, 70)} />
          <ProductRow today={TODAY} product={outOfStock} />
          <ProductRow today={TODAY} product={consult} />
        </Example>
      </Section>

      <Section id="cart" title="Cart line and summary" description="Discounts are per unit, as stored. Delivery is folded into the taxable subtotal before VAT, so total always equals subtotal plus VAT.">
        <div className="grid gap-4 md:grid-cols-2">
          <Example title="Cart lines" description="default, discounted, service, disabled" bare>
            <CartLine item={cart[0]} />
            <CartLine item={cart[1]} />
            <CartLine item={cart[2]} />
            <CartLine item={{ ...cart[0], id: 9 }} disabled />
          </Example>
          <div className="space-y-4">
            <Example title="Cart summary">
              <CartSummary items={cart} />
            </Example>
            <Example title="With delivery, held" description="Delivery fee 250.00">
              <CartSummary items={cart} deliveryFee={250} held />
            </Example>
          </div>
        </div>
      </Section>

      <Section
        id="cart-compact"
        title="Cart line and summary: compact version"
        description="A side-panel cart: thumbnail, one-line name, pack and unit price, a − 01 + pill stepper and the line total in teal. Bill details shows savings and Free delivery in green; an Rx notice appears when the basket holds prescription items; one full-width action. Same maths as above: per-unit discounts, delivery folded in before VAT."
      >
        <CompactCartDemos />
      </Section>

      <Section
        id="units"
        title="Units and packs"
        description="Sell by tablet, strip or box. Stock is counted in the base unit (tablets, capsules, ml); each pack has its own price, so bigger packs can be cheaper per tablet and show the saving. Units that stock cannot cover are disabled with the reason, never hidden. In the cart the unit can be changed in the line, with the quantity converted back to base units."
      >
        <UnitsDemos />
      </Section>

      <Section
        id="batch-picker"
        title="Batch picker"
        description="Which batch a sale comes from. Auto takes the earliest-expiring sellable batch first, as stock is deducted, and splits across batches when one cannot cover the quantity. Choose batch overrides it; skipping a batch that expires sooner needs a reason, which is logged. Expired and held (recall, quarantine) batches are listed but cannot be chosen. Units expiring within 90 days come with a note to tell the customer."
      >
        <BatchPickerDemos />
      </Section>

      <Section
        id="approval"
        title="Manager approval"
        description="When a cashier needs something above their authority (a discount over their limit, voiding a completed sale, a large refund, selling below cost) a manager approves it. At the till the manager picks a reason and enters their PIN; wrong PINs count down and lock the pad for 30 s. Or the request goes to a manager's queue and the till waits. Every decision is recorded: who, how, when and why."
      >
        <ApprovalDemos />
      </Section>

      <Section
        id="pos-bar"
        title="POS bar with shift status"
        description="The top strip of the full-screen till: till and branch, the shift (open since, running time, or none), connection and cash-drawer state, held sales, the keyboard map, lock and the cashier menu with Close shift. Light and teal tones. With no shift open the bar offers Open shift, since a till cannot sell without one."
      >
        <PosBarDemos />
      </Section>

      <Section
        id="payments"
        title="Payment methods: M-Pesa and card"
        description="M-Pesa: STK push sends a prompt to the customer's phone; Paybill (business number plus the receipt number as account) and Till (Buy Goods) are paid from the customer's phone, then confirmed with the M-Pesa code or a lookup. Card: the terminal by default, recording type, last 4 and approval code; card not present takes number, expiry, CVV and name laid out as a gateway's hosted fields, so the digits never reach the Medora API and the CVV is never stored. Previews simulate the network: STK confirms after 2.5 s, a card ending 0002 is declined."
      >
        <div className="grid gap-4 md:grid-cols-2">
          <Example title="M-Pesa" description="STK push, Paybill, Till. Try a phone ending 0000 (times out, then turns out paid) or 1111 (times out, not paid)">
            <div className="max-w-sm">
              <MpesaPayment amount={1058} accountRef="RCP-005201" />
            </div>
          </Example>
          <Example title="Card" description="Terminal, card not present (try 4242 4242 4242 4242)">
            <div className="max-w-sm">
              <CardPayment amount={1058} />
            </div>
          </Example>
        </div>
      </Section>

      <Section id="tender" title="Tender panel and M-Pesa" description="The bright teal Pay button, with dark text, is the one accent-filled action in the system. Cash shows change; credit warns when the sale passes the limit.">
        <div className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          <Example title="Cash, enough tendered">
            <TenderPanel total={1058} defaultTendered={2000} />
          </Example>
          <Example title="Cash, short (Pay blocked)">
            <TenderPanel total={1058} defaultTendered={500} />
          </Example>
          <Example title="Credit, over limit (Pay blocked)">
            <TenderPanel total={1058} defaultMethod="Credit" creditLimit={5000} creditBalance={4500} />
          </Example>
          <Example title="Credit, within limit">
            <TenderPanel total={1058} defaultMethod="Credit" creditLimit={10000} creditBalance={2200} />
          </Example>
          <Example title="M-Pesa" description="Complete sale unlocks once M-Pesa confirms">
            <TenderPanel total={1058} defaultMethod="M-Pesa" />
          </Example>
          <Example title="Card" description="Terminal by default; card not present in the second tab">
            <TenderPanel total={1058} defaultMethod="Card" />
          </Example>
          <Example title="Split payment" description="Try KES 500 cash, then M-Pesa for the rest; credit up to the headroom">
            <TenderPanel total={1058} defaultSplit hasCustomer creditLimit={5000} creditBalance={4700} />
          </Example>
          <Example title="Processing">
            <TenderPanel total={1058} defaultTendered={2000} state="processing" />
          </Example>
        </div>
        <Example title="M-Pesa status" description="Waiting, confirmed, failed; and after a timeout: check first, then resend only if M-Pesa confirms it wasn't paid" className="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
          <MpesaStatus state="waiting" phone="+254 712 345 678" amount={1058} />
          <MpesaStatus state="confirmed" phone="+254 712 345 678" amount={1058} receiptNo="SJK4L8P2QX" />
          <MpesaStatus state="failed" phone="+254 712 345 678" amount={1058} />
          <MpesaStatus state="timeout" phone="+254 712 345 678" amount={1058} />
          <MpesaStatus state="checking" phone="+254 712 345 678" amount={1058} />
          <MpesaStatus state="unpaid" phone="+254 712 345 678" amount={1058} />
        </Example>
      </Section>

      <PosOpsSection />
      <OnlineOrdersSection />

      <TillBasketSection />

      <ShiftsSection />

      <ShiftSalesSection />
      <CloseShiftSection />

      <Section id="receipt" title="Receipt" description="Thermal preview at 80 mm and 58 mm. Black logo, no colour. The eTIMS and KRA fields are placeholders until the device is linked.">
        <Example title="Receipt preview" className="flex flex-wrap items-start justify-center gap-8 bg-muted/40">
          <Receipt data={{ ...receiptData, tendered: 2000 }} paper="80mm" />
          <Receipt data={{ ...receiptData, method: "M-Pesa", mpesaRef: "SJK4L8P2QX", tendered: undefined }} paper="58mm" />
        </Example>
      </Section>

      <Section id="held-scan" title="Held sales and barcode scan" description="Parked baskets waiting to be resumed, and the scanner field that adds a product to the cart.">
        <div className="grid gap-4 md:grid-cols-2">
          <Example title="Held sales list" bare>
            <HeldSalesList sales={heldSales} customerNames={customerNames} />
          </Example>
          <div className="space-y-4">
            <Example title="Held sales: empty" bare>
              <HeldSalesList sales={[]} />
            </Example>
            <Example title="Held sales: loading" bare>
              <HeldSalesList sales={[]} loading />
            </Example>
          </div>
        </div>
        <Example title="Barcode scan input" description="Try typing 6161100000137 then Enter" className="grid gap-4 md:grid-cols-2">
          <BarcodeScanInput catalogue={{ [panadol.barcode]: panadol.name }} />
          <BarcodeScanInput initialResult={{ kind: "found", label: "Panadol 500 mg" }} catalogue={{}} />
          <BarcodeScanInput initialResult={{ kind: "not-found", code: "6161100009999" }} />
          <BarcodeScanInput initialResult={{ kind: "lookup" }} />
          <BarcodeScanInput disabled />
        </Example>
      </Section>

      <HeldOrdersSection />
      <SalesListSection />
    </>
  );
}
