"use client";

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

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import {
  batchCorrectionCheck,
  BranchTotals,
  CustomerForm,
  customerProblems,
  groupProblem,
  MergePreview,
  PriceGroupGrid,
  restoreBlock,
  SupplierChoice,
  SupplierReturnLines,
  type CustomerDraft,
  type CustomerGroup,
  type DeletedProduct,
  type MergeProduct,
  type ReturnableBatch,
} from "@/components/medora/catalog-ops";
import { ConfirmDialog } from "@/components/medora/confirm-dialog";
import { PriceGroupCsv } from "@/components/medora/setup-more";
import { DiffView } from "@/components/medora/diff-view";
import { Button } from "@/components/ui/button";
import { Field, FieldLabel } from "@/components/ui/field";
import { Input } from "@/components/ui/input";
import { toast } from "@/components/ui/toast";
import { formatDate, TODAY } from "@/lib/mock-data";

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

/* ---------------------------------- Price groups ---------------------------------- */

function PriceGroupsDemo() {
  const [prices, setPrices] = React.useState<Record<string, string>>({ "1:Insurance": "55", "1:Corporate": "48", "2:Corporate": "360", "3:Staff": "590" });
  return (
    <Example title="Price-group prices" description="One column per group beside retail. Empty pays retail. Type 25 for Panadol under Staff: it's below cost. Or download the prices, edit them and upload the file">
      <PriceGroupGrid
        products={[
          { id: 1, name: "Panadol 500 mg, strip of 10", cost: 30, retail: 58 },
          { id: 2, name: "Amoxil 500 mg capsules, 21s", cost: 290, retail: 380 },
          { id: 3, name: "Nivea Soft cream 200 ml", cost: 450, retail: 610 },
        ]}
        groups={["Insurance", "Corporate", "Staff"]}
        prices={prices}
        onChange={(k, v) => setPrices((p) => ({ ...p, [k]: v }))}
      />
      <div className="mt-4 border-t border-[var(--color-border-subtle)] pt-4">
        <PriceGroupCsv
          products={[
            { id: 1, code: "ANL-0007", name: "Panadol 500 mg, strip of 10", cost: 30 },
            { id: 2, code: "ANT-0031", name: "Amoxil 500 mg capsules, 21s", cost: 290 },
            { id: 3, code: "DER-0019", name: "Nivea Soft cream 200 ml", cost: 450 },
          ]}
          groups={["Insurance", "Corporate", "Staff"]}
          prices={prices}
          onApply={(u) => {
            setPrices((p) => ({ ...p, ...u }));
            toast.add({ title: `${Object.keys(u).length} prices updated from the file` });
          }}
        />
      </div>
    </Example>
  );
}

/* ------------------------------- Merge and deleted list ------------------------------- */

const KEEP: MergeProduct = { id: 13, name: "Panadol 500 mg tablets", barcode: "6161100000131", stock: 850, batches: 2, sales: 412, price: 5, taxCode: "A" };
const AWAY: MergeProduct = { id: 14, name: "Panadol 500mg Tabs", barcode: "5000158100021", stock: 120, batches: 1, sales: 37, price: 5.5, taxCode: "B" };

function MergeDemo() {
  const [take, setTake] = React.useState<Record<"price" | "taxCode", "keep" | "merge">>({ price: "keep", taxCode: "keep" });
  const [confirming, setConfirming] = React.useState(false);
  const [done, setDone] = React.useState(false);
  return (
    <Example title="Merge duplicate products" description="The kept product takes the other's batches, history and barcode. Where they differ, choose which value stays">
      {done ? (
        <p className="text-sm">
          Merged. <span className="font-mono">#{AWAY.id}</span> is listed in the merge report and its barcode now scans as {KEEP.name}.
        </p>
      ) : (
        <div className="space-y-3">
          <MergePreview keep={KEEP} merge={AWAY} take={take} onTake={(k, v) => setTake((t) => ({ ...t, [k]: v }))} />
          <div className="flex justify-end">
            <Button variant="destructive" onClick={() => setConfirming(true)}>
              Merge into {KEEP.name}
            </Button>
          </div>
        </div>
      )}
      <ConfirmDialog
        open={confirming}
        onOpenChange={setConfirming}
        level="B"
        title={`Merge ${AWAY.name} into ${KEEP.name}?`}
        consequences={[`${AWAY.stock} units, ${AWAY.batches} batch and ${AWAY.sales} sales lines move across.`, `${AWAY.name} disappears from lists; it can't be unmerged.`]}
        reasons={["Duplicate created by mistake", "Same product from a new supplier", "Other"]}
        actionLabel="Merge products"
        onConfirm={() => setDone(true)}
      />
    </Example>
  );
}

