import { Badge } from "Components/ui/badge";
import {
  Command,
  CommandEmpty,
  CommandItem,
  CommandList,
} from "Components/ui/command";
import { cn } from "Utils/libs";
import { Command as CommandPrimitive } from "cmdk";
import { ChevronDown, ChevronUp, X as RemoveIcon } from "lucide-react";
import React, {
  createContext,
  forwardRef,
  useCallback,
  useContext,
  useState,
} from "react";
import ClickOutside from "./ClickOutside";

const MultiSelectContext = createContext();

const useMultiSelect = () => {
  const context = useContext(MultiSelectContext);
  if (!context) {
    throw new Error("useMultiSelect must be used within MultiSelectProvider");
  }
  return context;
};

const MultiSelector = ({
  values: value,
  onValuesChange: onValueChange,
  loop = false,
  className,
  data = { data },
  children,
  dir,
  placeholder,
  ...props
}) => {
  const [inputValue, setInputValue] = useState("");
  const [open, setOpen] = useState(false);
  const [activeIndex, setActiveIndex] = useState(-1);

  const onValueChangeHandler = useCallback(
    (val) => {
      const exists = value.some((item) => item.value === val.value);

      if (exists) {
        onValueChange(value.filter((item) => item.value !== val.value));
      } else {
        onValueChange([
          ...value,
          {
            value: val.value,
            label: val.label,
          },
        ]);
      }
    },
    [value, onValueChange]
  );

  const handleKeyDown = useCallback(
    (e) => {
      const moveNext = () => {
        const nextIndex = activeIndex + 1;
        setActiveIndex(
          nextIndex > value.length - 1 ? (loop ? 0 : -1) : nextIndex
        );
      };

      const movePrev = () => {
        const prevIndex = activeIndex - 1;
        setActiveIndex(prevIndex < 0 ? value.length - 1 : prevIndex);
      };

      if ((e.key === "Backspace" || e.key === "Delete") && value.length > 0) {
        if (inputValue.length === 0) {
          if (activeIndex !== -1 && activeIndex < value.length) {
            onValueChange(value.filter((_, index) => index !== activeIndex));
            const newIndex = activeIndex - 1 < 0 ? 0 : activeIndex - 1;
            setActiveIndex(newIndex);
          } else {
            onValueChange(value.slice(0, -1));
          }
        }
      } else if (e.key === "Enter") {
        setOpen(true);
      } else if (e.key === "Escape") {
        if (activeIndex !== -1) {
          setActiveIndex(-1);
        } else {
          setOpen(false);
        }
      } else if (dir === "rtl") {
        if (e.key === "ArrowRight") {
          movePrev();
        } else if (e.key === "ArrowLeft" && (activeIndex !== -1 || loop)) {
          moveNext();
        }
      } else {
        if (e.key === "ArrowLeft") {
          movePrev();
        } else if (e.key === "ArrowRight" && (activeIndex !== -1 || loop)) {
          moveNext();
        }
      }
    },
    [value, inputValue, activeIndex, loop, setOpen, open]
  );

  return (
    <ClickOutside onClick={() => setOpen(false)} className="relative">
      <MultiSelectContext.Provider
        value={{
          data,
          value,
          onValueChange: onValueChangeHandler,
          open,
          setOpen,
          inputValue,
          setInputValue,
          activeIndex,
          setActiveIndex,
          placeholder,
        }}
      >
        <Command
          onKeyDown={handleKeyDown}
          className={cn(
            "flex overflow-visible flex-col h-full border-form-strokedark bg-form-input",
            className
          )}
          dir={dir}
          {...props}
        >
          {children}
        </Command>
      </MultiSelectContext.Provider>
    </ClickOutside>
  );
};

