import { Fragment, useState } from "react";

// headless ui
import { Menu, Transition } from "@headlessui/react";
// ui
import { Loader } from "components/ui";
// icons
import { Check, ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";

type MultiLevelDropdownProps = {
  label: string;
  options: {
    id: string;
    children?: {
      id: string;
      label: string | JSX.Element;
      value: any;
      selected?: boolean;
      element?: JSX.Element;
    }[];
    hasChildren: boolean;
    label: string;
    onClick?: () => void;
    selected?: boolean;
    value: any;
  }[];
  onSelect: (value: any) => void;
  direction?: "left" | "right";
  height?: "sm" | "md" | "rg" | "lg";
};

export const MultiLevelDropdown: React.FC<MultiLevelDropdownProps> = ({
  label,
  options,
  onSelect,
  direction = "right",
  height = "md",
}) => {
  const [openChildFor, setOpenChildFor] = useState<string | null>(null);

  return (
    <>
      <Menu as="div" className="relative z-10 inline-block text-left">
        {({ open }) => (
          <>
            <div>
              <Menu.Button
                onClick={() => setOpenChildFor(null)}
                className={`group flex items-center justify-between gap-2 rounded-md border border-custom-border-200 px-3 py-1.5 text-xs shadow-sm duration-300 focus:outline-none hover:text-custom-text-100 hover:bg-custom-background-90 ${
                  open ? "bg-custom-background-90 text-custom-text-100" : "text-custom-text-200"
                }`}
              >
                {label}
                <ChevronDown className="h-3 w-3" aria-hidden="true" />
              </Menu.Button>
            </div>
            <Transition
              as={Fragment}
              enter="transition ease-out duration-100"
              enterFrom="transform opacity-0 scale-95"
              enterTo="transform opacity-100 scale-100"
              leave="transition ease-in duration-75"
              leaveFrom="transform opacity-100 scale-100"
              leaveTo="transform opacity-0 scale-95"
            >
              <Menu.Items
                static
                className="absolute right-0 z-10 mt-1 w-36 origin-top-right select-none rounded-md bg-custom-background-90 border border-custom-border-300 text-xs shadow-lg focus:outline-none"
              >
                {options.map((option) => (
                  <div className="relative p-1" key={option.id}>
                    <Menu.Item
                      as="button"
                      onClick={(e: any) => {
                        if (option.hasChildren) {
                          e.stopPropagation();
                          e.preventDefault();

                          if (option.onClick) option.onClick();

                          if (openChildFor === option.id) setOpenChildFor(null);
                          else setOpenChildFor(option.id);
                        } else onSelect(option.value);
                      }}
                      className="w-full"
                    >
                      {({ active }) => (
                        <>
                          <div
                            className={`${
                              active || option.selected ? "bg-custom-background-80" : ""
                            } flex items-center gap-1 rounded px-1 py-1.5 text-custom-text-200 ${
                              direction === "right" ? "justify-between" : ""
                            }`}
                          >
                            {direction === "left" && option.hasChildren && <ChevronLeft className="h-3.5 w-3.5" />}
                            <span>{option.label}</span>
                            {direction === "right" && option.hasChildren && <ChevronRight className="h-3.5 w-3.5" />}
                          </div>
                        </>
                      )}
                    </Menu.Item>
                    {option.hasChildren && option.id === openChildFor && (
                      <div
                        className={`absolute top-0 min-w-36 whitespace-nowrap origin-top-right select-none overflow-y-scroll rounded-md bg-custom-background-90 border border-custom-border-300 shadow-lg focus:outline-none ${
                          direction === "left" ? "right-full -translate-x-1" : "left-full translate-x-1"
                        } ${
                          height === "sm"
                            ? "max-h-28"
                            : height === "md"
                            ? "max-h-44"
                            : height === "rg"
                            ? "max-h-56"
                            : height === "lg"
                            ? "max-h-80"
                            : ""
                        }`}
                      >
                        {option.children ? (
                          <div className="space-y-1 p-1">
                            {option.children.length === 0 ? (
                              <p className="text-custom-text-200 text-center px-1 py-1.5">No {option.label} found</p> //if no children found, show this message.
                            ) : (
                              option.children.map((child) => {
                                if (child.element) return child.element;
                                else
                                  return (
                                    <button
                                      key={child.id}
                                      type="button"
                                      onClick={() => onSelect(child.value)}
                                      className={`${
                                        child.selected ? "bg-custom-background-80" : ""
                                      } flex w-full items-center justify-between break-words rounded px-1 py-1.5 text-left text-custom-text-200 hover:bg-custom-background-80`}
                                    >
                                      {child.label}{" "}
                                      <Check
                                        className={`h-3.5 w-3.5 opacity-0 ${child.selected ? "opacity-100" : ""}`}
                                      />
                                    </button>
                                  );
                              })
                            )}
                          </div>
                        ) : (
                          <Loader className="p-1 space-y-2">
                            <Loader.Item height="20px" />
                            <Loader.Item height="20px" />
                            <Loader.Item height="20px" />
                            <Loader.Item height="20px" />
                          </Loader>
                        )}
                      </div>
                    )}
                  </div>
                ))}
              </Menu.Items>
            </Transition>
          </>
        )}
      </Menu>
    </>
  );
};