import { useMemo, useState } from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Plus, Trash2, FileDown, Send, Save } from "lucide-react";
import { money } from "../lib/format";
import jsPDF from "jspdf";
import autoTable from "jspdf-autotable";

export type LineItem = {
  description: string;
  quantity: number;
  rate: number;
  taxPct: number;
};

export type DocumentFormValues = {
  customerId: string;
  number: string;
  issueDate: string;
  dueDate: string;
  items: LineItem[];
  notes: string;
};

type Customer = { id: string; name: string };

export type DocumentFormProps = {
  kind: "Invoice" | "Estimate";
  numberPrefix: string;
  customers: Customer[];
  currency?: string;
  companyName?: string;
  dueDateLabel?: string;
  draftStatus: string;
  sentStatus: string;
  onSubmit: (
    values: DocumentFormValues & { subtotal: number; tax: number; total: number; status: string }
  ) => unknown | Promise<unknown>;
  onClose?: () => void;
};

const newItem = (): LineItem => ({ description: "", quantity: 1, rate: 0, taxPct: 0 });

export const generateNumber = (prefix: string) => {
  const ts = Date.now().toString().slice(-6);
  return `${prefix}-${ts}`;
};

export function DocumentForm({
  kind,
  numberPrefix,
  customers,
  currency = "USD",
  companyName = "",
  dueDateLabel = "Due Date",
  draftStatus,
  sentStatus,
  onSubmit,
  onClose,
}: DocumentFormProps) {
  const [values, setValues] = useState<DocumentFormValues>({
    customerId: "",
    number: generateNumber(numberPrefix),
    issueDate: new Date().toISOString().slice(0, 10),
    dueDate: "",
    items: [newItem()],
    notes: "",
  });
  const [saving, setSaving] = useState(false);

  const totals = useMemo(() => {
    let subtotal = 0;
    let tax = 0;
    for (const it of values.items) {
      const line = Number(it.quantity) * Number(it.rate);
      subtotal += line;
      tax += line * (Number(it.taxPct) / 100);
    }
    subtotal = +subtotal.toFixed(2);
    tax = +tax.toFixed(2);
    return { subtotal, tax, total: +(subtotal + tax).toFixed(2) };
  }, [values.items]);

  const updateItem = (idx: number, patch: Partial<LineItem>) => {
    setValues((v) => ({
      ...v,
      items: v.items.map((it, i) => (i === idx ? { ...it, ...patch } : it)),
    }));
  };

  const customerName = customers.find((c) => c.id === values.customerId)?.name ?? "";

  const submit = async (status: string) => {
    setSaving(true);
    try {
      await onSubmit({ ...values, ...totals, status });
    } finally {
      setSaving(false);
    }
  };

  const downloadPdf = () => {
    const doc = new jsPDF();
    doc.setFontSize(20);
    doc.text(kind.toUpperCase(), 14, 20);
    doc.setFontSize(10);
    if (companyName) doc.text(companyName, 14, 28);
    doc.text(`# ${values.number}`, 150, 20);
    doc.text(`Date: ${values.issueDate}`, 150, 28);
    if (values.dueDate) doc.text(`${dueDateLabel}: ${values.dueDate}`, 150, 34);
    doc.setFontSize(11);
    doc.text(`Bill To: ${customerName || "—"}`, 14, 44);

    autoTable(doc, {
      startY: 52,
      head: [["Description", "Qty", "Rate", "Tax %", "Amount"]],
      body: values.items.map((it) => [
        it.description,
        it.quantity,
        money(it.rate, currency),
        `${it.taxPct}%`,
        money(it.quantity * it.rate * (1 + it.taxPct / 100), currency),
      ]),
      styles: { fontSize: 9 },
      headStyles: { fillColor: [0, 137, 123] },
    });

    const finalY = (doc as any).lastAutoTable?.finalY ?? 80;
    doc.setFontSize(10);
    doc.text(`Subtotal: ${money(totals.subtotal, currency)}`, 140, finalY + 10);
    doc.text(`Tax: ${money(totals.tax, currency)}`, 140, finalY + 16);
    doc.setFontSize(12);
    doc.text(`Total: ${money(totals.total, currency)}`, 140, finalY + 24);
    if (values.notes) {
      doc.setFontSize(9);
      doc.text(`Notes: ${values.notes}`, 14, finalY + 34);
    }
    doc.save(`${kind}-${values.number}.pdf`);
  };

  return (
    <div className="space-y-5">
      <div className="grid grid-cols-2 gap-4">
        <div>
          <Label>Customer</Label>
          <Select value={values.customerId} onValueChange={(v) => setValues({ ...values, customerId: v })}>
            <SelectTrigger><SelectValue placeholder="Select customer" /></SelectTrigger>
            <SelectContent>
              {customers.map((c) => (
                <SelectItem key={c.id} value={c.id}>{c.name}</SelectItem>
              ))}
            </SelectContent>
          </Select>
        </div>
        <div>
          <Label>{kind} #</Label>
          <Input value={values.number} onChange={(e) => setValues({ ...values, number: e.target.value })} />
        </div>
        <div>
          <Label>{kind} Date</Label>
          <Input type="date" value={values.issueDate} onChange={(e) => setValues({ ...values, issueDate: e.target.value })} />
        </div>
        <div>
          <Label>{dueDateLabel}</Label>
          <Input type="date" value={values.dueDate} onChange={(e) => setValues({ ...values, dueDate: e.target.value })} />
        </div>
      </div>

      <div>
        <div className="mb-2 flex items-center justify-between">
          <Label>Line items</Label>
          <Button type="button" variant="outline" size="sm" onClick={() => setValues({ ...values, items: [...values.items, newItem()] })}>
            <Plus className="mr-1 h-3 w-3" /> Add row
          </Button>
        </div>
        <div className="overflow-hidden rounded-lg border border-border">
          <table className="w-full text-sm">
            <thead className="bg-muted/40 text-xs uppercase tracking-wide text-muted-foreground">
              <tr>
                <th className="px-3 py-2 text-left font-medium">Item / Description</th>
                <th className="w-20 px-3 py-2 text-right font-medium">Qty</th>
                <th className="w-28 px-3 py-2 text-right font-medium">Rate</th>
                <th className="w-20 px-3 py-2 text-right font-medium">Tax %</th>
                <th className="w-28 px-3 py-2 text-right font-medium">Amount</th>
                <th className="w-10" />
              </tr>
            </thead>
            <tbody className="divide-y divide-border">
              {values.items.map((it, idx) => {
                const amount = +(it.quantity * it.rate * (1 + it.taxPct / 100)).toFixed(2);
                return (
                  <tr key={idx}>
                    <td className="p-2">
                      <Input
                        placeholder="Item or description"
                        value={it.description}
                        onChange={(e) => updateItem(idx, { description: e.target.value })}
                      />
                    </td>
                    <td className="p-2">
                      <Input type="number" min={0} step="0.01" className="text-right" value={it.quantity}
                        onChange={(e) => updateItem(idx, { quantity: Number(e.target.value) })} />
                    </td>
                    <td className="p-2">
                      <Input type="number" min={0} step="0.01" className="text-right" value={it.rate}
                        onChange={(e) => updateItem(idx, { rate: Number(e.target.value) })} />
                    </td>
                    <td className="p-2">
                      <Input type="number" min={0} step="0.01" className="text-right" value={it.taxPct}
                        onChange={(e) => updateItem(idx, { taxPct: Number(e.target.value) })} />
                    </td>
                    <td className="px-3 py-2 text-right font-medium tabular-nums">{money(amount, currency)}</td>
                    <td className="p-2">
                      <Button type="button" variant="ghost" size="icon"
                        onClick={() => setValues({ ...values, items: values.items.filter((_, i) => i !== idx) })}>
                        <Trash2 className="h-4 w-4" />
                      </Button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      </div>

      <div className="grid grid-cols-2 gap-4">
        <div>
          <Label>Notes</Label>
          <Input maxLength={400} value={values.notes} onChange={(e) => setValues({ ...values, notes: e.target.value })} />
        </div>
        <div className="rounded-lg border border-border bg-muted/30 p-4 text-sm">
          <div className="flex justify-between py-1">
            <span className="text-muted-foreground">Subtotal</span>
            <span className="font-medium tabular-nums">{money(totals.subtotal, currency)}</span>
          </div>
          <div className="flex justify-between py-1">
            <span className="text-muted-foreground">Tax</span>
            <span className="font-medium tabular-nums">{money(totals.tax, currency)}</span>
          </div>
          <div className="mt-2 flex justify-between border-t border-border pt-2 text-base">
            <span className="font-semibold">Total</span>
            <span className="font-semibold tabular-nums">{money(totals.total, currency)}</span>
          </div>
        </div>
      </div>

      <div className="flex flex-wrap items-center justify-end gap-2 border-t border-border pt-4">
        {onClose && <Button type="button" variant="ghost" onClick={onClose}>Cancel</Button>}
        <Button type="button" variant="outline" onClick={downloadPdf}>
          <FileDown className="mr-1 h-4 w-4" /> Download PDF
        </Button>
        <Button type="button" variant="outline" disabled={saving} onClick={() => submit(draftStatus)}>
          <Save className="mr-1 h-4 w-4" /> Save as Draft
        </Button>
        <Button type="button" disabled={saving} onClick={() => submit(sentStatus)}>
          <Send className="mr-1 h-4 w-4" /> {kind === "Invoice" ? "Send" : "Send Estimate"}
        </Button>
      </div>
    </div>
  );
}
