import { useEffect, useMemo, useState } from "react";
import { createFileRoute, Link, notFound, useNavigate } from "@tanstack/react-router";
import {
  AlertTriangle,
  ArrowLeft,
  Check,
  CloudUpload,
  Copy,
  FileText,
  Info,
  Loader2,
  MoreHorizontal,
  Send,
  X,
} from "lucide-react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { Textarea } from "@/components/ui/textarea";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "@/components/ui/dialog";
import {
  DropdownMenu,
  DropdownMenuContent,
  DropdownMenuItem,
  DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu";
import { DocumentPreview } from "@/components/ledger/DocumentPreview";
import { SectionCard } from "@/components/ledger/Primitives";
import { StatusBadge, DuplicateBadge } from "@/components/ledger/StatusBadge";
import { ActivityTimeline } from "@/components/ledger/ActivityTimeline";
import { ConfidenceIndicator } from "@/components/ledger/ConfidenceIndicator";
import { useAuthSession } from "@/hooks/useAuthSession";
import { eur, useLedger } from "@/lib/ledger-store";
import { isSnelStartConnected, snelstartStatusLabel, snelstartStatusTone } from "@/lib/snelstart";
import type { Invoice } from "@/lib/ledger-types";

export const Route = createFileRoute("/invoices/$id")({
  head: () => ({
    meta: [
      { title: "Document review — Amanah" },
      {
        name: "description",
        content: "Review the original document, correct bookkeeping fields and approve or reject.",
      },
    ],
  }),
  component: InvoiceReview,
});

function isUnavailable(value: string | number | null | undefined): boolean {
  if (value === null || value === undefined) return true;
  if (typeof value === "number") return false;
  const v = value.trim();
  return !v || v === "—" || v === "-" || v === "Pending extraction";
}

function displayOrNA(value: string | null | undefined): string {
  return isUnavailable(value) ? "" : String(value);
}

function InvoiceReview() {
  const { id } = Route.useParams();
  const navigate = useNavigate();
  const session = useAuthSession("firm");
  const {
    getInvoice,
    clients,
    clientName,
    updateInvoiceFields,
    updateSuggestion,
    approveInvoice,
    rejectInvoice,
    syncInvoice,
    createQuery,
    setDuplicateStatus,
    activity,
  } = useLedger();

  const invoice = getInvoice(id);
  const [question, setQuestion] = useState("");
  const [rejectOpen, setRejectOpen] = useState(false);
  const [rejectReason, setRejectReason] = useState("");
  const [ocrTextOpen, setOcrTextOpen] = useState(false);

  if (!invoice) {
    throw notFound();
  }

  const client = clients.find((c) => c.id === invoice.clientId);
  const canApprove = invoice.status === "Needs review" || invoice.status === "Auto-ready";
  const canReject =
    invoice.status !== "Synced" &&
    invoice.status !== "Rejected" &&
    invoice.status !== "Sync failed";
  const canSync = invoice.status === "Approved" || invoice.status === "Auto-ready";
  const canEdit =
    invoice.status !== "Synced" &&
    invoice.status !== "Rejected";
  const title = isUnavailable(invoice.supplier) ? invoice.file : invoice.supplier;
  const isProcessing = invoice.status === "Processing" || invoice.status === "New";
  const ocrFailed = invoice.ocrStatus === "failed" || invoice.ocrStatus === "unavailable";
  const extractionReady = Boolean(invoice.processedAt) && invoice.confidence > 0;
  const docActivity = useMemo(
    () => activity.filter((e) => e.invoiceId === invoice.id).slice(0, 20),
    [activity, invoice.id],
  );

  return (
    <div className="space-y-5">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div className="min-w-0">
          <nav aria-label="Breadcrumb" className="text-[12.5px] text-muted-foreground">
            <Link to="/inbox" search={{}} className="hover:text-foreground">
              Document inbox
            </Link>
            <span aria-hidden="true"> / </span>
            <span className="text-foreground">{invoice.file}</span>
          </nav>
          <h1 className="mt-1.5 font-display text-[28px] leading-tight">{title}</h1>
          <div className="mt-2 flex flex-wrap items-center gap-3">
            <StatusBadge status={invoice.status} />
            <DuplicateBadge status={invoice.duplicateStatus} />
            <span className="text-[13px] text-muted-foreground">{clientName(invoice.clientId)}</span>
            {extractionReady ? (
              <div className="w-40">
                <ConfidenceIndicator value={invoice.confidence} compact />
              </div>
            ) : isProcessing ? (
              <span className="text-[12.5px] text-muted-foreground">Reading document...</span>
            ) : ocrFailed ? (
              <span className="text-[12.5px] text-attention">OCR needs attention</span>
            ) : (
              <span className="text-[12.5px] text-muted-foreground">Not processed yet</span>
            )}
          </div>
        </div>
        <div className="flex items-center gap-2">
          {invoice.ocrText ? (
            <Button variant="outline" size="sm" onClick={() => setOcrTextOpen(true)}>
              <FileText size={15} /> View extracted text
            </Button>
          ) : null}
          <DropdownMenu>
            <DropdownMenuTrigger asChild>
              <Button variant="ghost" size="icon" aria-label="More actions">
                <MoreHorizontal size={18} />
              </Button>
            </DropdownMenuTrigger>
            <DropdownMenuContent align="end">
              <DropdownMenuItem onSelect={() => navigate({ to: "/activity" })}>
                View activity
              </DropdownMenuItem>
              <DropdownMenuItem onSelect={() => navigate({ to: "/queries" })}>
                View client queries
              </DropdownMenuItem>
              {invoice.ocrText ? (
                <DropdownMenuItem onSelect={() => setOcrTextOpen(true)}>
                  View extracted text
                </DropdownMenuItem>
              ) : null}
            </DropdownMenuContent>
          </DropdownMenu>
          <Button variant="outline" asChild>
            <Link to="/inbox" search={{}}>
              <ArrowLeft size={16} /> Back to inbox
            </Link>
          </Button>
        </div>
      </div>

      {isProcessing ? (
        <div className="flex items-start gap-3 rounded-xl border border-primary/20 bg-primary-soft px-4 py-3">
          <Loader2 size={18} className="mt-0.5 animate-spin text-primary" aria-hidden="true" />
          <div>
            <p className="text-[13.5px] font-medium text-foreground">Processing</p>
            <p className="mt-0.5 text-[13px] text-muted-foreground">
              Reading document with local OCR. Extracted fields will appear when processing finishes.
            </p>
          </div>
        </div>
      ) : null}

      {ocrFailed ? (
        <div className="flex items-start gap-3 rounded-xl border border-attention/30 bg-attention-soft px-4 py-3">
          <AlertTriangle size={18} className="mt-0.5 text-attention" aria-hidden="true" />
          <div>
            <p className="text-[13.5px] font-medium text-foreground">
              Document processing is currently unavailable.
            </p>
            <p className="mt-0.5 text-[13px] text-muted-foreground">
              {invoice.ocrError?.trim()
                ? invoice.ocrError
                : "Local OCR could not read this document. Enter invoice fields manually from the original file."}
            </p>
          </div>
        </div>
      ) : null}

      {(invoice.duplicateOf || (invoice.duplicateStatus && invoice.duplicateStatus !== "None" && invoice.duplicateStatus !== "Not duplicate")) ? (
        <div className="flex flex-wrap items-start gap-3 rounded-xl border border-attention/30 bg-attention-soft px-4 py-3">
          <AlertTriangle size={18} className="mt-0.5 text-attention" aria-hidden="true" />
          <div className="min-w-0 flex-1">
            <p className="text-[13.5px] font-medium text-foreground">
              {invoice.duplicateStatus === "Confirmed duplicate"
                ? "Confirmed duplicate"
                : "Possible duplicate document"}
            </p>
            <p className="mt-0.5 text-[13px] leading-6 text-muted-foreground">
              {invoice.duplicateOf
                ? "This document matches another upload from the same client."
                : "This document may match another record based on file or invoice metadata."}
            </p>
          </div>
          {invoice.duplicateOf ? (
            <Button variant="outline" size="sm" asChild>
              <Link to="/invoices/$id" params={{ id: invoice.duplicateOf }}>
                <Copy size={15} /> View matching document
              </Link>
            </Button>
          ) : null}
          {invoice.duplicateStatus !== "Confirmed duplicate" ? (
            <Button
              variant="outline"
              size="sm"
              onClick={() => setDuplicateStatus(invoice.id, "Confirmed duplicate")}
            >
              Confirm duplicate
            </Button>
          ) : null}
          {invoice.duplicateStatus !== "Not duplicate" ? (
            <Button
              variant="ghost"
              size="sm"
              onClick={() => setDuplicateStatus(invoice.id, "Not duplicate")}
            >
              Mark not duplicate
            </Button>
          ) : null}
        </div>
      ) : null}

      {invoice.status === "Approved" ? (
        <div className="flex items-start gap-3 rounded-xl border border-success/25 bg-success-soft px-4 py-3">
          <Check size={18} className="mt-0.5 text-success" aria-hidden="true" />
          <div>
            <p className="text-[13.5px] font-medium text-foreground">Approved — awaiting SnelStart integration</p>
            <p className="mt-0.5 text-[13px] text-muted-foreground">
              This document is approved. Sync to SnelStart will be available once the integration is connected.
            </p>
          </div>
        </div>
      ) : null}

      {invoice.status === "Rejected" && invoice.rejectionReason ? (
        <div className="flex items-start gap-3 rounded-xl border border-destructive/25 bg-destructive-soft px-4 py-3">
          <X size={18} className="mt-0.5 text-destructive" aria-hidden="true" />
          <div>
            <p className="text-[13.5px] font-medium">Rejected</p>
            <p className="mt-0.5 text-[13px] text-muted-foreground">{invoice.rejectionReason}</p>
          </div>
        </div>
      ) : null}

      {invoice.status === "Sync failed" && invoice.syncError ? (
        <div className="flex items-start gap-3 rounded-xl border border-destructive/25 bg-destructive-soft px-4 py-3">
          <AlertTriangle size={18} className="mt-0.5 text-destructive" aria-hidden="true" />
          <p className="text-[13.5px] text-foreground">{invoice.syncError}</p>
        </div>
      ) : null}

      <div className="grid gap-4 lg:grid-cols-[1.2fr_1fr]">
        <div className="space-y-4">
          <SectionCard title="Document preview" description="Original uploaded file" bodyClassName="p-0 overflow-hidden">
            {invoice.storageKey && session?.email ? (
              <DocumentPreview
                invoiceId={invoice.id}
                platform="firm"
                email={session.email}
                mimeType={invoice.mimeType ?? null}
                fileName={invoice.file}
                className="min-h-[420px]"
              />
            ) : (
              <div className="flex min-h-[220px] items-center justify-center bg-muted/30 px-6 py-10 text-[13px] text-muted-foreground">
                Preview unavailable
              </div>
            )}
          </SectionCard>

          <ExtractedFields
            invoice={invoice}
            disabled={!canEdit}
            onSave={(patch) => updateInvoiceFields(invoice.id, patch)}
          />

          <SectionCard title="Line items" description="Editable document lines" bodyClassName="overflow-x-auto">
            {invoice.lines.length === 0 ? (
              <p className="px-5 py-6 text-[13.5px] text-muted-foreground">Not available</p>
            ) : (
              <LineItemsTable
                invoice={invoice}
                disabled={!canEdit}
                onSave={(lines) => updateInvoiceFields(invoice.id, { lines })}
              />
            )}
          </SectionCard>
        </div>

        <div className="space-y-4 lg:sticky lg:top-20 lg:self-start">
          <SectionCard title="Bookkeeping classification" bodyClassName="p-5 space-y-4">
            {isProcessing ? (
              <p className="text-[13px] leading-6 text-muted-foreground">
                Reading document… Local OCR suggestions will appear when processing finishes.
              </p>
            ) : ocrFailed ? (
              <p className="text-[13px] leading-6 text-muted-foreground">
                Document processing is currently unavailable. Enter classification manually before approval.
              </p>
            ) : !extractionReady ? (
              <p className="text-[13px] leading-6 text-muted-foreground">
                Local OCR suggestions are not available yet. Enter classification manually before approval.
              </p>
            ) : (
              <div className="space-y-2">
                <p className="text-[12px] font-medium text-muted-foreground">Local OCR/extraction confidence</p>
                <ConfidenceIndicator value={invoice.confidence} />
              </div>
            )}
            <div className="rounded-lg border border-border bg-muted/50 p-3">
              <p className="text-[12px] font-semibold text-foreground">Reasoning</p>
              <p className="mt-1 text-[13px] leading-6 text-muted-foreground">
                {invoice.suggestion.reasoning || "Not available"}
              </p>
            </div>
            {invoice.suggestion.editedBy ? (
              <p className="text-[11.5px] text-muted-foreground">Edited by {invoice.suggestion.editedBy}</p>
            ) : null}
            <div className="grid gap-3 sm:grid-cols-2">
              <FieldInput
                label="Ledger account"
                value={invoice.suggestion.ledger}
                disabled={!canEdit}
                placeholder="Not available"
                onSave={(v) => updateSuggestion(invoice.id, { ledger: v })}
              />
              <FieldInput
                label="VAT treatment"
                value={invoice.suggestion.vatCode}
                disabled={!canEdit}
                placeholder="Not available"
                onSave={(v) => updateSuggestion(invoice.id, { vatCode: v })}
              />
              <FieldInput
                label="Expense category"
                value={invoice.suggestion.category}
                disabled={!canEdit}
                placeholder="Not available"
                onSave={(v) => updateSuggestion(invoice.id, { category: v })}
              />
              <FieldInput
                label="Relation"
                value={invoice.suggestion.relation}
                disabled={!canEdit}
                placeholder="Not available"
                onSave={(v) => updateSuggestion(invoice.id, { relation: v })}
              />
            </div>
          </SectionCard>

          <SectionCard title="Workflow" bodyClassName="space-y-3 p-5">
            <div className="flex flex-wrap gap-2">
              <Button onClick={() => approveInvoice(invoice.id)} disabled={!canApprove}>
                <Check size={16} /> Approve
              </Button>
              <Button variant="outline" onClick={() => setRejectOpen(true)} disabled={!canReject}>
                <X size={16} /> Reject
              </Button>
            </div>
            {!canApprove && invoice.status === "Needs review" ? null : null}
            {canApprove && isUnavailable(invoice.supplier) ? (
              <p className="flex items-start gap-1.5 text-[12px] text-attention">
                <Info size={14} className="mt-0.5 shrink-0" aria-hidden="true" />
                Enter a supplier before approving.
              </p>
            ) : null}
            <div>
              <Button
                variant={canSync ? "default" : "secondary"}
                className="w-full"
                disabled={!canSync}
                title={canSync ? undefined : "Approve the document before syncing to SnelStart"}
                onClick={() => syncInvoice(invoice.id)}
              >
                <CloudUpload size={16} /> Sync to SnelStart
              </Button>
              {!canSync ? (
                <p className="mt-2 flex items-start gap-1.5 text-[12px] text-muted-foreground">
                  <Info size={14} className="mt-0.5 shrink-0" aria-hidden="true" />
                  Sync is available after approval. SnelStart integration is separate from review.
                </p>
              ) : null}
              {client && !isSnelStartConnected(client) ? (
                <p className="mt-2 flex items-start gap-1.5 text-[12px] text-attention">
                  <AlertTriangle size={14} className="mt-0.5 shrink-0" aria-hidden="true" />
                  SnelStart integration is not connected for {client.name}. Sync will remain unavailable until the integration is connected.
                </p>
              ) : null}
            </div>
            {invoice.approvedBy ? (
              <p className="text-[12px] text-muted-foreground">
                Approved by {invoice.approvedBy}
                {invoice.approvedAt ? ` · ${invoice.approvedAt.slice(0, 10)}` : ""}
              </p>
            ) : null}
          </SectionCard>

          <SectionCard title="Ask client" bodyClassName="space-y-3 p-5">
            <Label htmlFor="ask-client" className="text-[12px] text-muted-foreground">
              Question
            </Label>
            <Textarea
              id="ask-client"
              value={question}
              onChange={(e) => setQuestion(e.target.value)}
              placeholder="Can you confirm whether this invoice was paid?"
              className="min-h-24 bg-surface"
            />
            <Button
              variant="outline"
              disabled={!question.trim()}
              onClick={() => {
                createQuery(invoice.clientId, question.trim(), { invoiceId: invoice.id });
                setQuestion("");
              }}
            >
              <Send size={16} /> Ask client
            </Button>
          </SectionCard>

          <SectionCard title="Document history" description="Activity for this document">
            {docActivity.length === 0 ? (
              <p className="px-5 py-4 text-[13px] text-muted-foreground">No activity recorded yet.</p>
            ) : (
              <ActivityTimeline events={docActivity} showLinks />
            )}
          </SectionCard>
        </div>
      </div>

      <Dialog open={rejectOpen} onOpenChange={setRejectOpen}>
        <DialogContent className="sm:max-w-md">
          <DialogHeader>
            <DialogTitle>Reject document</DialogTitle>
            <DialogDescription>
              The client will see this reason. A rejection reason is required.
            </DialogDescription>
          </DialogHeader>
          <div className="space-y-2">
            <Label htmlFor="reject-reason">Reason for rejection</Label>
            <Textarea
              id="reject-reason"
              value={rejectReason}
              onChange={(e) => setRejectReason(e.target.value)}
              placeholder="The invoice image was unclear."
              className="min-h-28"
            />
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setRejectOpen(false)}>
              Cancel
            </Button>
            <Button
              variant="destructive"
              disabled={!rejectReason.trim()}
              onClick={() => {
                rejectInvoice(invoice.id, rejectReason.trim());
                setRejectOpen(false);
                setRejectReason("");
              }}
            >
              Reject document
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>

      <Dialog open={ocrTextOpen} onOpenChange={setOcrTextOpen}>
        <DialogContent className="sm:max-w-2xl">
          <DialogHeader>
            <DialogTitle>Extracted text</DialogTitle>
            <DialogDescription>
              Raw text from local OCR ({invoice.ocrEngine || "tesseract"}). Use this to verify field extraction —
              it is not sent to the client.
            </DialogDescription>
          </DialogHeader>
          <div className="max-h-[60vh] overflow-auto rounded-lg border border-border bg-muted/40 p-4">
            <pre className="whitespace-pre-wrap font-mono text-[12.5px] leading-5 text-foreground">
              {invoice.ocrText?.trim() || "No extracted text available."}
            </pre>
          </div>
          <DialogFooter>
            <Button variant="outline" onClick={() => setOcrTextOpen(false)}>
              Close
            </Button>
          </DialogFooter>
        </DialogContent>
      </Dialog>
    </div>
  );
}