const DELETED: DeletedProduct[] = [
  { id: 31, name: "Calamine lotion 100 ml", barcode: "6161100004230", deletedBy: "Peter Kamau", deletedAt: "2026-10-02", reason: "Discontinued by supplier" },
  { id: 32, name: "ORS sachets (old pack)", barcode: "6161100001091", deletedBy: "Grace Wanjiru", deletedAt: "2026-09-14", reason: "Replaced by new pack" },
];

function DeletedDemo() {
  const [rows, setRows] = React.useState(DELETED);
  return (
    <Example title="Deleted products" description="Deleting moves a product here, never off the books. Restore it unless its barcode now belongs to another product">
      <ul className="divide-y divide-[var(--color-border-subtle)] rounded-lg border border-[var(--color-border-panel)] text-sm">
        {rows.map((p) => {
          const block = restoreBlock(p, ["6161100001091"]);
          return (
            <li key={p.id} className="flex flex-wrap items-center gap-3 px-3 py-2">
              <div className="min-w-0 flex-1">
                <p className="font-medium">{p.name}</p>
                <p className="text-xs text-muted-foreground">
                  Deleted {formatDate(p.deletedAt)} by {p.deletedBy}
                  {p.reason ? `: ${p.reason}` : ""}
                </p>
                {block ? <p className="text-xs text-status-warning-text">{block}</p> : null}
              </div>
              <Button
                size="sm"
                variant="outline"
                disabled={!!block}
                onClick={() => {
                  setRows((xs) => xs.filter((x) => x.id !== p.id));
                  toast.add({ title: `${p.name} restored`, description: "Its stock, batches and history are back." });
                }}
              >
                <RotateCcwIcon data-icon="inline-start" />
                Restore
              </Button>
            </li>
          );
        })}
        {!rows.length ? <li className="px-3 py-6 text-center text-muted-foreground">Nothing deleted.</li> : null}
      </ul>
    </Example>
  );
}

/* ---------------------------------- Batch correction ---------------------------------- */

function BatchCorrectionDemo() {
  const before = { batch: "PN30891", expiry: "2028-01-31" };
  const [d, setD] = React.useState({ batch: "PN30981", expiry: "2027-12-31", reason: "" });
  const [tried, setTried] = React.useState(false);
  const [saved, setSaved] = React.useState(false);
  const { problems, warnings } = batchCorrectionCheck(d, before, TODAY);
  if (saved)
    return (
      <Example title="Correct a batch" description="Logged, and shown in the product's history as before → after">
        <DiffView
          action="Batch corrected"
          record="Panadol 500 mg, GRN-2026-0187"
          who="Grace Wanjiru"
          where="Westlands Main"
          module="Inventory"
          at="20 Oct 2026, 14:50"
          changes={[
            { field: "Batch number", before: before.batch, after: d.batch },
            { field: "Expiry", before: formatDate(before.expiry), after: formatDate(d.expiry) },
            { field: "Reason", after: d.reason },
          ]}
        />
      </Example>
    );
  return (
    <Example title="Correct a batch" description="Received as PN30891, expiring 31 Jan 2028; the box says PN30981, 31 Dec 2027">
      <div className="space-y-3">
        <div className="grid gap-3 sm:grid-cols-3">
          <Field>
            <FieldLabel htmlFor="bc-batch">Batch number</FieldLabel>
            <Input id="bc-batch" className="font-mono" value={d.batch} onChange={(e) => setD({ ...d, batch: e.target.value.toUpperCase() })} />
          </Field>
          <Field>
            <FieldLabel htmlFor="bc-exp">Expiry</FieldLabel>
            <Input id="bc-exp" type="date" value={d.expiry} onChange={(e) => setD({ ...d, expiry: e.target.value })} />
          </Field>
          <Field>
            <FieldLabel htmlFor="bc-reason">Reason</FieldLabel>
            <Input id="bc-reason" value={d.reason} onChange={(e) => setD({ ...d, reason: e.target.value })} placeholder="e.g. Typed wrong at receiving" />
          </Field>
        </div>
        {warnings.map((w) => (
          <p key={w} className="rounded-md border border-status-warning-border bg-status-warning-bg px-3 py-2 text-sm text-status-warning-text">
            {w}
          </p>
        ))}
        {tried && problems.length ? <p className="text-sm text-status-error-text">{problems.join(" ")}</p> : null}
        <div className="flex justify-end">
          <Button
            onClick={() => {
              setTried(true);
              if (!problems.length) setSaved(true);
            }}
          >
            Save correction
          </Button>
        </div>
      </div>
    </Example>
  );
}

