"use client";

import * as React from "react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { BillForm, billProblems, creditNoteProblems, GrnList, receiveCheck, ReceiveGoodsForm, SupplierBills, SupplierCreditNoteForm, type BillDraft, type CreditNoteDraft, type Grn, type ReceiveHeader, type ReceiveLine, type SupplierBill } from "@/components/medora/goods-in";
import { PendingOrders, PoApproval, poProblems, PurchaseOrderForm, SupplierForm, supplierProblems, type OpenOrder, type PoDraft, type SupplierDraft } from "@/components/medora/purchasing";
import { Button } from "@/components/ui/button";
import { toast } from "@/components/ui/toast";
import { TODAY } from "@/lib/mock-data";

/*
 * One story, so the figures carry through: Harleys Ltd, PO-2026-0142 for Nivea, calamine and Panadol.
 * Six Nivea tubes arrive damaged and are refused (SRN-0044 returns them); 80 strips of Panadol are still to
 * come. GRN-2026-0318 is worth 15,567.60 with VAT. Harleys bill all 24 tubes (18,734.40), so the bill is
 * held, and their credit note for the 6 tubes (3,166.80) brings it back to the goods received.
 */

const LOCATIONS = ["Westlands Main, Store room", "Westlands Main, Dispensary", "Kilimani, Store room"];

/* ------------------------------------ Supplier record ------------------------------------ */

function SupplierDemo() {
  const [d, setD] = React.useState<SupplierDraft>({
    name: "Harleys Ltd",
    kraPin: "P051234567K",
    contact: "Wanjiku Mwangi",
    phone: "020 444 5000",
    email: "orders@harleys",
    postal: "PO Box 30254-00100",
    address: "Industrial Area, Lunga Lunga Road",
    city: "Nairobi",
    country: "Kenya",
    bankName: "",
    bankBranch: "",
    accountNo: "0120 2934 1188",
    wht: false,
    creditLimit: "250000",
    termsDays: "30",
    discount: "2.5",
    leadDays: "5",
  });
  const [tried, setTried] = React.useState(false);
  const p = supplierProblems(d, ["P051987654Z"]);
  return (
    <Example title="Supplier record" description="Save as it is: the email is incomplete and an account number has no bank. The terms say when a bill dated today falls due">
      <SupplierForm d={d} onChange={setD} problems={tried ? p : {}} today={TODAY} />
      <div className="mt-4 flex justify-end">
        <Button
          onClick={() => {
            setTried(true);
            if (!Object.keys(p).length) toast.add({ title: `${d.name} saved` });
          }}
        >
          Save supplier
        </Button>
      </div>
    </Example>
  );
}

export function SupplierRecordSection() {
  return (
    <Section id="supplier-record" title="Supplier record" description="SU-01 and SU-07: company, contacts, bank and tax details, and the terms that drive purchasing: credit limit, payment terms (which set each bill's due date), agreed discount and delivery lead time (which reorder suggestions use).">
      <SupplierDemo />
    </Section>
  );
}

/* ------------------------------------ Order, approval, pending ------------------------------------ */

function OrderDemo() {
  const [d, setD] = React.useState<PoDraft>({
    supplier: "Surgipharm",
    supplierRef: "",
    orderDate: TODAY,
    deadline: "2026-10-22",
    deliverTo: "Westlands Main, Store room",
    notes: "",
    lines: [
      { id: 1, product: "Augmentin 625 mg, 14s", qty: "30", unitCost: "1020", vat: 0 },
      { id: 2, product: "Gloves, box of 100", qty: "10", unitCost: "650", vat: 16 },
      { id: 3, product: "Augmentin 625 mg, 14s", qty: "", unitCost: "", vat: 0 },
    ],
  });
  const [tried, setTried] = React.useState(false);
  const p = poProblems(d);
  return (
    <Example title="New purchase order" description="Surgipharm takes 4 days, so a 2-day deadline is flagged. Try Submit: the third line repeats a product and has no quantity">
      <PurchaseOrderForm
        d={d}
        onChange={setD}
        tried={tried}
        suppliers={[
          { name: "Harleys Ltd", leadDays: 5 },
          { name: "Surgipharm", leadDays: 4 },
          { name: "Dawa Ltd", leadDays: 3 },
        ]}
        locations={LOCATIONS}
        lastCosts={{ "Augmentin 625 mg, 14s": 980, "Gloves, box of 100": 650 }}
      />
      {tried && p.length ? (
        <ul role="alert" className="mt-3 list-disc pl-5 text-sm text-status-error-text">
          {p.map((x) => (
            <li key={x}>{x}</li>
          ))}
        </ul>
      ) : null}
      <div className="mt-4 flex justify-end gap-2">
        <Button variant="outline" onClick={() => toast.add({ title: "Draft saved", description: "Not sent; it needs approval first." })}>
          Save draft
        </Button>
        <Button
          onClick={() => {
            setTried(true);
            if (!poProblems(d).length) toast.add({ title: "PO-2026-0146 submitted for approval", description: "An approver has been notified." });
          }}
        >
          Submit for approval
        </Button>
      </div>
    </Example>
  );
}

