import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react';
import {
  Table,
  TableBody,
  TableCell,
  TableHead,
  TableHeader,
  TableRow,
} from "../ui/table";
import { Input } from "../ui/input";
import { Button } from "../ui/button";
import {
  Select,
  SelectContent,
  SelectItem,
  SelectTrigger,
  SelectValue,
} from "../ui/select";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
} from "../ui/dialog";
import { Label } from "../ui/label";
import { Switch } from "../ui/switch";
import { Badge } from "../ui/badge";
import { Plus, Edit, MoreHorizontal, ChevronsUpDown, Trash2 } from "lucide-react";
import { toast } from "sonner";
import { skipCountForPage } from "../../lib/paginationQuery";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import { Checkbox } from "../ui/checkbox";
import { SearchableSelect } from "../ui/searchable-select";
import {
  Command,
  CommandEmpty,
  CommandGroup,
  CommandInput,
  CommandItem,
  CommandList,
} from "../ui/command";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "../ui/pagination";
import { getLabels, getLabel, createLabel, updateLabel, deleteLabel } from "../../services/labelService";
import type { LabelDto, LabelCreateInput, LabelUpdateInput } from "../../types/label";
import { getLocations } from "../../services/locationService";
import { getLabelCategories } from "../../services/labelCategoryService";
import { getLabelTypes } from "../../services/labelTypeService";
import { getLabelTemplates } from "../../services/labelTemplateService";
import { getProducts } from "../../services/productService";
import type { LocationDto } from "../../types/location";
import type { LabelCategoryDto } from "../../types/labelCategory";
import type { LabelTypeDto } from "../../types/labelType";
import type { LabelTemplateDto } from "../../types/labelTemplate";
import type { ProductDto } from "../../types/product";

function toDisplay(v: string | null | undefined): string {
  const s = (v ?? "").trim();
  return s ? s : "None";
}

/** 列表行：标签编码（接口可能只返回 id 为 LabelCode） */
function labelRowCode(item: LabelDto): string {
  const c = (item.labelCode ?? item.id ?? "").trim();
  return c || "None";
}

/** 列表行：产品列（接口可能返回 `products` 汇总字符串或 `productName` / productIds） */
function labelRowProductsText(item: LabelDto): string {
  const aggregated = (item.products ?? "").trim();
  if (aggregated) return aggregated;
  const pn = (item.productName ?? "").trim();
  if (pn) return pn;
  const n = item.productIds?.length ?? 0;
  if (n > 0) return `${n} product(s)`;
  return "None";
}

/** 列表行：最后编辑时间 */
function labelRowLastEdited(item: LabelDto): string {
  const le = (item.lastEdited ?? "").trim();
  if (le) return le;
  const ct = item.creationTime;
  if (ct) {
    try {
      return new Date(ct).toLocaleString();
    } catch {
      return String(ct);
    }
  }
  return "None";
}

/** 详情 / 列表行 → 编辑表单（列表接口可能缺 ID 字段，需再以 GET 详情补全） */
function labelDtoToUpdateForm(d: LabelDto): LabelUpdateInput {
  const ids = d.productIds;
  return {
    labelName: d.labelName ?? "",
    templateCode: d.templateCode ?? "",
    locationId: d.locationId ?? "",
    labelCategoryId: d.labelCategoryId ?? "",
    labelTypeId: d.labelTypeId ?? "",
    productIds: Array.isArray(ids) ? [...ids] : [],
    labelInfoJson: d.labelInfoJson ?? null,
    state: d.state ?? true,
  };
}

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

function templateListCode(t: LabelTemplateDto): string {
  return (t.templateCode ?? t.id ?? "").trim();
}

function templateListLabel(t: LabelTemplateDto): string {
  const name = (t.templateName ?? t.name ?? "").trim() || "None";
  const code = templateListCode(t) || "None";
  return `${name} (${code})`;
}