/* ------------------------------ Supplier return and PO choice ------------------------------ */

const RETURNABLE: ReturnableBatch[] = [
  { id: "r1", name: "Augmentin 625 mg, 14s", batch: "AG77310", expiry: "30 Nov 2026", onHand: 12, unitCost: 850, grn: "GRN-2026-0170" },
  { id: "r2", name: "Insulin glargine pen", batch: "IG20915", expiry: "31 Mar 2027", onHand: 9, unitCost: 1450, grn: "GRN-2026-0181" },
  { id: "r3", name: "Amoxil 500 mg, 21s", batch: "AX55102", expiry: "31 Mar 2027", onHand: 30, unitCost: 290, grn: "GRN-2026-0187" },
];

function SupplierReturnDemo() {
  const [qty, setQty] = React.useState<Record<string, number>>({ r1: 6 });
  const [reason, setReason] = React.useState<Record<string, string>>({});
  const [tried, setTried] = React.useState(false);
  const lines = RETURNABLE.filter((b) => (qty[b.id] ?? 0) > 0);
  const missing = lines.filter((b) => !reason[b.id]);
  return (
    <Example title="Return to supplier: Harleys Ltd" description="From batches bought from Harleys, no more than is on hand, each with a reason; the credit expected goes to payables">
      <div className="space-y-3">
        <SupplierReturnLines batches={RETURNABLE} qty={qty} reasons={["Short expiry on delivery", "Damaged in transit", "Recalled", "Wrong item sent", "Overstocked (agreed return)"]} reason={reason} onQty={(id, n) => setQty((q) => ({ ...q, [id]: n }))} onReason={(id, r) => setReason((x) => ({ ...x, [id]: r }))} />
        {tried && (missing.length || !lines.length) ? <p className="text-sm text-status-error-text">{!lines.length ? "Add at least one line to return." : "Choose a reason for each line."}</p> : null}
        <div className="flex justify-end">
          <Button
            onClick={() => {
              setTried(true);
              if (!lines.length || missing.length) return;
              const credit = lines.reduce((s, b) => s + (qty[b.id] ?? 0) * b.unitCost, 0);
              toast.add({ title: "Return SRT-2026-0009 recorded", description: `${kes(credit)} credit expected from Harleys; stock leaves the batches now.` });
            }}
          >
            Return and print note
          </Button>
        </div>
      </div>
    </Example>
  );
}

function PoSupplierDemo() {
  const [sup, setSup] = React.useState<Record<string, string>>({ amox: "Harleys Ltd", pan: "Surgipharm" });
  return (
    <Example title="Supplier on a purchase order line" description="Each line suggests the cheapest current price and says when you've picked a dearer one. Stale prices are labelled">
      <div className="space-y-3 text-sm">
        {[
          { id: "amox", product: "Amoxil 500 mg, 21s", quotes: [{ supplier: "Harleys Ltd", cost: 290, lastReceived: "2026-10-12", usual: true }, { supplier: "Dawa Distributors", cost: 305, lastReceived: "2026-09-28" }, { supplier: "Surgipharm", cost: 270, lastReceived: "2026-05-02", stale: true }] },
          { id: "pan", product: "Panadol 500 mg, strip of 10", quotes: [{ supplier: "Dawa Distributors", cost: 28, lastReceived: "2026-10-10", usual: true }, { supplier: "Surgipharm", cost: 31, lastReceived: "2026-10-01" }] },
        ].map((l) => (
          <div key={l.id} className="grid items-start gap-2 sm:grid-cols-[1fr_20rem]">
            <span className="pt-1 font-medium">{l.product}</span>
            <SupplierChoice product={l.product} quotes={l.quotes} value={sup[l.id]} onChange={(s) => setSup((x) => ({ ...x, [l.id]: s }))} />
          </div>
        ))}
      </div>
    </Example>
  );
}

/* --------------------------------- Customers --------------------------------- */

const blankCustomer: CustomerDraft = { kind: "Company", name: "Nairobi West Clinic", contact: "", phone: "0712 345 678", email: "", kraPin: "A012345678Z", etimsId: "", vat: "Vatable", group: "Corporate", city: "Nairobi", address: "", postal: "", country: "Kenya", bankName: "", bankAccount: "" };

function CustomerFormDemo() {
  const [d, setD] = React.useState(blankCustomer);
  const [tried, setTried] = React.useState(false);
  const problems = customerProblems(d, ["0712345678"]);
  return (
    <Example title="Customer form" description="Individual or company. Save as it is: the phone is already Mary's, a company PIN starts with P, and a company needs a contact person">
      <div className="space-y-3">
        <CustomerForm d={d} onChange={setD} groups={["Insurance", "Corporate", "Staff"]} problems={tried ? problems : {}} />
        <div className="flex justify-end">
          <Button
            onClick={() => {
              setTried(true);
              if (!Object.keys(problems).length) toast.add({ title: `${d.name} saved` });
            }}
          >
            Save customer
          </Button>
        </div>
      </div>
    </Example>
  );
}

