"use client";

import * as React from "react";
import { CalendarClockIcon, PlusIcon, Trash2Icon } from "lucide-react";

import { Example } from "@/components/design-system/example";
import { Section } from "@/components/design-system/section";
import { ConfirmDialog } from "@/components/medora/confirm-dialog";
import { RecordDrawer } from "@/components/medora/drawer";
import type { RowAction } from "@/components/medora/row-actions";
import { ProductTaxReview, TaxBadge, TaxCodesTable, VatBreakdown, type TaxCode, type TaxKind, type TaxProduct, type TaxedLine } from "@/components/medora/tax";
import { Button } from "@/components/ui/button";
import { Field, FieldDescription, FieldError, 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 { addDays, formatDate, products, TODAY } from "@/lib/mock-data";

const SEED_CODES: TaxCode[] = [
  { code: "A", name: "Exempt", kind: "Exempt", rate: 0, effectiveFrom: "2023-07-01", products: 0, etims: true },
  { code: "B", name: "VAT", kind: "Standard", rate: 16, effectiveFrom: "2023-07-01", products: 0, etims: true },
  { code: "C", name: "Zero-rated", kind: "Zero-rated", rate: 0, effectiveFrom: "2023-07-01", products: 0, etims: true },
  { code: "D", name: "Non-VAT", kind: "Non-VAT", rate: 0, effectiveFrom: "2023-07-01", products: 0, etims: true },
  { code: "E", name: "Reduced VAT", kind: "Reduced", rate: 8, effectiveFrom: "2023-07-01", products: 0, etims: true },
];

/** Every product starts on B (16%) as "not reviewed": what the migration does to keep today's behaviour. */
const SEED_PRODUCTS: TaxProduct[] = products
  .filter((p) => p.type === "Product")
  .slice(0, 16)
  .map((p) => ({ id: p.id, name: p.name, sub: `${p.strength} · ${p.form}`, category: p.category, taxCode: "B", reviewed: false }));

const KINDS: TaxKind[] = ["Standard", "Reduced", "Zero-rated", "Exempt", "Non-VAT"];

type Draft = { code: string; name: string; kind: TaxKind; rate: string };

function NewCodeDrawer({ open, onClose, codes, onSave }: { open: boolean; onClose: () => void; codes: TaxCode[]; onSave: (c: TaxCode) => void }) {
  const [d, setD] = React.useState<Draft>({ code: "", name: "", kind: "Standard", rate: "" });
  const [tried, setTried] = React.useState(false);
  const rateFixed = d.kind === "Exempt" || d.kind === "Zero-rated" || d.kind === "Non-VAT";
  const errs = {
    code: !/^[A-Z]$/.test(d.code) ? "Use one capital letter, matching the KRA eTIMS tax type." : codes.some((c) => c.code === d.code) ? `${d.code} is already ${codes.find((c) => c.code === d.code)!.name}.` : undefined,
    name: d.name.trim() ? undefined : "Enter a name people will recognise, e.g. Tourism levy.",
    rate: rateFixed ? undefined : !/^\d{1,2}(\.\d)?$/.test(d.rate) || Number(d.rate) <= 0 ? "Enter the rate as a percentage, e.g. 16." : undefined,
  };
  const ok = !Object.values(errs).some(Boolean);
  return (
    <RecordDrawer
      open={open}
      onOpenChange={(o) => !o && onClose()}
      variant="edit"
      dirty={!!(d.code || d.name || d.rate)}
      title="New tax code"
      footer={
        <>
          <Button variant="outline" onClick={onClose}>
            Cancel
          </Button>
          <Button
            onClick={() => {
              setTried(true);
              if (ok) onSave({ code: d.code, name: d.name.trim(), kind: d.kind, rate: rateFixed ? 0 : Number(d.rate), effectiveFrom: TODAY, products: 0 });
            }}
          >
            Save tax code
          </Button>
        </>
      }
    >
      <div className="space-y-4">
        <p className="text-sm text-muted-foreground">Codes A to E are KRA&apos;s standard eTIMS types and already exist. Add a code only when KRA introduces a new type.</p>
        <div className="grid gap-4 sm:grid-cols-2">
          <Field data-invalid={tried && !!errs.code}>
            <FieldLabel htmlFor="tx-code">Code</FieldLabel>
            <Input id="tx-code" className="w-20 font-mono uppercase" maxLength={1} value={d.code} onChange={(e) => setD({ ...d, code: e.target.value.toUpperCase() })} aria-invalid={tried && !!errs.code} />
            {tried && errs.code ? <FieldError>{errs.code}</FieldError> : null}
          </Field>
          <Field data-invalid={tried && !!errs.name}>
            <FieldLabel htmlFor="tx-name">Name</FieldLabel>
            <Input id="tx-name" value={d.name} onChange={(e) => setD({ ...d, name: e.target.value })} aria-invalid={tried && !!errs.name} />
            {tried && errs.name ? <FieldError>{errs.name}</FieldError> : null}
          </Field>
          <Field>
            <FieldLabel htmlFor="tx-kind">Kind</FieldLabel>
            <NativeSelect id="tx-kind" value={d.kind} onChange={(e) => setD({ ...d, kind: e.target.value as TaxKind })}>
              {KINDS.map((k) => (
                <NativeSelectOption key={k} value={k}>
                  {k}
                </NativeSelectOption>
              ))}
            </NativeSelect>
          </Field>
          <Field data-invalid={tried && !!errs.rate}>
            <FieldLabel htmlFor="tx-rate">Rate (%)</FieldLabel>
            <Input id="tx-rate" inputMode="decimal" className="w-28 tabular-nums" disabled={rateFixed} value={rateFixed ? "0" : d.rate} onChange={(e) => setD({ ...d, rate: e.target.value })} aria-invalid={tried && !!errs.rate} />
            {tried && errs.rate ? <FieldError>{errs.rate}</FieldError> : rateFixed ? <FieldDescription>{d.kind} is always 0%.</FieldDescription> : null}
          </Field>
        </div>
      </div>
    </RecordDrawer>
  );
}

function RateChangeDrawer({ code, onClose, onSave }: { code: TaxCode; onClose: () => void; onSave: (rate: number, from: string) => void }) {
  const [rate, setRate] = React.useState("");
  const [from, setFrom] = React.useState(addDays(TODAY, 1));
  const [tried, setTried] = React.useState(false);
  const [confirming, setConfirming] = React.useState(false);
  const errs = {
    rate: !/^\d{1,2}(\.\d)?$/.test(rate) ? "Enter the new rate as a percentage, e.g. 17." : Number(rate) === code.rate ? `${code.code} is already ${code.rate}%.` : undefined,
    from: !from ? "Enter the date the new rate applies from." : from <= TODAY ? "Choose a date after today: sales already made keep the rate they were sold at." : undefined,
  };
  return (
    <>
      <RecordDrawer
        open
        onOpenChange={(o) => !o && onClose()}
        variant="edit"
        dirty={!!rate}
        title={`Change the rate of ${code.code} ${code.name}`}
        footer={
          <>
            <Button variant="outline" onClick={onClose}>
              Cancel
            </Button>
            <Button
              onClick={() => {
                setTried(true);
                if (!errs.rate && !errs.from) setConfirming(true);
              }}
            >
              Schedule change
            </Button>
          </>
        }
      >
        <div className="space-y-4">
          <p className="text-sm text-muted-foreground">
            The new rate starts on the date you choose. Every sale before it keeps {code.rate}%, so receipts, the VAT report and eTIMS stay correct for past dates.
          </p>
          <div className="grid gap-4 sm:grid-cols-2">
            <Field data-invalid={tried && !!errs.rate}>
              <FieldLabel htmlFor="rc-rate">New rate (%)</FieldLabel>
              <Input id="rc-rate" inputMode="decimal" className="w-28 tabular-nums" value={rate} onChange={(e) => setRate(e.target.value)} aria-invalid={tried && !!errs.rate} />
              {tried && errs.rate ? <FieldError>{errs.rate}</FieldError> : <FieldDescription>Now {code.rate}%.</FieldDescription>}
            </Field>
            <Field data-invalid={tried && !!errs.from}>
              <FieldLabel htmlFor="rc-from">Applies from</FieldLabel>
              <Input id="rc-from" type="date" min={addDays(TODAY, 1)} value={from} onChange={(e) => setFrom(e.target.value)} aria-invalid={tried && !!errs.from} />
              {tried && errs.from ? <FieldError>{errs.from}</FieldError> : null}
            </Field>
          </div>
        </div>
      </RecordDrawer>
      <ConfirmDialog
        open={confirming}
        onOpenChange={setConfirming}
        level="A"
        title={`Change ${code.code} to ${rate}% from ${from ? formatDate(from) : ""}?`}
        consequences={[`${code.products} ${code.products === 1 ? "product uses" : "products use"} ${code.code}; their prices to customers change by the VAT difference from that date.`, `Sales before ${from ? formatDate(from) : ""} keep ${code.rate}%.`]}
        actionLabel="Schedule change"
        onConfirm={() => onSave(Number(rate), from)}
      />
    </>
  );
}

export function TaxCodesSection() {
  const [codes, setCodes] = React.useState(SEED_CODES);
  const [items, setItems] = React.useState(SEED_PRODUCTS);
  const [adding, setAdding] = React.useState(false);
  const [rateFor, setRateFor] = React.useState<TaxCode | null>(null);
  const [deleting, setDeleting] = React.useState<TaxCode | null>(null);

  // Product counts follow the assignments.
  const withCounts = codes.map((c) => ({ ...c, products: items.filter((p) => p.taxCode === c.code).length }));

  const actionsFor = (c: TaxCode): RowAction[] => [
    ...(c.kind === "Standard" || c.kind === "Reduced" ? [{ label: "Change rate…", icon: CalendarClockIcon, onSelect: () => setRateFor(c) }] : []),
    ...(c.etims
      ? []
      : [
          {
            label: "Delete…",
            icon: Trash2Icon,
            destructive: true,
            onSelect: () => {
              if (c.products) toast.add({ type: "error", title: `${c.code} is used by ${c.products} ${c.products === 1 ? "product" : "products"}`, description: "Move them to another code first; a code in use can't be deleted." });
              else setDeleting(c);
            },
          },
        ]),
  ];

  // A till basket, priced from the products' current codes.
  const pick = (name: string) => items.find((p) => p.name === name);
  const cart: TaxedLine[] = [
    { id: 1, name: "Panadol 500 mg", qty: 20, unitPrice: 5, taxCode: pick("Panadol")?.taxCode ?? "B" },
    { id: 2, name: "Amoxil 500 mg", qty: 21, unitPrice: 15, taxCode: pick("Amoxil")?.taxCode ?? "B" },
    { id: 3, name: "Nivea Soft cream 200 ml", qty: 1, unitPrice: 610, taxCode: "B" },
  ];

  return (
    <Section
      id="tax-codes"
      title="Tax codes"
      description="Tax codes match KRA eTIMS types (A Exempt, B VAT 16%, C Zero-rated, D Non-VAT, E 8%), and every product has one: the till, receipts and VAT report use it instead of a fixed 16%. A rate change takes an effective date, so past sales keep their rate. A code in use can't be deleted. Existing products move to B and are marked Not reviewed until someone checks them; most medicines are exempt."
    >
      <Example title="Tax codes (Settings)" bare>
        <div className="flex justify-end border-b border-border px-4 py-3">
          <Button size="sm" variant="outline" onClick={() => setAdding(true)}>
            <PlusIcon data-icon="inline-start" />
            New tax code
          </Button>
        </div>
        <div className="p-4">
          <TaxCodesTable codes={withCounts} actionsFor={actionsFor} formatDate={(d) => formatDate(d)} />
        </div>
      </Example>
      <div className="grid gap-4 xl:grid-cols-[minmax(0,2fr)_minmax(0,1fr)]">
        <Example title="Review product tax codes" description="Tick Panadol and Amoxil, assign A (Exempt), and watch the basket" bare>
          <div className="p-4">
            <ProductTaxReview
              products={items}
              codes={withCounts}
              onAssign={(ids, code) => {
                setItems((xs) => xs.map((p) => (ids.includes(p.id) ? { ...p, taxCode: code, reviewed: true } : p)));
                toast.add({ title: `${ids.length} ${ids.length === 1 ? "product" : "products"} set to ${code}` });
              }}
            />
          </div>
        </Example>
        <Example title="At the till" description="Each line shows its code; VAT is worked out per code">
          <ul className="mb-3 divide-y divide-[var(--color-border-subtle)] text-sm">
            {cart.map((l) => (
              <li key={l.id} className="flex items-center gap-2 py-1.5">
                <TaxBadge code={l.taxCode} />
                <span className="min-w-0 flex-1 truncate">{l.name}</span>
                <span className="text-muted-foreground tabular-nums">
                  {l.qty} × {l.unitPrice.toFixed(2)}
                </span>
              </li>
            ))}
          </ul>
          <VatBreakdown lines={cart} codes={withCounts} />
        </Example>
      </div>
      {adding ? (
        <NewCodeDrawer
          open
          onClose={() => setAdding(false)}
          codes={codes}
          onSave={(c) => {
            setCodes((xs) => [...xs, c]);
            setAdding(false);
            toast.add({ title: `Tax code ${c.code} added` });
          }}
        />
      ) : null}
      {rateFor ? (
        <RateChangeDrawer
          code={withCounts.find((c) => c.code === rateFor.code)!}
          onClose={() => setRateFor(null)}
          onSave={(rate, from) => {
            setCodes((xs) => xs.map((c) => (c.code === rateFor.code ? { ...c, next: { rate, from } } : c)));
            setRateFor(null);
            toast.add({ title: `${rateFor.code} changes to ${rate}% on ${formatDate(from)}` });
          }}
        />
      ) : null}
      {deleting ? (
        <ConfirmDialog
          open
          onOpenChange={(o) => !o && setDeleting(null)}
          level="A"
          title={`Delete tax code ${deleting.code}?`}
          consequences={["No products use it.", "Past sales that used it keep it on their receipts and in the VAT report."]}
          actionLabel="Delete tax code"
          onConfirm={() => {
            setCodes((xs) => xs.filter((c) => c.code !== deleting.code));
            setDeleting(null);
          }}
        />
      ) : null}
    </Section>
  );
}