function FieldInput({
  label,
  value,
  onSave,
  type = "text",
  disabled = false,
  placeholder = "Not available",
}: {
  label: string;
  value: string;
  onSave: (v: string) => void;
  type?: string;
  disabled?: boolean;
  placeholder?: string;
}) {
  const [draft, setDraft] = useState(displayOrNA(value));
  useEffect(() => {
    setDraft(displayOrNA(value));
  }, [value]);
  const id = `f-${label.replace(/\s+/g, "-").toLowerCase()}`;
  return (
    <div>
      <Label htmlFor={id} className="text-[12px] text-muted-foreground">
        {label}
      </Label>
      <Input
        id={id}
        type={type}
        value={draft}
        disabled={disabled}
        placeholder={placeholder}
        onChange={(e) => setDraft(e.target.value)}
        onBlur={() => draft !== displayOrNA(value) && onSave(draft)}
        className="mt-1 h-9 bg-surface"
      />
    </div>
  );
}

function ExtractedFields({
  invoice,
  onSave,
  disabled,
}: {
  invoice: Invoice;
  onSave: (patch: Partial<Invoice>) => void;
  disabled?: boolean;
}) {
  const [draft, setDraft] = useState({
    supplier: displayOrNA(invoice.supplier),
    number: displayOrNA(invoice.number),
    invoiceDate: displayOrNA(invoice.invoiceDate),
    dueDate: displayOrNA(invoice.dueDate),
    vatAmount: invoice.vatAmount ? String(invoice.vatAmount) : "",
    total: invoice.total ? String(invoice.total) : "",
    currency: invoice.currency || "EUR",
    paymentRef: displayOrNA(invoice.paymentRef),
  });

  useEffect(() => {
    setDraft({
      supplier: displayOrNA(invoice.supplier),
      number: displayOrNA(invoice.number),
      invoiceDate: displayOrNA(invoice.invoiceDate),
      dueDate: displayOrNA(invoice.dueDate),
      vatAmount: invoice.vatAmount ? String(invoice.vatAmount) : "",
      total: invoice.total ? String(invoice.total) : "",
      currency: invoice.currency || "EUR",
      paymentRef: displayOrNA(invoice.paymentRef),
    });
  }, [invoice]);

  const set = (k: keyof typeof draft) => (e: React.ChangeEvent<HTMLInputElement>) =>
    setDraft((d) => ({ ...d, [k]: e.target.value }));

  const fields: { key: keyof typeof draft; label: string; type?: string; placeholder?: string }[] = [
    { key: "supplier", label: "Supplier", placeholder: "Not available" },
    { key: "number", label: "Invoice number", placeholder: "Not available" },
    { key: "invoiceDate", label: "Invoice date", type: "date" },
    { key: "dueDate", label: "Due date", type: "date" },
    { key: "vatAmount", label: "VAT", type: "number", placeholder: "Not available" },
    { key: "total", label: "Total", type: "number", placeholder: "Not available" },
    { key: "currency", label: "Currency" },
    { key: "paymentRef", label: "Payment reference", placeholder: "Not available" },
  ];

  return (
    <SectionCard
      title="Invoice information"
      description={
        invoice.ocrStatus === "completed"
          ? "Local OCR filled what it could — verify and correct before approval"
          : "Verify or enter bookkeeping fields"
      }
      bodyClassName="p-5"
    >
      <div className="grid gap-3 sm:grid-cols-2">
        {fields.map((f) => (
          <div key={f.key}>
            <Label htmlFor={`ex-${f.key}`} className="text-[12px] text-muted-foreground">
              {f.label}
            </Label>
            <Input
              id={`ex-${f.key}`}
              type={f.type ?? "text"}
              value={draft[f.key]}
              disabled={disabled}
              placeholder={f.placeholder ?? "Not available"}
              onChange={set(f.key)}
              className="mt-1 h-9 bg-surface"
            />
          </div>
        ))}
      </div>
      <div className="mt-4">
        <Button
          disabled={disabled}
          onClick={() =>
            onSave({
              supplier: draft.supplier.trim(),
              number: draft.number.trim(),
              invoiceDate: draft.invoiceDate,
              dueDate: draft.dueDate,
              vatAmount: Number(draft.vatAmount) || 0,
              total: Number(draft.total) || 0,
              currency: draft.currency || "EUR",
              paymentRef: draft.paymentRef.trim(),
            })
          }
        >
          Save changes
        </Button>
      </div>
    </SectionCard>
  );
}

