import { X, GripVertical, Trash2 } from "lucide-react";
import React, { useState, useEffect, useRef } from "react";

import {
  DndContext,
  closestCenter,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  useSortable,
  verticalListSortingStrategy,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";

const SortableItem = ({ id, label, onRemove, disabled }) => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging,
  } = useSortable({ id });

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    zIndex: isDragging ? 9999 : "auto",
    position: isDragging ? "relative" : "static",
  };

  return (
    <span
      ref={setNodeRef}
      {...attributes}
      {...listeners}
      style={style}
      className="bg-gray-100 shadow-sm text-xs py-1 px-2 rounded-md text-gray-700 flex items-center gap-1 cursor-move border border-gray-300 hover:shadow-md transition-shadow"
    >
      <span className="text-gray-400">
        <GripVertical className="w-4 h-4" />
      </span>
      {label}
    </span>
  );
};

const MultiSelect = ({
  label,
  name,
  options = [],
  value = [],
  onChange,
  placeholder = "",
  searchPlaceholder = "Search...",
  className = "",
  closeOnSelect = false,
  labelPlacement = "default",
  showClearAll = false,
  required = false,
  isMulti = false,
  isSearchable = false,
  disabled = false,
  selectable = false,
  component = null,
  labelComponent = null,
  draggable = false,
  grouped = false,
  groupByKey = "",
  helperText = "",
  errors = {},
}) => {
  const [isOpen, setIsOpen] = useState(false);
  const [searchTerm, setSearchTerm] = useState("");
  const [highlightIndex, setHighlightIndex] = useState(-1);
  const [selectAll, setSelectAll] = useState(false);
  const wrapperRef = useRef(null);
  const sensors = useSensors(useSensor(PointerSensor));

  const processedOptions = React.useMemo(() => {
    if (!grouped) return options;

    const isAlreadyGrouped = options.every(
      (opt) => opt.options && Array.isArray(opt.options)
    );
    if (isAlreadyGrouped) return options;

    const groupedMap = {};
    for (const item of options) {
      const groupLabel = groupByKey ? item[groupByKey] : "Others";
      if (!groupLabel) continue;
      if (!groupedMap[groupLabel]) groupedMap[groupLabel] = [];
      groupedMap[groupLabel].push(item);
    }

    return Object.entries(groupedMap).map(([label, groupOptions]) => ({
      label,
      options: groupOptions,
    }));
  }, [options, grouped, groupByKey]);

  const flatOptions = grouped
    ? processedOptions.flatMap((group) => group.options)
    : processedOptions;

  // Ensure value is always an array for consistent handling
  const valueArray = Array.isArray(value)
    ? value
    : value !== undefined && value !== null
      ? [value]
      : [];

  const toggleDropdown = () => !disabled && setIsOpen((prev) => !prev);
  const closeDropdown = () => setIsOpen(false);

  const handleClickOutside = (e) => {
    if (wrapperRef.current && !wrapperRef.current.contains(e.target)) {
      closeDropdown();
    }
  };

  useEffect(() => {
    document.addEventListener("mousedown", handleClickOutside);
    return () => document.removeEventListener("mousedown", handleClickOutside);
  }, []);

  // useEffect(() => {
  //   if (isOpen && isSearchable) {
  //     setTimeout(() => {
  //       wrapperRef.current?.querySelector("input[type='text']")?.focus();
  //     }, 0);
  //   }
  // }, [isOpen, isSearchable]);
  const selectedOptions = flatOptions.filter(
    (opt) =>
      opt && (isMulti ? valueArray.includes(opt.value) : opt.value === value)
  );

  const filteredOptions = grouped
    ? processedOptions
        .map((group) => {
          const groupLabelMatches = group.label
            .toLowerCase()
            .includes(searchTerm.toLowerCase());

          const matchedOptions = group.options.filter((opt) =>
            opt.label.toLowerCase().includes(searchTerm.toLowerCase())
          );

          // If group label matches but no child match, show all children
          if (groupLabelMatches && matchedOptions.length === 0) {
            return group;
          }

          // Otherwise only show matched children
          if (matchedOptions.length > 0) {
            return {
              ...group,
              options: matchedOptions,
            };
          }

          return null;
        })
        .filter(Boolean)
    : processedOptions.filter((opt) =>
        opt.label.toLowerCase().includes(searchTerm.toLowerCase())
      );

  const handleSelect = (selectedValue) => {
    let newValue;

    if (isMulti) {
      if (valueArray.includes(selectedValue)) {
        newValue = valueArray.filter((v) => v !== selectedValue); // Toggle off
      } else {
        newValue = [...valueArray, selectedValue];
      }
    } else {
      newValue = selectedValue;
    }

    onChange?.(newValue);
    if (closeOnSelect || !isMulti) closeDropdown();
  };

  const handleRemove = (val) => {
    const updated = valueArray.filter((v) => v !== val);
    onChange?.(updated);
  };

  const clearAll = () => {
    onChange?.(isMulti ? [] : null);
    setSearchTerm("");
    setSelectAll(false);
  };

  const handleSelectAllToggle = () => {
    const filteredIds = grouped
      ? filteredOptions.flatMap((g) => g.options.map((o) => o.value))
      : filteredOptions.map((f) => f.value);

    if (selectAll) {
      onChange?.(valueArray.filter((v) => !filteredIds.includes(v)));
    } else {
      const uniqueSet = new Set([...valueArray, ...filteredIds]);
      onChange?.([...uniqueSet]);
    }
    setSelectAll(!selectAll);
  };

  useEffect(() => {
    const allFilteredIds = grouped
      ? filteredOptions.flatMap((g) => g.options.map((o) => o.value))
      : filteredOptions.map((f) => f.value);

    const allSelected =
      allFilteredIds.length > 0 &&
      allFilteredIds.every((id) => valueArray.includes(id));

    setSelectAll(allSelected);
  }, [searchTerm, value, options]);

  const handleKeyDown = (e) => {
    if (!isOpen) {
      if (
        e.key === "Enter" ||
        e.key === " " ||
        e.key === "ArrowDown" ||
        e.key === "ArrowUp"
      ) {
        e.preventDefault();
        setIsOpen(true);
        setHighlightIndex(0);
        return;
      }
    }

    // ✅ Close dropdown when pressing Tab
    if (e.key === "Tab") {
      setIsOpen(false);
      return;
    }

    if (filteredOptions.length === 0) return;

    if (e.key === "ArrowDown") {
      e.preventDefault();
      setHighlightIndex((prev) =>
        prev + 1 >= filteredOptions.length ? 0 : prev + 1
      );
    } else if (e.key === "ArrowUp") {
      e.preventDefault();
      setHighlightIndex((prev) =>
        prev - 1 < 0 ? filteredOptions.length - 1 : prev - 1
      );
    } else if (e.key === "Enter" || e.key === " ") {
      e.preventDefault();
      if (highlightIndex !== -1) {
        const selected = filteredOptions[highlightIndex];
        if (selected) handleSelect(selected.value);
      }
    } else if (e.key === "Escape") {
      e.preventDefault();
      setIsOpen(false);
    }
  };

  return (
    <div className={`relative w-full ${className || ""}`} ref={wrapperRef}>
      {/* Label */}
      {label && labelPlacement === "floating" ? (
        <label
          htmlFor={name}
          className={`absolute z-10 text-sm px-1 bg-white left-2 -top-2.5 ${
            required
              ? "after:content-['*'] after:ml-0.5 after:text-red-500"
              : ""
          }`}
        >
          {label}
        </label>
      ) : label ? (
        <label
          htmlFor={name}
          className="flex items-center gap-2 text-sm font-medium mb-0.5"
        >
          <div className="">
            {label}
            {required && <span className="text-red-500 ml-1">*</span>}
          </div>
          {labelComponent && labelComponent}
        </label>
      ) : null}

      {/* Selected View */}
      <div
        className={`border rounded-sm p-2 pl-2 cursor-pointer flex flex-wrap items-center gap-2 ${
          disabled
            ? "bg-gray-100 text-gray-400 cursor-not-allowed"
            : "border-gray-300"
        }`}
        onClick={toggleDropdown}
        onKeyDown={handleKeyDown}
        tabIndex={0}
      >
        {selectedOptions.length > 0 ? (
          draggable && isMulti ? (
            <DndContext
              sensors={sensors}
              collisionDetection={closestCenter}
              onDragEnd={({ active, over }) => {
                if (active.id !== over?.id) {
                  const oldIndex = valueArray.indexOf(active.id);
                  const newIndex = valueArray.indexOf(over.id);
                  const reordered = arrayMove(valueArray, oldIndex, newIndex);
                  onChange?.(reordered);
                }
              }}
            >
              <SortableContext
                items={valueArray}
                strategy={verticalListSortingStrategy}
              >
                {valueArray.map((val) => {
                  const opt = selectedOptions.find((o) => o.value === val);
                  if (!opt) return null;

                  return (
                    <SortableItem
                      key={val}
                      id={val}
                      label={opt.label}
                      onRemove={() => handleRemove(val)}
                      disabled={disabled}
                    />
                  );
                })}
              </SortableContext>
            </DndContext>
          ) : (
            selectedOptions.map((opt) => (
              <span
                key={opt.value}
                className={`${
                  isMulti
                    ? "bg-gray-100 shadow-sm text-xs py-1 px-2 rounded-md text-gray-700 flex items-center gap-1 border border-gray-300"
                    : ""
                } px-2 text-sm flex items-center gap-1`}
              >
                {opt.label}
                {isMulti && !disabled && (
                  <button
                    type="button"
                    className="ml-1 text-xs text-red-500 hover:text-red-600 rounded-full hover:bg-red-100 transition"
                    onClick={(e) => {
                      e.stopPropagation();
                      handleRemove(opt.value);
                    }}
                  >
                    <X className="w-4 h-4" />
                  </button>
                )}
              </span>
            ))
          )
        ) : (
          <span className="text-gray-400 text-sm">
            {placeholder || `Select ` + label}
          </span>
        )}
        {/* 
        {showClearAll && isMulti && selectedOptions.length > 0 && !disabled && (
          <button
            type="button"
            className="ml-auto text-xs text-red-500 hover:text-red-600"
            onClick={(e) => {
              e.stopPropagation();
              clearAll();
            }}
          >
            <X className="w-4 h-4" />
          </button>
        )} */}

        {showClearAll && selectedOptions.length > 0 && !disabled && (
          <button
            type="button"
            className="ml-auto text-red-500 hover:text-red-600 p-1 rounded-full hover:bg-red-100 transition"
            onClick={(e) => {
              e.stopPropagation();
              clearAll();
            }}
            title="Clear All"
          >
            <Trash2 className="w-4 h-4" />
          </button>
        )}
      </div>

      {/* Dropdown */}
      {isOpen && !disabled && (
        <div className="absolute z-10 bg-white border rounded-md mt-1 shadow-md w-full max-h-60 overflow-auto">
          {isSearchable && (
            <input
              type="text"
              placeholder={searchPlaceholder}
              value={searchTerm}
              onChange={(e) => {
                setSearchTerm(e.target.value);
                setHighlightIndex(0);
              }}
              className="w-full border-b outline-none text-sm p-2 pl-4 sticky top-0 bg-white"
            />
          )}

          {/* Select All */}
          {selectable && isMulti && filteredOptions.length > 0 && (
            <div className="flex items-center gap-2 px-4 py-2 border-b text-sm">
              <label className="cursor-pointer">
                <input
                  type="checkbox"
                  checked={selectAll}
                  onChange={handleSelectAllToggle}
                  className="accent-brand-dark mr-2"
                />
                Select All
              </label>
            </div>
          )}
          {filteredOptions.length > 0 || (!isMulti && value) ? (
            <>
              {/* Empty option for single-select */}
              {value !== null && (
                <div
                  className="px-4 py-2 text-sm text-gray-500 hover:bg-gray-100 cursor-pointer"
                  onClick={() => {
                    onChange?.(null);
                    closeDropdown();
                  }}
                >
                  Select an option
                </div>
              )}

              {grouped
                ? filteredOptions.map((group, groupIdx) => (
                    <div key={`group-${groupIdx}`}>
                      <div className="px-4 py-1 text-xs font-bold text-gray-500 bg-gray-100 border">
                        {group.label}
                      </div>
                      {group.options.map((opt, idx) => {
                        const isSelected = isMulti
                          ? valueArray.includes(opt.value)
                          : value === opt.value;
                        const isHighlighted =
                          highlightIndex === idx && groupIdx === 0;

                        return (
                          <div
                            key={opt.value}
                            className={`px-4 py-2 flex items-center gap-2 text-sm cursor-pointer transition-colors
              ${
                isSelected && isHighlighted
                  ? "bg-brand-dark/90 border border-white text-brand-gold font-semibold"
                  : isSelected
                    ? "bg-brand-dark/90 text-white"
                    : isHighlighted
                      ? "bg-brand-dark/50 text-white"
                      : "hover:bg-brand-dark/10 hover:text-brand-dark"
              }`}
                            onClick={() => handleSelect(opt.value)}
                          >
                            {selectable && isMulti && (
                              <input
                                type="checkbox"
                                checked={isSelected}
                                readOnly
                                className="accent-brand-gold"
                              />
                            )}
                            {opt.label}
                          </div>
                        );
                      })}
                    </div>
                  ))
                : filteredOptions.map((opt, idx) => {
                    const isSelected = isMulti
                      ? valueArray.includes(opt.value)
                      : value === opt.value;
                    const isHighlighted = highlightIndex === idx;

                    return (
                      <div
                        key={opt.value}
                        className={`px-4 py-2 flex items-center gap-2 text-sm cursor-pointer transition-colors
          ${
            isSelected && isHighlighted
              ? "bg-brand-dark/90 border border-white text-brand-gold font-semibold"
              : isSelected
                ? "bg-brand-dark/90 text-white"
                : isHighlighted
                  ? "bg-brand-dark/50 text-white"
                  : "hover:bg-brand-dark/10 hover:text-brand-dark"
          }`}
                        onClick={() => handleSelect(opt.value)}
                      >
                        {selectable && isMulti && (
                          <input
                            type="checkbox"
                            checked={isSelected}
                            readOnly
                            className="accent-brand-gold"
                          />
                        )}
                        {opt.label}
                      </div>
                    );
                  })}
            </>
          ) : (
            <div className="px-4 py-2 text-sm text-gray-400">No options</div>
          )}
        </div>
      )}

      {/* Error */}
      {errors?.[name] && (
        <p className="text-sm text-red-500 text-end">{errors[name]?.message}</p>
      )}
      {/* Helper Text */}
      {helperText && (
        <p className="text-sm text-muted-foreground text-end mt-1">
          {helperText}
        </p>
      )}

      {component && component}
    </div>
  );
};

export default MultiSelect;
