"use client";

import { useCallback, useEffect, useMemo, useState } from "react";
import Link from "next/link";
import { useParams, useRouter, useSearchParams } from "next/navigation";
import MainTitle from "@/components/layout/dashboard/main-title";
import ProductThumb from "@/components/app/product-thumb";
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 DataService from "@/config/axios";
import { useRequireSuperAdmin } from "@/hooks/use-require-super-admin";
import { getApiErrorMessage } from "@/lib/api-error";
import { toast } from "sonner";

type Supplier = { _id: string; name: string; active?: boolean };
type Warehouse = { _id: string; name: string; code: string; active?: boolean; isDefault?: boolean };
type ProductRow = {
  _id: string;
  title: string;
  status: string;
  stock?: number;
  images?: string[];
  variants?: { name: string; values: { label: string; stock?: number | null }[] }[];
};

type LineDraft = {
  product: string;
  variantKey: string;
  warehouse: string;
  qty: string;
  unitCost: string;
};

type Props = {
  billId: string | null;
};

function slotOptionsFor(product: ProductRow | undefined) {
  const opts = [{ value: "", label: "Main stock" }];
  if (!product) return opts;
  for (const g of product.variants || []) {
    for (const v of g.values || []) {
      if (v.stock != null && Number(v.stock) >= 0) {
        opts.push({ value: `opt:${g.name}:${v.label}`, label: `${g.name}: ${v.label}` });
      }
    }
  }
  return opts;
}