function LineItemsTable({
  invoice,
  onSave,
  disabled,
}: {
  invoice: Invoice;
  onSave: (lines: Invoice["lines"]) => void;
  disabled?: boolean;
}) {
  const [lines, setLines] = useState(invoice.lines);
  useEffect(() => setLines(invoice.lines), [invoice.lines]);

  const update = (id: string, patch: Partial<Invoice["lines"][number]>) =>
    setLines((prev) => prev.map((l) => (l.id === id ? { ...l, ...patch } : l)));

  return (
    <div>
      <table className="w-full min-w-[620px] text-[13.5px]">
        <thead className="border-b border-border bg-muted/50 text-[11.5px] tracking-wide text-muted-foreground uppercase">
          <tr>
            <th className="px-5 py-2.5 text-left font-semibold">Description</th>
            <th className="px-3 py-2.5 text-right font-semibold">Qty</th>
            <th className="px-3 py-2.5 text-right font-semibold">Unit price</th>
            <th className="px-3 py-2.5 text-right font-semibold">VAT</th>
            <th className="px-5 py-2.5 text-right font-semibold">Total</th>
          </tr>
        </thead>
        <tbody className="divide-y divide-border">
          {lines.map((l) => (
            <tr key={l.id}>
              <td className="px-5 py-2">
                <Input
                  value={l.description}
                  disabled={disabled}
                  aria-label="Line description"
                  onChange={(e) => update(l.id, { description: e.target.value })}
                  className="h-8 border-transparent bg-transparent px-1 hover:border-border focus:bg-surface"
                />
              </td>
              <td className="px-3 py-2 text-right">
                <Input
                  type="number"
                  value={l.qty}
                  disabled={disabled}
                  aria-label="Quantity"
                  onChange={(e) => update(l.id, { qty: Number(e.target.value) })}
                  className="num h-8 w-20 border-transparent bg-transparent px-1 text-right hover:border-border focus:bg-surface"
                />
              </td>
              <td className="px-3 py-2 text-right">
                <Input
                  type="number"
                  value={l.unitPrice}
                  disabled={disabled}
                  aria-label="Unit price"
                  onChange={(e) => update(l.id, { unitPrice: Number(e.target.value) })}
                  className="num h-8 w-24 border-transparent bg-transparent px-1 text-right hover:border-border focus:bg-surface"
                />
              </td>
              <td className="num px-3 py-2 text-right text-muted-foreground">{l.vatRate}%</td>
              <td className="num px-5 py-2 text-right font-medium">{eur(l.qty * l.unitPrice)}</td>
            </tr>
          ))}
        </tbody>
      </table>
      <div className="flex justify-end px-5 py-3">
        <Button variant="outline" size="sm" disabled={disabled} onClick={() => onSave(lines)}>
          Save line items
        </Button>
      </div>
    </div>
  );
}