function GroupsDemo() {
  const [groups, setGroups] = React.useState<CustomerGroup[]>([
    { name: "Insurance", priceGroup: "Insurance", discountPct: 5, members: 214 },
    { name: "Corporate", priceGroup: "Corporate", discountPct: 8, members: 12 },
    { name: "Staff", priceGroup: "Staff", discountPct: 10, members: 18 },
  ]);
  const [edit, setEdit] = React.useState<{ g: CustomerGroup; editing?: string } | null>(null);
  const problem = edit ? groupProblem(edit.g, groups, edit.editing) : undefined;
  return (
    <Example title="Customer groups" description="A group sets the price list and a default discount that apply automatically at the till">
      <div className="space-y-3">
        <ul className="divide-y divide-[var(--color-border-subtle)] rounded-lg border border-[var(--color-border-panel)] text-sm">
          {groups.map((g) => (
            <li key={g.name} className="flex items-center gap-3 px-3 py-2">
              <span className="min-w-0 flex-1">
                <span className="font-medium">{g.name}</span>
                <span className="block text-xs text-muted-foreground">
                  {g.priceGroup} prices · {g.discountPct}% off · {g.members} customers
                </span>
              </span>
              <Button size="xs" variant="ghost" onClick={() => setEdit({ g: { ...g }, editing: g.name })}>
                Edit
              </Button>
            </li>
          ))}
        </ul>
        {edit ? (
          <div className="space-y-2 rounded-lg border border-[var(--color-border-panel)] p-3 text-sm">
            <div className="grid gap-2 sm:grid-cols-3">
              <Input aria-label="Group name" value={edit.g.name} onChange={(e) => setEdit({ ...edit, g: { ...edit.g, name: e.target.value } })} />
              <Input aria-label="Price group" value={edit.g.priceGroup} onChange={(e) => setEdit({ ...edit, g: { ...edit.g, priceGroup: e.target.value } })} />
              <Input aria-label="Default discount %" inputMode="numeric" value={String(edit.g.discountPct)} onChange={(e) => setEdit({ ...edit, g: { ...edit.g, discountPct: Number(e.target.value) || 0 } })} />
            </div>
            {problem ? <p className="text-xs text-status-error-text">{problem}</p> : null}
            <div className="flex justify-end gap-2">
              <Button size="sm" variant="ghost" onClick={() => setEdit(null)}>
                Cancel
              </Button>
              <Button
                size="sm"
                disabled={!!problem}
                onClick={() => {
                  setGroups((xs) => (edit.editing ? xs.map((x) => (x.name === edit.editing ? edit.g : x)) : [...xs, edit.g]));
                  setEdit(null);
                }}
              >
                Save group
              </Button>
            </div>
          </div>
        ) : (
          <Button size="sm" variant="outline" onClick={() => setEdit({ g: { name: "", priceGroup: "Retail", discountPct: 0, members: 0 } })}>
            New group
          </Button>
        )}
      </div>
    </Example>
  );
}

export function CatalogOpsSection() {
  return (
    <Section
      id="catalog-ops"
      title="Catalogue, suppliers and customers"
      description="Keeping product, supplier and customer records right: special prices per group, merging duplicates, restoring deleted products, correcting a batch, returning stock to a supplier, choosing the supplier on a PO, stock value per branch, and the customer record with its groups."
    >
      <PriceGroupsDemo />
      <div className="grid gap-4 lg:grid-cols-2">
        <MergeDemo />
        <DeletedDemo />
      </div>
      <BatchCorrectionDemo />
      <SupplierReturnDemo />
      <PoSupplierDemo />
      <Example title="Stock value by branch" description="At cost and at selling price, with margin, and a grand total">
        <BranchTotals
          rows={[
            { branch: "Westlands Main", items: 412, units: 18420, cost: 684210, selling: 1023900 },
            { branch: "Kilimani", items: 298, units: 9310, cost: 312450, selling: 471200 },
            { branch: "Nyali", items: 276, units: 7988, cost: 268900, selling: 395100 },
            { branch: "Milimani", items: 201, units: 4120, cost: 141300, selling: 214650 },
          ]}
        />
      </Example>
      <div className="grid gap-4 xl:grid-cols-2">
        <CustomerFormDemo />
        <GroupsDemo />
      </div>
    </Section>
  );
}