export default function SupplierBillEditor({ billId }: Props) {
  const ready = useRequireSuperAdmin();
  const params = useParams();
  const app = params.app as string;
  const router = useRouter();
  const searchParams = useSearchParams();
  const isNew = !billId;

  const [loading, setLoading] = useState(true);
  const [busy, setBusy] = useState(false);
  const [suppliers, setSuppliers] = useState<Supplier[]>([]);
  const [warehouses, setWarehouses] = useState<Warehouse[]>([]);
  const [products, setProducts] = useState<ProductRow[]>([]);
  const [status, setStatus] = useState("draft");
  const [supplier, setSupplier] = useState("");
  const [billNumber, setBillNumber] = useState("");
  const [invoiceNumber, setInvoiceNumber] = useState("");
  const [invoiceFileUrl, setInvoiceFileUrl] = useState("");
  const [billDate, setBillDate] = useState(() => new Date().toISOString().slice(0, 10));
  const [notes, setNotes] = useState("");
  const [lines, setLines] = useState<LineDraft[]>([
    { product: "", variantKey: "", warehouse: "", qty: "1", unitCost: "0" },
  ]);
  const [productFilter, setProductFilter] = useState("");
  const [receiveOnCreate, setReceiveOnCreate] = useState(false);

  const defaultWarehouseId = useMemo(() => {
    const def = warehouses.find((w) => w.isDefault) || warehouses[0];
    return def?._id || "";
  }, [warehouses]);

  const loadMeta = useCallback(async () => {
    const [sRes, wRes, pRes] = await Promise.all([
      DataService.get("/admin/suppliers"),
      DataService.get("/admin/warehouses"),
      DataService.get("/admin/inventory/products"),
    ]);
    setSuppliers((sRes.data?.data || []).filter((s: Supplier) => s.active !== false));
    setWarehouses((wRes.data?.data || []).filter((w: Warehouse) => w.active !== false));
    setProducts(pRes.data?.data || []);
  }, []);

  const loadBill = useCallback(async () => {
    if (!billId) return;
    const res = await DataService.get(`/admin/supplier-bills/${billId}`);
    const b = res.data?.data;
    if (!b) throw new Error("Bill not found");
    setStatus(b.status || "draft");
    setSupplier(b.supplier?._id || b.supplier || "");
    setBillNumber(b.billNumber || "");
    setInvoiceNumber(b.invoiceNumber || "");
    setInvoiceFileUrl(b.invoiceFileUrl || "");
    setBillDate(b.billDate ? new Date(b.billDate).toISOString().slice(0, 10) : "");
    setNotes(b.notes || "");
    setLines(
      (b.lines || []).map((l: {
        product: { _id?: string } | string;
        variantKey?: string;
        warehouse: { _id?: string } | string;
        qty: number;
        unitCost?: number;
      }) => ({
        product: typeof l.product === "object" ? l.product._id || "" : String(l.product || ""),
        variantKey: l.variantKey || "",
        warehouse:
          typeof l.warehouse === "object" ? l.warehouse._id || "" : String(l.warehouse || ""),
        qty: String(l.qty ?? 1),
        unitCost: String(l.unitCost ?? 0),
      }))
    );
  }, [billId]);

  useEffect(() => {
    if (!ready) return;
    (async () => {
      try {
        await loadMeta();
        if (billId) await loadBill();
        else {
          const pre = searchParams.get("supplier");
          if (pre) setSupplier(pre);
        }
      } catch (e: unknown) {
        toast.error(getApiErrorMessage(e, "Failed to load bill"));
      } finally {
        setLoading(false);
      }
    })();
  }, [ready, billId, loadMeta, loadBill, searchParams]);

  useEffect(() => {
    if (!defaultWarehouseId) return;
    setLines((prev) =>
      prev.map((l) => (l.warehouse ? l : { ...l, warehouse: defaultWarehouseId }))
    );
  }, [defaultWarehouseId]);

  const filteredProducts = products.filter((p) => {
    if (!productFilter.trim()) return true;
    const q = productFilter.trim().toLowerCase();
    return p.title.toLowerCase().includes(q) || p.status.toLowerCase().includes(q);
  });

  const subtotal = lines.reduce((sum, l) => {
    return sum + Math.max(0, Number(l.qty) || 0) * Math.max(0, Number(l.unitCost) || 0);
  }, 0);

  const uploadInvoice = async (file: File) => {
    const fd = new FormData();
    fd.append("file", file);
    try {
      const res = await DataService.post("/admin/uploads/supplier-invoice", fd);
      const url = res.data?.data?.url || "";
      setInvoiceFileUrl(url);
      toast.success("Invoice uploaded");
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Upload failed"));
    }
  };

  const save = async (e: React.FormEvent) => {
    e.preventDefault();
    if (!isNew && status === "cancelled") {
      toast.error("Cancelled bills cannot be edited");
      return;
    }
    if (!isNew && status === "received") {
      const ok = confirm(
        "This bill is already received. Saving will reverse previous stock and re-post the updated lines. Continue?"
      );
      if (!ok) return;
    }
    setBusy(true);
    try {
      const payload = {
        supplier,
        billNumber: billNumber.trim(),
        invoiceNumber: invoiceNumber.trim(),
        invoiceFileUrl,
        billDate,
        notes: notes.trim(),
        lines: lines.map((l) => ({
          product: l.product,
          variantKey: l.variantKey,
          warehouse: l.warehouse,
          qty: Number(l.qty),
          unitCost: Number(l.unitCost) || 0,
        })),
      };
      if (isNew) {
        const res = await DataService.post("/admin/supplier-bills", payload);
        const id = res.data?.data?._id;
        if (receiveOnCreate && id) {
          await DataService.post(`/admin/supplier-bills/${id}/receive`);
          toast.success("Bill created and added to inventory");
        } else {
          toast.success("Bill created as draft");
        }
        if (id) router.push(`/${app}/admin/suppliers/bills/${id}`);
        else router.push(`/${app}/admin/suppliers/bills`);
      } else {
        await DataService.patch(`/admin/supplier-bills/${billId}`, payload);
        toast.success(status === "received" ? "Bill updated and stock re-posted" : "Bill updated");
        await loadBill();
      }
    } catch (err: unknown) {
      toast.error(getApiErrorMessage(err, "Could not save bill"));
    } finally {
      setBusy(false);
    }
  };

  const receive = async () => {
    if (!billId || !confirm("Add this bill into warehouse inventory?")) return;
    setBusy(true);
    try {
      await DataService.post(`/admin/supplier-bills/${billId}/receive`);
      toast.success("Added to inventory");
      await loadBill();
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not add to inventory"));
    } finally {
      setBusy(false);
    }
  };

  const cancel = async () => {
    if (!billId || !confirm("Cancel this bill?")) return;
    setBusy(true);
    try {
      await DataService.post(`/admin/supplier-bills/${billId}/cancel`);
      toast.success("Cancelled");
      await loadBill();
    } catch (e: unknown) {
      toast.error(getApiErrorMessage(e, "Could not cancel"));
    } finally {
      setBusy(false);
    }
  };

  if (!ready || loading) {
    return <div className="rounded-md border bg-white p-8 text-center text-gray-500">Loading…</div>;
  }

  const editable = isNew || status === "draft" || status === "received";

  return (
    <div className="space-y-6">
      <div className="flex flex-wrap items-start justify-between gap-3">
        <div>
          <MainTitle title={isNew ? "New supplier bill" : `Edit bill ${billNumber || ""}`} />
          <p className="text-sm text-gray-500">
            Status: <span className="capitalize">{status}</span>
            {" · "}
            {editable
              ? "Edit supplier, invoice, notes, and all line items."
              : "Cancelled bills are read-only."}
          </p>
        </div>
        <Button type="button" variant="outline" asChild>
          <Link href={`/${app}/admin/suppliers/bills`}>Back to bills</Link>
        </Button>
      </div>

      <form onSubmit={save} className="space-y-4 rounded-md border bg-white p-4">
        <div className="grid gap-3 md:grid-cols-2">
          <div className="grid gap-2">
            <Label>Supplier</Label>
            <Select value={supplier} onValueChange={setSupplier} disabled={!editable}>
              <SelectTrigger>
                <SelectValue placeholder="Select supplier" />
              </SelectTrigger>
              <SelectContent>
                {suppliers.map((s) => (
                  <SelectItem key={s._id} value={s._id}>
                    {s.name}
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
          </div>
          <div className="grid gap-2">
            <Label>Bill number</Label>
            <Input
              value={billNumber}
              onChange={(e) => setBillNumber(e.target.value)}
              required
              disabled={!editable}
            />
          </div>
          <div className="grid gap-2">
            <Label>Invoice number (optional)</Label>
            <Input
              value={invoiceNumber}
              onChange={(e) => setInvoiceNumber(e.target.value)}
              disabled={!editable}
            />
          </div>
          <div className="grid gap-2">
            <Label>Bill date</Label>
            <Input
              type="date"
              value={billDate}
              onChange={(e) => setBillDate(e.target.value)}
              disabled={!editable}
            />
          </div>
          <div className="grid gap-2 md:col-span-2">
            <Label>Invoice file (optional)</Label>
            <div className="flex flex-wrap items-center gap-3">
              <Input
                type="file"
                accept="image/*,.pdf"
                disabled={!editable}
                onChange={(e) => {
                  const f = e.target.files?.[0];
                  if (f) uploadInvoice(f);
                }}
              />
              {invoiceFileUrl ? (
                <a
                  href={invoiceFileUrl}
                  target="_blank"
                  rel="noreferrer"
                  className="text-sm text-blue-600 underline"
                >
                  View invoice
                </a>
              ) : null}
            </div>
          </div>
          <div className="grid gap-2 md:col-span-2">
            <Label>Notes</Label>
            <Input
              value={notes}
              onChange={(e) => setNotes(e.target.value)}
              disabled={!editable}
            />
          </div>
        </div>

        <div className="space-y-3 border-t pt-4">
          <div className="flex flex-wrap items-end justify-between gap-3">
            <div>
              <h3 className="font-medium">Line items</h3>
              <p className="text-xs text-gray-500">Filter products (includes unpublished).</p>
            </div>
            <Input
              className="max-w-xs"
              placeholder="Filter products…"
              value={productFilter}
              onChange={(e) => setProductFilter(e.target.value)}
              disabled={!editable}
            />
          </div>

          {lines.map((line, idx) => {
            const product = products.find((p) => p._id === line.product);
            const slots = slotOptionsFor(product);
            return (
              <div
                key={idx}
                className="grid gap-2 rounded-md border border-gray-100 p-3 md:grid-cols-6"
              >
                <div className="grid gap-1 md:col-span-2">
                  <Label className="text-xs">Product</Label>
                  <Select
                    value={line.product}
                    disabled={!editable}
                    onValueChange={(v) =>
                      setLines((prev) =>
                        prev.map((l, i) =>
                          i === idx ? { ...l, product: v, variantKey: "" } : l
                        )
                      )
                    }
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Product" />
                    </SelectTrigger>
                    <SelectContent className="max-h-64">
                      {filteredProducts.map((p) => (
                        <SelectItem key={p._id} value={p._id}>
                          <span className="flex items-center gap-2">
                            <ProductThumb src={p.images?.[0]} alt={p.title} />
                            <span>
                              {p.title} [{p.status}]
                            </span>
                          </span>
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                {slots.length > 1 ? (
                  <div className="grid gap-1">
                    <Label className="text-xs">Slot</Label>
                    <Select
                      value={line.variantKey || "__main__"}
                      disabled={!editable}
                      onValueChange={(v) =>
                        setLines((prev) =>
                          prev.map((l, i) =>
                            i === idx
                              ? { ...l, variantKey: v === "__main__" ? "" : v }
                              : l
                          )
                        )
                      }
                    >
                      <SelectTrigger>
                        <SelectValue />
                      </SelectTrigger>
                      <SelectContent>
                        {slots.map((s) => (
                          <SelectItem key={s.value || "__main__"} value={s.value || "__main__"}>
                            {s.label}
                          </SelectItem>
                        ))}
                      </SelectContent>
                    </Select>
                  </div>
                ) : (
                  <div />
                )}
                <div className="grid gap-1">
                  <Label className="text-xs">Warehouse</Label>
                  <Select
                    value={line.warehouse}
                    disabled={!editable}
                    onValueChange={(v) =>
                      setLines((prev) =>
                        prev.map((l, i) => (i === idx ? { ...l, warehouse: v } : l))
                      )
                    }
                  >
                    <SelectTrigger>
                      <SelectValue placeholder="Warehouse" />
                    </SelectTrigger>
                    <SelectContent>
                      {warehouses.map((w) => (
                        <SelectItem key={w._id} value={w._id}>
                          {w.name}
                        </SelectItem>
                      ))}
                    </SelectContent>
                  </Select>
                </div>
                <div className="grid gap-1">
                  <Label className="text-xs">Qty</Label>
                  <Input
                    type="number"
                    min={1}
                    value={line.qty}
                    disabled={!editable}
                    onChange={(e) =>
                      setLines((prev) =>
                        prev.map((l, i) => (i === idx ? { ...l, qty: e.target.value } : l))
                      )
                    }
                  />
                </div>
                <div className="grid gap-1">
                  <Label className="text-xs">Unit cost</Label>
                  <div className="flex gap-2">
                    <Input
                      type="number"
                      min={0}
                      step="0.01"
                      value={line.unitCost}
                      disabled={!editable}
                      onChange={(e) =>
                        setLines((prev) =>
                          prev.map((l, i) =>
                            i === idx ? { ...l, unitCost: e.target.value } : l
                          )
                        )
                      }
                    />
                    {editable && lines.length > 1 ? (
                      <Button
                        type="button"
                        variant="outline"
                        size="sm"
                        onClick={() => setLines((prev) => prev.filter((_, i) => i !== idx))}
                      >
                        ×
                      </Button>
                    ) : null}
                  </div>
                </div>
              </div>
            );
          })}

          {editable ? (
            <Button
              type="button"
              variant="outline"
              onClick={() =>
                setLines((prev) => [
                  ...prev,
                  {
                    product: "",
                    variantKey: "",
                    warehouse: defaultWarehouseId,
                    qty: "1",
                    unitCost: "0",
                  },
                ])
              }
            >
              Add line
            </Button>
          ) : null}

          <div className="text-right text-sm font-medium">Subtotal: {subtotal.toFixed(2)}</div>
        </div>

        <div className="flex flex-wrap items-center gap-3 border-t pt-4">
          {isNew ? (
            <label className="mr-auto flex items-center gap-2 text-sm">
              <input
                type="checkbox"
                checked={receiveOnCreate}
                onChange={(e) => setReceiveOnCreate(e.target.checked)}
              />
              Add to inventory immediately (receive on create)
            </label>
          ) : null}
          {editable ? (
            <Button type="submit" disabled={busy}>
              {busy
                ? "Saving…"
                : isNew
                  ? receiveOnCreate
                    ? "Create & add to inventory"
                    : "Create draft bill"
                  : status === "received"
                    ? "Save changes"
                    : "Save draft"}
            </Button>
          ) : null}
          {!isNew && status === "draft" ? (
            <Button type="button" disabled={busy} onClick={receive}>
              Add to inventory
            </Button>
          ) : null}
          {!isNew && status !== "cancelled" ? (
            <Button type="button" variant="outline" disabled={busy} onClick={cancel}>
              Cancel bill
            </Button>
          ) : null}
        </div>
      </form>
    </div>
  );
}