function useLabelFormReferenceData(open: boolean) {
  const [loading, setLoading] = useState(false);
  const [templates, setTemplates] = useState<LabelTemplateDto[]>([]);
  const [locations, setLocations] = useState<LocationDto[]>([]);
  const [categories, setCategories] = useState<LabelCategoryDto[]>([]);
  const [types, setTypes] = useState<LabelTypeDto[]>([]);
  const [products, setProducts] = useState<ProductDto[]>([]);

  useEffect(() => {
    if (!open) return;
    let cancelled = false;
    (async () => {
      setLoading(true);
      try {
        const [tplRes, locRes, catRes, typeRes, prodRes] = await Promise.all([
          getLabelTemplates({ skipCount: 1, maxResultCount: 500 }),
          getLocations({ skipCount: 1, maxResultCount: 500 }),
          getLabelCategories({ skipCount: 1, maxResultCount: 500 }),
          getLabelTypes({ skipCount: 1, maxResultCount: 500 }),
          getProducts({ skipCount: 1, maxResultCount: 500 }),
        ]);
        if (cancelled) return;
        setTemplates(tplRes.items ?? []);
        setLocations(locRes.items ?? []);
        setCategories(catRes.items ?? []);
        setTypes(typeRes.items ?? []);
        setProducts(prodRes.items ?? []);
      } catch (e: any) {
        if (!cancelled) {
          toast.error("Failed to load options", {
            description: e?.message ? String(e.message) : "Check network or sign-in.",
          });
          setTemplates([]);
          setLocations([]);
          setCategories([]);
          setTypes([]);
          setProducts([]);
        }
      } finally {
        if (!cancelled) setLoading(false);
      }
    })();
    return () => {
      cancelled = true;
    };
  }, [open]);

  const productOptions: ProductOptionRow[] = useMemo(
    () =>
      products.map((p) => {
        const name =
          (p.productName ?? p.productCode ?? "").trim() || p.id;
        return { id: p.id, name };
      }),
    [products],
  );

  return { loading, templates, locations, categories, types, productOptions };
}

function ProductMultiSelectField({
  value,
  onChange,
  disabled,
  productOptions,
}: {
  value: string[];
  onChange: (next: string[]) => void;
  disabled?: boolean;
  productOptions: ProductOptionRow[];
}) {
  const [open, setOpen] = useState(false);
  const summary = useMemo(() => {
    if (value.length === 0) return "Select products (multi-select)";
    const names = value
      .map((id) => productOptions.find((p) => p.id === id)?.name ?? id)
      .slice(0, 2);
    const more = value.length > 2 ? `, ${value.length} total` : "";
    return `${names.join(", ")}${more}`;
  }, [value, productOptions]);

  const toggle = useCallback(
    (id: string, checked: boolean) => {
      const set = new Set(value);
      if (checked) set.add(id);
      else set.delete(id);
      onChange(Array.from(set));
    },
    [value, onChange],
  );

  const extraProductIds = useMemo(
    () => value.filter((id) => !productOptions.some((p) => p.id === id)),
    [value, productOptions],
  );

  return (
    <Popover open={open} onOpenChange={setOpen}>
      <PopoverTrigger asChild>
        <Button
          type="button"
          variant="outline"
          role="combobox"
          disabled={disabled}
          className="w-full justify-between h-10 px-3 font-normal border border-gray-300 bg-white"
        >
          <span className="truncate text-left text-sm">{summary}</span>
          <ChevronsUpDown className="ml-2 h-4 w-4 shrink-0 opacity-50" />
        </Button>
      </PopoverTrigger>
      <PopoverContent
        className="w-[var(--radix-popover-trigger-width)] max-w-[min(100vw-2rem,400px)] p-0"
        align="start"
      >
        <Command>
          <CommandInput placeholder="Search products…" />
          <CommandList>
            <CommandEmpty>No matching products.</CommandEmpty>
            <CommandGroup>
              {productOptions.map((p) => (
                <CommandItem
                  key={p.id}
                  value={`${p.name} ${p.id}`}
                  onSelect={() => {
                    toggle(p.id, !value.includes(p.id));
                  }}
                  className="cursor-pointer"
                >
                  <Checkbox
                    className="pointer-events-none"
                    checked={value.includes(p.id)}
                  />
                  <span className="flex-1 min-w-0">
                    <span className="font-medium">{p.name}</span>
                    <span className="block text-xs text-gray-400 truncate">{p.id}</span>
                  </span>
                </CommandItem>
              ))}
              {extraProductIds.length > 0 ? (
                <CommandGroup heading="Linked (not in current list, can deselect)">
                  {extraProductIds.map((id) => (
                    <CommandItem
                      key={id}
                      value={id}
                      onSelect={() => {
                        toggle(id, !value.includes(id));
                      }}
                      className="cursor-pointer"
                    >
                      <Checkbox className="pointer-events-none" checked={value.includes(id)} />
                      <span className="text-xs font-mono truncate">{id}</span>
                    </CommandItem>
                  ))}
                </CommandGroup>
              ) : null}
            </CommandGroup>
          </CommandList>
        </Command>
      </PopoverContent>
    </Popover>
  );
}

