import React, { useEffect, useMemo, useRef, useState } 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, X } from "lucide-react";
import { toast } from "sonner";
import { Popover, PopoverContent, PopoverTrigger } from "../ui/popover";
import {
  Pagination,
  PaginationContent,
  PaginationItem,
  PaginationLink,
  PaginationNext,
  PaginationPrevious,
} from "../ui/pagination";
import {
  getLabelMultipleOptions,
  getLabelMultipleOption,
  createLabelMultipleOption,
  updateLabelMultipleOption,
  deleteLabelMultipleOption,
} from "../../services/labelMultipleOptionService";
import type {
  LabelMultipleOptionDto,
  LabelMultipleOptionCreateInput,
  LabelMultipleOptionUpdateInput,
} from "../../types/labelMultipleOption";

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

export function MultipleOptionsView() {
  const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false);
  const [isEditDialogOpen, setIsEditDialogOpen] = useState(false);
  const [isDeleteDialogOpen, setIsDeleteDialogOpen] = useState(false);
  const [editingOption, setEditingOption] = useState<LabelMultipleOptionDto | null>(null);
  const [deletingOption, setDeletingOption] = useState<LabelMultipleOptionDto | null>(null);
  const [options, setOptions] = useState<LabelMultipleOptionDto[]>([]);
  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 [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, stateFilter, pageSize]);

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

      setLoading(true);
      try {
        const skipCount = (pageIndex - 1) * pageSize;
        const res = await getLabelMultipleOptions(
          {
            skipCount,
            maxResultCount: pageSize,
            keyword: debouncedKeyword || undefined,
            state: stateFilter === "all" ? undefined : stateFilter === "true",
          },
          ac.signal,
        );

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

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

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

  const openEdit = (opt: LabelMultipleOptionDto) => {
    setActionsOpenForId(null);
    setEditingOption(opt);
    setIsEditDialogOpen(true);
  };

  const openDelete = (opt: LabelMultipleOptionDto) => {
    setActionsOpenForId(null);
    setDeletingOption(opt);
    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={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 Multiple Options <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-[200px]">Multiple Option Name</TableHead>
                <TableHead className="font-bold text-gray-900 w-[200px]">Option Code</TableHead>
                <TableHead className="font-bold text-gray-900">Contents</TableHead>
                <TableHead className="font-bold text-gray-900 w-[100px]">State</TableHead>
                <TableHead className="font-bold text-gray-900 w-[100px]">Order</TableHead>
                <TableHead className="font-bold text-gray-900 w-[180px]">Last Edited</TableHead>
                <TableHead className="font-bold text-gray-900 text-center w-[100px]">Actions</TableHead>
              </TableRow>
            </TableHeader>
            <TableBody>
              {loading ? (
                <TableRow>
                  <TableCell colSpan={7} className="text-center text-sm text-gray-500 py-10">
                    Loading...
                  </TableCell>
                </TableRow>
              ) : options.length === 0 ? (
                <TableRow>
                  <TableCell colSpan={7} className="text-center text-sm text-gray-500 py-10">
                    No results.
                  </TableCell>
                </TableRow>
              ) : (
                options.map((item) => (
                  <TableRow key={item.id} className="hover:bg-gray-50">
                    <TableCell className="font-medium">{toDisplay(item.optionName)}</TableCell>
                    <TableCell className="text-gray-600">{toDisplay(item.optionCode)}</TableCell>
                    <TableCell className="text-gray-600">
                      {item.optionValuesJson && item.optionValuesJson.length > 0
                        ? item.optionValuesJson.join("; ")
                        : "None"}
                    </TableCell>
                    <TableCell>
                      <Badge className={item.state ? "bg-green-600" : "bg-gray-400"}>
                        {item.state ? "Active" : "Inactive"}
                      </Badge>
                    </TableCell>
                    <TableCell className="font-numeric">{item.orderNum ?? "None"}</TableCell>
                    <TableCell className="text-gray-500 tabular-nums font-numeric">
                      {item.creationTime ? new Date(item.creationTime).toLocaleString() : "None"}
                    </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 h-9 px-2 font-normal text-red-600 hover:text-red-700 hover:bg-red-50"
                            onClick={() => openDelete(item)}
                          >
                            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>

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

      <EditMultipleOptionDialog
        open={isEditDialogOpen}
        option={editingOption}
        onOpenChange={(open) => {
          setIsEditDialogOpen(open);
          if (!open) setEditingOption(null);
        }}
        onUpdated={refreshList}
      />

      <DeleteMultipleOptionDialog
        open={isDeleteDialogOpen}
        option={deletingOption}
        onOpenChange={(open) => {
          setIsDeleteDialogOpen(open);
          if (!open) setDeletingOption(null);
        }}
        onDeleted={refreshList}
      />
    </div>
  );
}

function CreateMultipleOptionDialog({
  open,
  onOpenChange,
  onCreated,
}: {
  open: boolean;
  onOpenChange: (open: boolean) => void;
  onCreated: () => void;
}) {
  const [submitting, setSubmitting] = useState(false);
  const [form, setForm] = useState<LabelMultipleOptionCreateInput>({
    optionCode: "",
    optionName: "",
    optionValuesJson: [],
    state: true,
    orderNum: null,
  });
  const [newValue, setNewValue] = useState("");

  const resetForm = () => {
    setForm({
      optionCode: "",
      optionName: "",
      optionValuesJson: [],
      state: true,
      orderNum: null,
    });
    setNewValue("");
  };

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

  const addValue = () => {
    const trimmed = newValue.trim();
    if (!trimmed) return;
    if (form.optionValuesJson.includes(trimmed)) {
      toast.error("Duplicate value", {
        description: "This value already exists.",
      });
      return;
    }
    setForm((p) => ({
      ...p,
      optionValuesJson: [...p.optionValuesJson, trimmed],
    }));
    setNewValue("");
  };

  const removeValue = (index: number) => {
    setForm((p) => ({
      ...p,
      optionValuesJson: p.optionValuesJson.filter((_, i) => i !== index),
    }));
  };

  const submit = async () => {
    if (!form.optionCode.trim() || !form.optionName.trim()) {
      toast.error("Validation failed", {
        description: "Option Code and Option Name are required.",
      });
      return;
    }
    if (form.optionValuesJson.length === 0) {
      toast.error("Validation failed", {
        description: "At least one option value is required.",
      });
      return;
    }

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

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

        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Option Code *</Label>
              <Input
                placeholder="e.g. OPT_ALLERGENS"
                value={form.optionCode}
                onChange={(e) => setForm((p) => ({ ...p, optionCode: e.target.value }))}
              />
            </div>
            <div className="space-y-2">
              <Label>Option Name *</Label>
              <Input
                placeholder="e.g. Allergens"
                value={form.optionName}
                onChange={(e) => setForm((p) => ({ ...p, optionName: e.target.value }))}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Option Values *</Label>
            <div className="flex gap-2">
              <Input
                placeholder="Enter a value and press Add"
                value={newValue}
                onChange={(e) => setNewValue(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    addValue();
                  }
                }}
              />
              <Button type="button" onClick={addValue} variant="outline">
                Add
              </Button>
            </div>
            {form.optionValuesJson.length > 0 && (
              <div className="flex flex-wrap gap-2 mt-2">
                {form.optionValuesJson.map((val, idx) => (
                  <Badge key={idx} variant="secondary" className="flex items-center gap-1">
                    {val}
                    <button
                      type="button"
                      onClick={() => removeValue(idx)}
                      className="ml-1 hover:text-red-600"
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </Badge>
                ))}
              </div>
            )}
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Order</Label>
              <Input
                type="number"
                placeholder="e.g. 1"
                value={form.orderNum ?? ""}
                onChange={(e) => setForm((p) => ({ ...p, orderNum: e.target.value ? Number(e.target.value) : null }))}
              />
            </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>
        </div>

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

function EditMultipleOptionDialog({
  open,
  option,
  onOpenChange,
  onUpdated,
}: {
  open: boolean;
  option: LabelMultipleOptionDto | null;
  onOpenChange: (open: boolean) => void;
  onUpdated: () => void;
}) {
  const [submitting, setSubmitting] = useState(false);
  const [form, setForm] = useState<LabelMultipleOptionUpdateInput>({
    optionCode: "",
    optionName: "",
    optionValuesJson: [],
    state: true,
    orderNum: null,
  });
  const [newValue, setNewValue] = useState("");

  useEffect(() => {
    if (open && option) {
      setForm({
        optionCode: option.optionCode ?? "",
        optionName: option.optionName ?? "",
        optionValuesJson: option.optionValuesJson ?? [],
        state: option.state ?? true,
        orderNum: option.orderNum ?? null,
      });
      setNewValue("");
    }
  }, [open, option]);

  const addValue = () => {
    const trimmed = newValue.trim();
    if (!trimmed) return;
    if (form.optionValuesJson.includes(trimmed)) {
      toast.error("Duplicate value", {
        description: "This value already exists.",
      });
      return;
    }
    setForm((p) => ({
      ...p,
      optionValuesJson: [...p.optionValuesJson, trimmed],
    }));
    setNewValue("");
  };

  const removeValue = (index: number) => {
    setForm((p) => ({
      ...p,
      optionValuesJson: p.optionValuesJson.filter((_, i) => i !== index),
    }));
  };

  const submit = async () => {
    if (!option?.id) return;
    if (!form.optionCode.trim() || !form.optionName.trim()) {
      toast.error("Validation failed", {
        description: "Option Code and Option Name are required.",
      });
      return;
    }
    if (form.optionValuesJson.length === 0) {
      toast.error("Validation failed", {
        description: "At least one option value is required.",
      });
      return;
    }

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

  return (
    <Dialog open={open} onOpenChange={onOpenChange}>
      <DialogContent className="sm:max-w-[600px]">
        <DialogHeader>
          <DialogTitle>Edit Multiple Option</DialogTitle>
          <DialogDescription>
            Update the multiple option details.
          </DialogDescription>
        </DialogHeader>

        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Option Code *</Label>
              <Input
                placeholder="e.g. OPT_ALLERGENS"
                value={form.optionCode}
                onChange={(e) => setForm((p) => ({ ...p, optionCode: e.target.value }))}
              />
            </div>
            <div className="space-y-2">
              <Label>Option Name *</Label>
              <Input
                placeholder="e.g. Allergens"
                value={form.optionName}
                onChange={(e) => setForm((p) => ({ ...p, optionName: e.target.value }))}
              />
            </div>
          </div>

          <div className="space-y-2">
            <Label>Option Values *</Label>
            <div className="flex gap-2">
              <Input
                placeholder="Enter a value and press Add"
                value={newValue}
                onChange={(e) => setNewValue(e.target.value)}
                onKeyDown={(e) => {
                  if (e.key === "Enter") {
                    e.preventDefault();
                    addValue();
                  }
                }}
              />
              <Button type="button" onClick={addValue} variant="outline">
                Add
              </Button>
            </div>
            {form.optionValuesJson.length > 0 && (
              <div className="flex flex-wrap gap-2 mt-2">
                {form.optionValuesJson.map((val, idx) => (
                  <Badge key={idx} variant="secondary" className="flex items-center gap-1">
                    {val}
                    <button
                      type="button"
                      onClick={() => removeValue(idx)}
                      className="ml-1 hover:text-red-600"
                    >
                      <X className="h-3 w-3" />
                    </button>
                  </Badge>
                ))}
              </div>
            )}
          </div>

          <div className="grid grid-cols-2 gap-4">
            <div className="space-y-2">
              <Label>Order</Label>
              <Input
                type="number"
                placeholder="e.g. 1"
                value={form.orderNum ?? ""}
                onChange={(e) => setForm((p) => ({ ...p, orderNum: e.target.value ? Number(e.target.value) : null }))}
              />
            </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>
        </div>

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

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

  const name = useMemo(() => {
    const n = (option?.optionName ?? "").trim();
    return n || option?.optionCode || "this option";
  }, [option]);

  const submit = async () => {
    if (!option?.id) return;
    setSubmitting(true);
    try {
      await deleteLabelMultipleOption(option.id);
      toast.success("Multiple option deleted.", {
        description: "The multiple option has been removed successfully.",
      });
      onOpenChange(false);
      onDeleted();
    } catch (e: any) {
      toast.error("Failed to delete multiple option.", {
        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 Multiple Option</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"
            variant="destructive"
            disabled={submitting}
            onClick={submit}
          >
            {submitting ? "Deleting..." : "Delete"}
          </Button>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}