const MultiSelectorTrigger = forwardRef(
  ({ className, children, ...props }, ref) => {
    const { value, onValueChange, activeIndex, setOpen, open } =
      useMultiSelect();

    const mousePreventDefault = useCallback((e) => {
      e.preventDefault();
      e.stopPropagation();
    }, []);

    return (
      <div className={`relative ${className}`}>
        <div
          ref={ref}
          className={cn(
            `scrollbar-hide  relative  flex h-full w-[calc(100%)] flex-wrap items-center gap-4 rounded border border-form-strokedark bg-form-input focus:border-blue-600 ${
              value.length > 0
                ? "overflow-y-auto pl-[4px] pr-[24px] pt-[6px]"
                : ""
            }`,
            className
          )}
          {...props}
        >
          {value.map((item, index) => (
            <Badge
              key={item.value}
              className={cn(
                "flex h-[20px] max-w-[300px] items-center gap-2 rounded border-transparent bg-white/30 px-[6px] py-[3px] text-white ring-0",
                activeIndex === index && "ring-muted-foreground ring-2 "
              )}
              variant={"outline"}
            >
              <span className="e truncate text-[10px] text-black text-white">
                {item.label}
              </span>
              <button
                aria-label={`Remove ${item.label} option`}
                aria-roledescription="button to remove option"
                type="button"
                onMouseDown={mousePreventDefault}
                onClick={() => onValueChange(item)}
                className="rounded bg-transparent p-[2px] text-white"
              >
                <span className="sr-only">Remove {item.label} option</span>
                <RemoveIcon className="w-4 h-4 text-white hover:stroke-destructive" />
              </button>
            </Badge>
          ))}
          {children}
        </div>
        {open ? (
          <ChevronUp
            onClick={() => {
              setOpen(!open);
            }}
            className="absolute right-[-6px] top-[50%] -translate-x-[50%] -translate-y-[50%] cursor-pointer"
          />
        ) : (
          <ChevronDown
            onClick={() => {
              setOpen(!open);
            }}
            className="absolute right-[-6px] top-[50%] -translate-x-[50%] -translate-y-[50%] cursor-pointer"
          />
        )}
      </div>
    );
  }
);

MultiSelectorTrigger.displayName = "MultiSelectorTrigger";

const MultiSelectorInput = forwardRef(({ className, ...props }, ref) => {
  const {
    setOpen,
    inputValue,
    setInputValue,
    activeIndex,
    setActiveIndex,
    value,
    placeholder,
  } = useMultiSelect();
  return (
    <CommandPrimitive.Input
      {...props}
      ref={ref}
      value={inputValue}
      onValueChange={activeIndex === -1 ? setInputValue : undefined}
      onBlur={() => setOpen(false)}
      onFocus={() => setOpen(true)}
      onClick={() => setActiveIndex(-1)}
      placeholder={`${value.length ? "" : placeholder || "Select"}`}
      className={cn(
        " h-[36px] w-[30%] flex-1 bg-transparent text-white outline-none placeholder:text-bodydark2",
        className,
        activeIndex !== -1 && "caret-transparent",
        value.length > 0 && "h-[20px]ml-2 w-[calc(30%-18px)]"
      )}
    />
  );
});

MultiSelectorInput.displayName = "MultiSelectorInput";

const MultiSelectorContent = forwardRef(({ children }, ref) => {
  const { open } = useMultiSelect();
  return (
    <div ref={ref} className="relative">
      {open && children}
    </div>
  );
});

MultiSelectorContent.displayName = "MultiSelectorContent";

const MultiSelectorList = forwardRef(({ className, children }, ref) => {
  return (
    <CommandList
      ref={ref}
      className={cn(
        "flex absolute top-0 z-10 flex-col gap-2 p-2 w-full rounded-md border shadow-md transition-colors custom-overflow border-form-strokedark bg-meta-4",
        className
      )}
    >
      {children}
      <CommandEmpty>
        <span className="text-muted-foreground">No results found</span>
      </CommandEmpty>
    </CommandList>
  );
});

MultiSelectorList.displayName = "MultiSelectorList";

const MultiSelectorItem = forwardRef(
  ({ className, value: itemValue, children, ...props }, ref) => {
    const {
      value: selectedValues,
      onValueChange,
      setInputValue,
      data,
    } = useMultiSelect();

    const mousePreventDefault = useCallback((e) => {
      e.preventDefault();
      e.stopPropagation();
    }, []);

    console.log(data, itemValue);
    const datas = data.find((item) => item.value === itemValue);
    console.log(datas);
    const isIncluded = selectedValues.some((item) => item.value == datas.value);

    return (
      <CommandItem
        ref={ref}
        {...props}
        onSelect={() => {
          onValueChange({
            value: datas.value,
            label: datas.label,
          });
          setInputValue("");
        }}
        className={cn(
          "flex cursor-pointer    gap-3 border-b border-b-form-strokedark  px-2 py-2 text-white transition-colors hover:bg-primary/5 ",
          className,
          isIncluded && "cursor-default ",
          props.disabled && "cursor-not-allowed "
        )}
        onMouseDown={mousePreventDefault}
      >
        <input
          style={{ accentColor: "black", color: "#3C50E0" }}
          checked={isIncluded}
          className="w-4 h-4 accent-primary hover:cursor-pointer"
          type="checkbox"
          name=""
          id=""
        />
        {children}
      </CommandItem>
    );
  }
);

MultiSelectorItem.displayName = "MultiSelectorItem";

export {
  MultiSelector,
  MultiSelectorContent,
  MultiSelectorInput,
  MultiSelectorItem,
  MultiSelectorList,
  MultiSelectorTrigger,
};