export function LabelsList() {
  const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
  const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
  const [editingLabel, setEditingLabel] = useState<LabelDto | null>(null);
  const [deletingLabel, setDeletingLabel] = useState<LabelDto | null>(null);
  const [labels, setLabels] = useState<LabelDto[]>([]);
  const [loading, setLoading] = useState(false);
  const [total, setTotal] = useState(0);
  const [refreshSeq, setRefreshSeq] = useState(0);
  const [actionsOpenForId, setActionsOpenForId] = useState<string | null>(null);

  const [keyword, setKeyword] = useState("");
  const [locationFilter, setLocationFilter] = useState<string>("all");
  const [labelCategoryFilter, setLabelCategoryFilter] = useState<string>("all");
  const [labelTypeFilter, setLabelTypeFilter] = useState<string>("all");
  const [templateFilter, setTemplateFilter] = useState<string>("all");
  const [stateFilter, setStateFilter] = useState<string>("all");

  const [pageIndex, setPageIndex] = useState(1);
  const [pageSize, setPageSize] = useState(10);

  const abortRef = useRef<AbortController | null>(null);
  const keywordTimerRef = useRef<number | null>(null);
  const [debouncedKeyword, setDebouncedKeyword] = useState("");

  useEffect(() => {
    if (keywordTimerRef.current) window.clearTimeout(keywordTimerRef.current);
    keywordTimerRef.current = window.setTimeout(() => setDebouncedKeyword(keyword.trim()), 300);
    return () => {
      if (keywordTimerRef.current) window.clearTimeout(keywordTimerRef.current);
    };
  }, [keyword]);

  const totalPages = Math.max(1, Math.ceil(total / pageSize));

  useEffect(() => {
    setPageIndex(1);
  }, [debouncedKeyword, locationFilter, labelCategoryFilter, labelTypeFilter, templateFilter, stateFilter, pageSize]);

  useEffect(() => {
    const run = async () => {
      abortRef.current?.abort();
      const ac = new AbortController();
      abortRef.current = ac;

      setLoading(true);
      try {
        const skipCount = skipCountForPage(pageIndex);
        const res = await getLabels(
          {
            skipCount,
            maxResultCount: pageSize,
            keyword: debouncedKeyword || undefined,
            locationId: locationFilter !== "all" ? locationFilter : undefined,
            labelCategoryId: labelCategoryFilter !== "all" ? labelCategoryFilter : undefined,
            labelTypeId: labelTypeFilter !== "all" ? labelTypeFilter : undefined,
            templateCode: templateFilter !== "all" ? templateFilter : undefined,
            state: stateFilter === "all" ? undefined : stateFilter === "true",
          },
          ac.signal,
        );

        setLabels(res.items ?? []);
        setTotal(res.totalCount ?? 0);
      } catch (e: any) {
        if (e?.name === "AbortError") return;
        toast.error("Failed to load labels.", {
          description: e?.message ? String(e.message) : "Please try again.",
        });
        setLabels([]);
        setTotal(0);
      } finally {
        setLoading(false);
      }
    };

    run();
    return () => abortRef.current?.abort();
  }, [debouncedKeyword, locationFilter, labelCategoryFilter, labelTypeFilter, templateFilter, stateFilter, pageIndex, pageSize, refreshSeq]);

  const refreshList = () => setRefreshSeq((x) => x + 1);

  const openEdit = (label: LabelDto) => {
    setActionsOpenForId(null);
    setEditingLabel(label);
    setIsEditDialogOpen(true);
  };

  const openDelete = (label: LabelDto) => {
    setActionsOpenForId(null);
    setDeletingLabel(label);
    setIsDeleteDialogOpen(true);
  };

  return (
    <div className="h-full flex flex-col">
      <div className="pb-4">
        <div className="flex flex-col gap-4">
          <div className="flex flex-nowrap items-center gap-3">
            <Input
              placeholder="Search"
              value={keyword}
              onChange={(e) => setKeyword(e.target.value)}
              style={{ height: 40, boxSizing: 'border-box' }}
              className="bg-white border border-gray-300 rounded-md w-40 shrink-0 placeholder:text-gray-500"
            />
            <Select value={locationFilter} onValueChange={setLocationFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Location" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Locations</SelectItem>
              </SelectContent>
            </Select>
            <Select value={labelCategoryFilter} onValueChange={setLabelCategoryFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Category" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Categories</SelectItem>
              </SelectContent>
            </Select>
            <Select value={labelTypeFilter} onValueChange={setLabelTypeFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="Type" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All Types</SelectItem>
              </SelectContent>
            </Select>
            <Select value={stateFilter} onValueChange={setStateFilter}>
              <SelectTrigger className="bg-white border border-gray-300 rounded-md w-[150px] shrink-0" style={{ height: 40, boxSizing: 'border-box' }}>
                <SelectValue placeholder="State" />
              </SelectTrigger>
              <SelectContent>
                <SelectItem value="all">All States</SelectItem>
                <SelectItem value="true">Active</SelectItem>
                <SelectItem value="false">Inactive</SelectItem>
              </SelectContent>
            </Select>
            <div className="flex-1" />
            <Button
              className="bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-md h-10 px-6 shrink-0"
              onClick={() => setIsCreateDialogOpen(true)}
            >
              New Label <Plus className="ml-1 h-4 w-4" />
            </Button>
          </div>
        </div>
      </div>

      <div className="flex-1 overflow-auto pt-6">
        <div className="rounded-md border bg-white shadow-sm">
          <Table>
            <TableHeader>
              <TableRow className="bg-gray-50 hover:bg-gray-50">
                <TableHead className="font-bold text-gray-900 w-[120px]">Label Code</TableHead>
                <TableHead className="font-bold text-gray-900 w-[140px]">Label Name</TableHead>
                <TableHead className="font-bold text-gray-900 w-[120px]">Location</TableHead>
                <TableHead className="font-bold text-gray-900 w-[140px]">Category</TableHead>
                <TableHead className="font-bold text-gray-900 w-[140px]">Type</TableHead>
                <TableHead className="font-bold text-gray-900 w-[120px]">Template</TableHead>
                <TableHead className="font-bold text-gray-900">Products</TableHead>
                <TableHead className="font-bold text-gray-900 w-[100px]">State</TableHead>
                <TableHead className="font-bold text-gray-900">Last Edited</TableHead>
                <TableHead className="font-bold text-gray-900 text-center w-[100px]">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading ? (
                <TableRow>
                  <TableCell colSpan={10} className="text-center text-sm text-gray-500 py-10">
                    Loading...
                  </TableCell>
                </TableRow>
              ) : labels.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={10} className="text-center text-sm text-gray-500 py-10">
                    No results.
                  </TableCell>
                </TableRow>
              ) : (
                labels.map((item) => (
                  <TableRow key={item.id} className="hover:bg-gray-50">
                    <TableCell className="font-medium whitespace-nowrap">{labelRowCode(item)}</TableCell>
                    <TableCell className="whitespace-nowrap">{toDisplay(item.labelName)}</TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap">
                      {toDisplay(item.locationName ?? item.locationId)}
                    </TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap">
                      {toDisplay(item.labelCategoryName ?? item.labelCategoryId)}
                    </TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap">
                      {toDisplay(item.labelTypeName ?? item.labelTypeId)}
                    </TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap">
                      {toDisplay(item.templateName ?? item.templateCode)}
                    </TableCell>
                    <TableCell className="text-gray-600 whitespace-nowrap">{labelRowProductsText(item)}</TableCell>
                    <TableCell>
                      <Badge className={item.state === true ? "bg-green-600" : "bg-gray-400"}>
                        {item.state === true ? "Active" : "Inactive"}
                      </Badge>
                    </TableCell>
                    <TableCell className="text-gray-500 tabular-nums font-numeric whitespace-nowrap">
                      {labelRowLastEdited(item)}
                    </TableCell>
                    <TableCell className="text-center">
                      <Popover
                        open={actionsOpenForId === item.id}
                        onOpenChange={(open) => setActionsOpenForId(open ? item.id : null)}
                      >
                        <PopoverTrigger asChild>
                          <Button
                            type="button"
                            variant="ghost"
                            size="icon"
                            className="h-8 w-8"
                            aria-label="Row actions"
                          >
                            <MoreHorizontal className="h-4 w-4 text-gray-500" />
                          </Button>
                        </PopoverTrigger>
                        <PopoverContent align="end" className="w-40 p-1">
                          <Button
                            type="button"
                            variant="ghost"
                            className="w-full justify-start gap-2 h-9 px-2 font-normal"
                            onClick={() => openEdit(item)}
                          >
                            <Edit className="w-4 h-4" />
                            Edit
                          </Button>
                          <Button
                            type="button"
                            variant="ghost"
                            className="w-full justify-start gap-2 h-9 px-2 font-normal text-red-600 hover:text-red-700 hover:bg-red-50"
                            onClick={() => openDelete(item)}
                          >
                            <Trash2 className="w-4 h-4 shrink-0" />
                            Delete
                          </Button>
                        </PopoverContent>
                      </Popover>
                    </TableCell>
                  </TableRow>
                ))
              )}
            </TableBody>
          </Table>
        </div>
      </div>

      <div className="pt-4">
        <div className="flex items-center justify-between text-sm text-gray-600">
          <div>
            Showing {total === 0 ? 0 : (pageIndex - 1) * pageSize + 1}-
            {Math.min(pageIndex * pageSize, total)} of {total}
          </div>
          <div className="flex items-center gap-3">
            <Select value={String(pageSize)} onValueChange={(v) => setPageSize(Number(v))}>
              <SelectTrigger className="w-[110px] h-9 rounded-md border border-gray-300 bg-white text-gray-900">
                <SelectValue />
              </SelectTrigger>
              <SelectContent>
                {[10, 20, 50].map((n) => (
                  <SelectItem key={n} value={String(n)}>
                    {n} / page
                  </SelectItem>
                ))}
              </SelectContent>
            </Select>
            <Pagination className="mx-0 w-auto justify-end">
              <PaginationContent>
                <PaginationItem>
                  <PaginationPrevious
                    href="#"
                    size="default"
                    onClick={(e) => {
                      e.preventDefault();
                      setPageIndex((p) => Math.max(1, p - 1));
                    }}
                    aria-disabled={pageIndex <= 1}
                    className={pageIndex <= 1 ? "pointer-events-none opacity-50" : ""}
                  />
                </PaginationItem>
                <PaginationItem>
                  <PaginationLink
                    href="#"
                    isActive
                    size="default"
                    onClick={(e) => e.preventDefault()}
                  >
                    Page {pageIndex} / {totalPages}
                  </PaginationLink>
                </PaginationItem>
                <PaginationItem>
                  <PaginationNext
                    href="#"
                    size="default"
                    onClick={(e) => {
                      e.preventDefault();
                      setPageIndex((p) => Math.min(totalPages, p + 1));
                    }}
                    aria-disabled={pageIndex >= totalPages}
                    className={pageIndex >= totalPages ? "pointer-events-none opacity-50" : ""}
                  />
                </PaginationItem>
              </PaginationContent>
            </Pagination>
          </div>
        </div>
      </div>

      <CreateLabelDialog
        open={isCreateDialogOpen}
        onOpenChange={setIsCreateDialogOpen}
        onCreated={() => {
          setPageIndex(1);
          refreshList();
        }}
      />

      <EditLabelDialog
        open={isEditDialogOpen}
        label={editingLabel}
        onOpenChange={(open) => {
          setIsEditDialogOpen(open);
          if (!open) setEditingLabel(null);
        }}
        onUpdated={refreshList}
      />

      <DeleteLabelDialog
        open={isDeleteDialogOpen}
        label={deletingLabel}
        onOpenChange={(open) => {
          setIsDeleteDialogOpen(open);
          if (!open) setDeletingLabel(null);
        }}
        onDeleted={refreshList}
      />
    </div>
  );
}

function CreateLabelDialog({
  open,
  onOpenChange,
  onCreated,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onCreated: () => void;
}) {
  const { loading: refLoading, templates, locations, categories, types, productOptions } =
    useLabelFormReferenceData(open);
  const [submitting, setSubmitting] = useState(false);
  const [form, setForm] = useState<LabelCreateInput>({
    labelCode: "",
    labelName: "",
    templateCode: "",
    locationId: "",
    labelCategoryId: "",
    labelTypeId: "",
    productIds: [],
    labelInfoJson: null,
    state: true,
  });

  const resetForm = () => {
    setForm({
      labelCode: "",
      labelName: "",
      templateCode: "",
      locationId: "",
      labelCategoryId: "",
      labelTypeId: "",
      productIds: [],
      labelInfoJson: null,
      state: true,
    });
  };

  useEffect(() => {
    if (!open) {
      resetForm();
    }
  }, [open]);

  const submit = async () => {
    if (!form.labelCode.trim() || !form.labelName.trim() || !form.templateCode.trim() || !form.locationId.trim() || !form.labelCategoryId.trim() || !form.labelTypeId.trim()) {
      toast.error("Validation failed", {
        description: "Fill all required fields and select template, location, category, and type.",
      });
      return;
    }
    if (form.productIds.length === 0) {
      toast.error("Validation failed", {
        description: "Select at least one product.",
      });
      return;
    }

    setSubmitting(true);
    try {
      await createLabel(form);
      toast.success("Label created.", {
        description: "The label has been created successfully.",
      });
      onOpenChange(false);
      onCreated();
    } catch (e: any) {
      toast.error("Failed to create label.", {
        description: e?.message ? String(e.message) : "Please try again.",
      });
    } finally {
      setSubmitting(false);
    }
  };

  const templateOptions = useMemo(
    () =>
      templates
        .filter((t) => templateListCode(t))
        .map((t) => ({
          value: templateListCode(t),
          label: templateListLabel(t),
        })),
    [templates],
  );

  const locationOptions = useMemo(
    () =>
      locations.map((loc) => ({
        value: loc.id,
        label: toDisplay(loc.locationName ?? loc.locationCode ?? loc.id),
      })),
    [locations],
  );

  const categoryOptions = useMemo(
    () =>
      categories.map((c) => ({
        value: c.id,
        label: toDisplay(c.categoryName ?? c.categoryCode ?? c.id),
      })),
    [categories],
  );

  const typeOptions = useMemo(
    () =>
      types.map((ty) => ({
        value: ty.id,
        label: toDisplay(ty.typeName ?? ty.typeCode ?? ty.id),
      })),
    [types],
  );

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle>Add New Label</DialogTitle>
          <DialogDescription>Enter the details for the new label.</DialogDescription>
        </DialogHeader>

        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Label Code *</Label>
              <Input
                className="h-10"
                placeholder="e.g. LBL_TEST_001"
                value={form.labelCode}
                onChange={(e) => setForm((p) => ({ ...p, labelCode: e.target.value }))}
              />
            </div>
            <div className="space-y-2">
              <Label>Label Name *</Label>
              <Input
                className="h-10"
                placeholder="e.g. Breakfast label"
                value={form.labelName}
                onChange={(e) => setForm((p) => ({ ...p, labelName: e.target.value }))}
              />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Label Template *</Label>
              <SearchableSelect
                value={form.templateCode}
                onValueChange={(v) => setForm((p) => ({ ...p, templateCode: v }))}
                options={templateOptions}
                placeholder="Select template"
                searchPlaceholder="Search template…"
                emptyText="No templates found."
                disabled={refLoading}
              />
            </div>
            <div className="space-y-2">
              <Label>Location *</Label>
              <SearchableSelect
                value={form.locationId}
                onValueChange={(v) => setForm((p) => ({ ...p, locationId: v }))}
                options={locationOptions}
                placeholder="Select location"
                searchPlaceholder="Search location…"
                emptyText="No locations found."
                disabled={refLoading}
              />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Label Category *</Label>
              <SearchableSelect
                value={form.labelCategoryId}
                onValueChange={(v) => setForm((p) => ({ ...p, labelCategoryId: v }))}
                options={categoryOptions}
                placeholder="Select category"
                searchPlaceholder="Search category…"
                emptyText="No categories found."
                disabled={refLoading}
              />
            </div>
            <div className="space-y-2">
              <Label>Label Type *</Label>
              <SearchableSelect
                value={form.labelTypeId}
                onValueChange={(v) => setForm((p) => ({ ...p, labelTypeId: v }))}
                options={typeOptions}
                placeholder="Select type"
                searchPlaceholder="Search type…"
                emptyText="No types found."
                disabled={refLoading}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Product * (multi-select)</Label>
            <ProductMultiSelectField
              value={form.productIds}
              onChange={(next) => setForm((p) => ({ ...p, productIds: next }))}
              disabled={refLoading}
              productOptions={productOptions}
            />
          </div>

          <div
            className="flex items-center justify-between border border-gray-200 rounded-md px-3 bg-white"
            style={{ height: 40 }}
          >
            <div className="text-sm font-medium text-gray-900">Enabled</div>
            <Switch checked={form.state} onCheckedChange={(checked) => setForm((p) => ({ ...p, state: checked }))} />
          </div>
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button disabled={submitting || refLoading} onClick={submit}>
            {submitting ? "Creating…" : "Create"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function EditLabelDialog({
  open,
  label,
  onOpenChange,
  onUpdated,
}: {
  open: boolean;
  label: LabelDto | null;
  onOpenChange: (open: boolean) => void;
  onUpdated: () => void;
}) {
  const { loading: refLoading, templates, locations, categories, types, productOptions } =
    useLabelFormReferenceData(open);
  const [submitting, setSubmitting] = useState(false);
  const [detailLoading, setDetailLoading] = useState(false);
  const [form, setForm] = useState<LabelUpdateInput>({
    labelName: "",
    templateCode: "",
    locationId: "",
    labelCategoryId: "",
    labelTypeId: "",
    productIds: [],
    labelInfoJson: null,
    state: true,
  });

  useEffect(() => {
    if (!open || !label?.id) return;

    const id = label.id;
    setForm(labelDtoToUpdateForm(label));

    const ac = new AbortController();
    let cancelled = false;
    setDetailLoading(true);
    (async () => {
      try {
        const detail = await getLabel(id, ac.signal);
        if (cancelled) return;
        setForm(labelDtoToUpdateForm(detail));
      } catch (e: any) {
        if (cancelled || e?.name === "AbortError") return;
        toast.error("Failed to load label details.", {
          description: e?.message ? String(e.message) : "Form shows list data only; check network.",
        });
      } finally {
        if (!cancelled) setDetailLoading(false);
      }
    })();

    return () => {
      cancelled = true;
      ac.abort();
    };
  }, [open, label]);

  const submit = async () => {
    if (!label?.id) return;
    if (!form.labelName.trim() || !form.templateCode.trim() || !form.locationId.trim() || !form.labelCategoryId.trim() || !form.labelTypeId.trim()) {
      toast.error("Validation failed", {
        description: "Fill all required fields and select template, location, category, and type.",
      });
      return;
    }
    if (form.productIds.length === 0) {
      toast.error("Validation failed", {
        description: "Select at least one product.",
      });
      return;
    }

    setSubmitting(true);
    try {
      await updateLabel(label.id, form);
      toast.success("Label updated.", {
        description: "The label has been updated successfully.",
      });
      onOpenChange(false);
      onUpdated();
    } catch (e: any) {
      toast.error("Failed to update label.", {
        description: e?.message ? String(e.message) : "Please try again.",
      });
    } finally {
      setSubmitting(false);
    }
  };

  const editTemplateOptions = useMemo(() => {
    const base = templates
      .filter((t) => templateListCode(t))
      .map((t) => ({
        value: templateListCode(t),
        label: templateListLabel(t),
      }));
    const c = form.templateCode;
    if (c && !base.some((o) => o.value === c)) {
      return [{ value: c, label: `${c} (current)` }, ...base];
    }
    return base;
  }, [templates, form.templateCode]);

  const editLocationOptions = useMemo(() => {
    const base = locations.map((loc) => ({
      value: loc.id,
      label: toDisplay(loc.locationName ?? loc.locationCode ?? loc.id),
    }));
    const id = form.locationId;
    if (id && !base.some((o) => o.value === id)) {
      return [{ value: id, label: `${id} (current)` }, ...base];
    }
    return base;
  }, [locations, form.locationId]);

  const editCategoryOptions = useMemo(() => {
    const base = categories.map((c) => ({
      value: c.id,
      label: toDisplay(c.categoryName ?? c.categoryCode ?? c.id),
    }));
    const id = form.labelCategoryId;
    if (id && !base.some((o) => o.value === id)) {
      return [{ value: id, label: `${id} (current)` }, ...base];
    }
    return base;
  }, [categories, form.labelCategoryId]);

  const editTypeOptions = useMemo(() => {
    const base = types.map((ty) => ({
      value: ty.id,
      label: toDisplay(ty.typeName ?? ty.typeCode ?? ty.id),
    }));
    const id = form.labelTypeId;
    if (id && !base.some((o) => o.value === id)) {
      return [{ value: id, label: `${id} (current)` }, ...base];
    }
    return base;
  }, [types, form.labelTypeId]);

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle>Edit Label</DialogTitle>
          <DialogDescription>
            {detailLoading ? "Loading label details…" : "Update the label details."}
          </DialogDescription>
        </DialogHeader>

        <div className="grid gap-4 py-4">
          <div className="space-y-2">
            <Label>Label Name *</Label>
            <Input
              className="h-10"
              placeholder="e.g. Breakfast label"
              value={form.labelName}
              onChange={(e) => setForm((p) => ({ ...p, labelName: e.target.value }))}
              disabled={detailLoading}
            />
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Label Template *</Label>
              <SearchableSelect
                value={form.templateCode}
                onValueChange={(v) => setForm((p) => ({ ...p, templateCode: v }))}
                options={editTemplateOptions}
                placeholder="Select template"
                searchPlaceholder="Search template…"
                emptyText="No templates found."
                disabled={refLoading || detailLoading}
              />
            </div>
            <div className="space-y-2">
              <Label>Location *</Label>
              <SearchableSelect
                value={form.locationId}
                onValueChange={(v) => setForm((p) => ({ ...p, locationId: v }))}
                options={editLocationOptions}
                placeholder="Select location"
                searchPlaceholder="Search location…"
                emptyText="No locations found."
                disabled={refLoading || detailLoading}
              />
            </div>
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Label Category *</Label>
              <SearchableSelect
                value={form.labelCategoryId}
                onValueChange={(v) => setForm((p) => ({ ...p, labelCategoryId: v }))}
                options={editCategoryOptions}
                placeholder="Select category"
                searchPlaceholder="Search category…"
                emptyText="No categories found."
                disabled={refLoading || detailLoading}
              />
            </div>
            <div className="space-y-2">
              <Label>Label Type *</Label>
              <SearchableSelect
                value={form.labelTypeId}
                onValueChange={(v) => setForm((p) => ({ ...p, labelTypeId: v }))}
                options={editTypeOptions}
                placeholder="Select type"
                searchPlaceholder="Search type…"
                emptyText="No types found."
                disabled={refLoading || detailLoading}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Product * (multi-select)</Label>
            <ProductMultiSelectField
              value={form.productIds}
              onChange={(next) => setForm((p) => ({ ...p, productIds: next }))}
              disabled={refLoading || detailLoading}
              productOptions={productOptions}
            />
          </div>

          <div
            className="flex items-center justify-between border border-gray-200 rounded-md px-3 bg-white"
            style={{ height: 40 }}
          >
            <div className="text-sm font-medium text-gray-900">Enabled</div>
            <Switch
              checked={form.state}
              onCheckedChange={(checked) => setForm((p) => ({ ...p, state: checked }))}
              disabled={detailLoading}
            />
          </div>
        </div>

        <DialogFooter>
          <Button variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button disabled={submitting || refLoading || detailLoading} onClick={submit}>
            {submitting ? "Updating…" : "Update"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

function DeleteLabelDialog({
  open,
  label,
  onOpenChange,
  onDeleted,
}: {
  open: boolean;
  label: LabelDto | null;
  onOpenChange: (open: boolean) => void;
  onDeleted: () => void;
}) {
  const [submitting, setSubmitting] = useState(false);

  const name = useMemo(() => {
    const n = (label?.labelName ?? "").trim();
    return n || label?.labelCode || label?.id || "this label";
  }, [label]);

  const submit = async () => {
    if (!label?.id) return;
    setSubmitting(true);
    try {
      await deleteLabel(label.id);
      toast.success("Label deleted.", {
        description: "The label has been removed successfully.",
      });
      onOpenChange(false);
      onDeleted();
    } catch (e: any) {
      toast.error("Failed to delete label.", {
        description: e?.message ? String(e.message) : "Please try again.",
      });
    } finally {
      setSubmitting(false);
    }
  };

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-none" style={{ width: "30%" }}>
        <DialogHeader>
          <DialogTitle>Delete Label</DialogTitle>
          <DialogDescription>This action cannot be undone.</DialogDescription>
        </DialogHeader>

        <div className="text-sm text-gray-700">
          Are you sure you want to delete <span className="font-medium">{name}</span>?
        </div>

        <DialogFooter className="flex-row flex-wrap justify-end">
          <Button className="min-w-24" variant="outline" onClick={() => onOpenChange(false)}>
            Cancel
          </Button>
          <Button
            className="min-w-24 gap-2"
            variant="destructive"
            disabled={submitting}
            onClick={submit}
          >
            <Trash2 className="h-4 w-4 shrink-0" />
            {submitting ? "Deleting..." : "Delete"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