const ORDERS: OpenOrder[] = [
  {
    number: "PO-2026-0142",
    supplier: "Harleys Ltd",
    status: "Partly received",
    deadline: "2026-10-19",
    lines: [
      { product: "Nivea Soft cream 200 ml", ordered: 24, received: 18, unitCost: 455 },
      { product: "Calamine lotion 100 ml", ordered: 12, received: 12, unitCost: 160 },
      { product: "Panadol 500 mg, strip", ordered: 200, received: 120, unitCost: 32 },
    ],
  },
  {
    number: "PO-2026-0139",
    supplier: "Dawa Ltd",
    status: "Sent",
    deadline: "2026-10-15",
    lines: [
      { product: "Amoxil 500 mg, 21s", ordered: 60, received: 0, unitCost: 210 },
      { product: "Panadol 500 mg, strip", ordered: 100, received: 0, unitCost: 31 },
    ],
  },
  {
    number: "PO-2026-0145",
    supplier: "Surgipharm",
    status: "Awaiting approval",
    deadline: "2026-10-24",
    lines: [{ product: "Glucometer strips, 50s", ordered: 30, received: 0, unitCost: 1450 }],
  },
  { number: "PO-2026-0131", supplier: "Cosmos Ltd", status: "Received", deadline: "2026-10-02", lines: [{ product: "Metformin 500 mg, 100s", ordered: 12, received: 12, unitCost: 330 }] },
];

export function PurchasingFlowSection() {
  const [viewer, setViewer] = React.useState<"Faith Njeri" | "Grace Wanjiru">("Grace Wanjiru");
  return (
    <Section
      id="purchasing-flow"
      title="Purchase orders, approval and what's on order"
      description="IN-14 and IN-15. An order gets its number when saved, must be approved before it goes to the supplier, and nobody approves their own. What's already on order is listed by order or by product, so it isn't ordered twice."
    >
      <OrderDemo />
      <div className="grid gap-4 xl:grid-cols-2">
        <Example title="Approve an order" description="PO-2026-0145 was raised by Faith Njeri. View as Faith to see the self-approval block">
          <div className="mb-3 flex gap-2 text-sm">
            {(["Grace Wanjiru", "Faith Njeri"] as const).map((v) => (
              <Button key={v} size="sm" variant={viewer === v ? "secondary" : "ghost"} onClick={() => setViewer(v)}>
                As {v}
              </Button>
            ))}
          </div>
          <PoApproval
            key={viewer}
            number="PO-2026-0145"
            supplier="Surgipharm"
            total={43500}
            raisedBy="Faith Njeri"
            raisedAt="20 Oct 2026, 09:40"
            viewer={viewer}
            viewerLimit={viewer === "Grace Wanjiru" ? 100000 : 50000}
            onDecide={(r) => toast.add({ title: r.approved ? "PO-2026-0145 approved and emailed to Surgipharm" : "PO-2026-0145 rejected", description: r.reason ? `Sent back to Faith Njeri: ${r.reason}` : undefined })}
          />
        </Example>
        <Example title="On order" description="Open orders as at 20 Oct 2026. PO-2026-0139 is late">
          <PendingOrders orders={ORDERS} today={TODAY} />
        </Example>
      </div>
    </Section>
  );
}

/* ------------------------------------ Receiving and GRNs ------------------------------------ */

const RECEIVE_START: ReceiveLine[] = [
  { id: 1, product: "Nivea Soft cream 200 ml", ordered: 24, before: 0, unitCost: 455, vat: 16, delivered: "24", received: "18", batch: "NV24-0912", expiry: "2028-03-31", reason: "" },
  { id: 2, product: "Calamine lotion 100 ml", ordered: 12, before: 0, unitCost: 160, vat: 16, delivered: "12", received: "12", batch: "CL-5521", expiry: "2027-02-28", reason: "" },
  { id: 3, product: "Panadol 500 mg, strip", ordered: 200, before: 0, unitCost: 32, vat: 0, delivered: "120", received: "120", batch: "", expiry: "2027-09-30", reason: "" },
];

function ReceiveDemo() {
  const [h, setH] = React.useState<ReceiveHeader>({ po: "PO-2026-0142", supplier: "Harleys Ltd", dnNo: "DN-77120", cuNo: "", location: "Westlands Main, Store room", date: "2026-10-18" });
  const [lines, setLines] = React.useState(RECEIVE_START);
  const [tried, setTried] = React.useState(false);
  const check = receiveCheck(h, lines, "2026-10-18");
  return (
    <Example title="Receive goods against PO-2026-0142" description="Post as it is: the CU number is missing, Panadol has no batch, and 6 Nivea tubes aren't accepted without a reason. Then fill them in">
      <ReceiveGoodsForm header={h} onHeader={setH} lines={lines} onLines={setLines} locations={LOCATIONS} check={check} tried={tried} />
      <div className="mt-4 flex justify-end">
        <Button
          onClick={() => {
            setTried(true);
            if (!check.blocking.length) toast.add({ title: "GRN-2026-0318 posted", description: "Stock and batches updated; the order stays open for 80 strips of Panadol." });
          }}
        >
          Post GRN
        </Button>
      </div>
    </Example>
  );
}

export const GRNS: Grn[] = [
  {
    no: "GRN-2026-0318",
    date: "2026-10-18",
    supplier: "Harleys Ltd",
    po: "PO-2026-0142",
    dnNo: "DN-77120",
    cuNo: "0040112580000004417",
    location: "Westlands Main, Store room",
    lines: [
      { product: "Nivea Soft cream 200 ml", batch: "NV24-0912", expiry: "2028-03-31", qty: 18, unitCost: 455, vat: 16 },
      { product: "Calamine lotion 100 ml", batch: "CL-5521", expiry: "2027-02-28", qty: 12, unitCost: 160, vat: 16 },
      { product: "Panadol 500 mg, strip", batch: "PN-30217", expiry: "2027-09-30", qty: 120, unitCost: 32, vat: 0 },
    ],
  },
  {
    no: "GRN-2026-0311",
    date: "2026-10-11",
    supplier: "Dawa Ltd",
    po: "PO-2026-0133",
    dnNo: "D-4410",
    cuNo: "0040098810000001290",
    location: "Westlands Main, Store room",
    lines: [{ product: "Amoxil 500 mg, 21s", batch: "AMX-2310", expiry: "2027-06-30", qty: 80, unitCost: 210, vat: 0 }],
  },
  {
    no: "GRN-2026-0305",
    date: "2026-10-03",
    supplier: "Cosmos Ltd",
    po: "PO-2026-0131",
    dnNo: "CDN-9921",
    cuNo: "0040077340000000873",
    location: "Kilimani, Store room",
    lines: [{ product: "Metformin 500 mg, 100s", batch: "MF-0882", expiry: "2027-11-30", qty: 12, unitCost: 330, vat: 0 }],
  },
  {
    no: "GRN-2026-0299",
    date: "2026-09-26",
    supplier: "Harleys Ltd",
    po: "PO-2026-0127",
    dnNo: "DN-76604",
    cuNo: "0040112580000003961",
    location: "Westlands Main, Store room",
    lines: [{ product: "Calamine lotion 100 ml", batch: "CL-5480", expiry: "2026-12-31", qty: 24, unitCost: 158, vat: 16 }],
  },
];

export function GoodsInSection() {
  return (
    <Section
      id="goods-in"
      title="Receiving and goods received notes"
      description="IN-16 and IN-17. Receiving records the supplier's delivery note and KRA CU invoice numbers, the location, and per line what was delivered, what was accepted and why not, with batch and expiry. Posting creates the GRN; the GRN list shows them as a summary or line by line, and the same list sits on each supplier's record."
    >
      <ReceiveDemo />
      <Example title="Goods received notes" description="1 Sep to 20 Oct 2026, all branches. Search by any number, or switch to itemised">
        <GrnList grns={GRNS} onOpen={(no) => toast.add({ title: `Opens ${no}` })} />
      </Example>
      <Example title="On Harleys Ltd's record" description="The same list, for one supplier (SU-05)">
        <GrnList grns={GRNS} supplier="Harleys Ltd" />
      </Example>
    </Section>
  );
}

/* ------------------------------------ Bills and credit notes ------------------------------------ */

const BILLS: SupplierBill[] = [
  { no: "BILL-2026-0201", supplier: "Harleys Ltd", invoiceNo: "HL-88412", grn: "GRN-2026-0318", invoiceDate: "2026-10-18", dueDate: "2026-11-17", amount: 18734.4, grnValue: 15567.6, paid: 0, credited: 0, held: "Billed for 24 Nivea tubes; 6 were refused. Credit note requested." },
  { no: "BILL-2026-0196", supplier: "Dawa Ltd", invoiceNo: "DW/2210", grn: "GRN-2026-0311", invoiceDate: "2026-10-11", dueDate: "2026-11-10", amount: 16800, grnValue: 16800, paid: 10000, credited: 0 },
  { no: "BILL-2026-0190", supplier: "Cosmos Ltd", invoiceNo: "CS-55102", grn: "GRN-2026-0305", invoiceDate: "2026-10-03", dueDate: "2026-10-17", amount: 3960, grnValue: 3960, paid: 0, credited: 0 },
  { no: "BILL-2026-0184", supplier: "Harleys Ltd", invoiceNo: "HL-87950", grn: "GRN-2026-0299", invoiceDate: "2026-09-26", dueDate: "2026-10-26", amount: 4398.72, grnValue: 4398.72, paid: 4398.72, credited: 0 },
];

function BillDemo() {
  const grn = GRNS[0];
  const [b, setB] = React.useState<BillDraft>({ invoiceNo: "HL-87950", cuNo: "0040112580000004417", invoiceDate: "2026-10-18", amount: "18,734.40", note: "" });
  const [tried, setTried] = React.useState(false);
  const p = billProblems(b, 15567.6, ["HL-87950"]);
  return (
    <Example title="Enter a bill from GRN-2026-0318" description="Save as it is: the invoice number was already entered, and the total is more than the goods received. Correct the number to HL-88412 and explain the difference">
      <BillForm grn={grn} termsDays={30} b={b} onChange={setB} problems={p} tried={tried} />
      <div className="mt-4 flex justify-end">
        <Button
          onClick={() => {
            setTried(true);
            if (!p.length) toast.add({ title: "BILL-2026-0201 saved", description: Math.abs(Number(b.amount.replace(/,/g, "")) - 15567.6) > 1 ? "Held from payment until the difference is cleared." : "Due 17 Nov 2026." });
          }}
        >
          Save bill
        </Button>
      </div>
    </Example>
  );
}

function CreditNoteDemo() {
  const [d, setD] = React.useState<CreditNoteDraft>({ bill: "BILL-2026-0201", supplierCn: "HL-CN-2207", returnRef: "SRN-0044", amount: "3166.80", reason: "6 Nivea Soft cream 200 ml refused as damaged, returned on SRN-0044" });
  const [tried, setTried] = React.useState(false);
  const p = creditNoteProblems(d, BILLS);
  return (
    <Example title="Supplier credit note" description="3,166.80 brings BILL-2026-0201 back to the goods received (6 × 455 + VAT). Try 20,000 to see the limit">
      <SupplierCreditNoteForm d={d} onChange={setD} bills={BILLS} returns={[{ ref: "SRN-0044", value: 2730 }]} problems={p} tried={tried} />
      <div className="mt-4 flex justify-end">
        <Button
          onClick={() => {
            setTried(true);
            if (!p.length) toast.add({ title: "Credit note recorded", description: `${d.bill} reduced by KES ${d.amount}.` });
          }}
        >
          Record credit note
        </Button>
      </div>
    </Example>
  );
}

export function SupplierBillsSection() {
  return (
    <Section
      id="supplier-bills"
      title="Supplier bills and credit notes"
      description="AC-10. A bill is raised from a GRN, because we owe for goods received, not goods ordered. It's checked against the GRN's value, gets its due date from the supplier's terms, and is held if it disagrees until someone clears it. A supplier credit note reduces one bill and can't take it below zero."
    >
      <div className="grid gap-4 xl:grid-cols-2">
        <BillDemo />
        <CreditNoteDemo />
      </div>
      <Example title="Supplier bills" description="As at 20 Oct 2026, all suppliers">
        <SupplierBills bills={BILLS} today={TODAY} />
      </Example>
    </Section>
  );
}
