import React, { useState } from "react";

import { Listbox, Transition } from "@headlessui/react";

import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/20/solid";

type TSelectOption = {
  id: string;
  label: string;
  value: any;
  children?:
    | (TSelectOption & {
        children?: null;
      })[]
    | null;
};

type TMultipleSelectProps = {
  options: TSelectOption[];
  selected: TSelectOption | null;
  setSelected: (value: any) => void;
  label: string;
  direction?: "left" | "right";
};

export const MultiLevelSelect: React.FC<TMultipleSelectProps> = (props) => {
  const { options, selected, setSelected, label, direction = "right" } = props;

  const [openChildFor, setOpenChildFor] = useState<TSelectOption | null>(null);

  return (
    <div className="fixed top-16 w-72">
      <Listbox
        value={selected}
        onChange={(value) => {
          if (value?.children === null) {
            setSelected(value);
            setOpenChildFor(null);
          } else setOpenChildFor(value);
        }}
      >
        {({ open }) => (
          <div className="relative mt-1">
            <Listbox.Button
              onClick={() => setOpenChildFor(null)}
              className="relative w-full cursor-default rounded-lg bg-white py-2 pl-3 pr-10 text-left shadow-md sm:text-sm"
            >
              <span className="block truncate">{selected?.label ?? label}</span>
              <span className="pointer-events-none absolute inset-y-0 right-0 flex items-center pr-2">
                <ChevronUpDownIcon className="h-5 w-5 text-gray-400" aria-hidden="true" />
              </span>
            </Listbox.Button>
            <Transition
              as={React.Fragment}
              show={open}
              leave="transition ease-in duration-100"
              leaveFrom="opacity-100"
              leaveTo="opacity-0"
            >
              <Listbox.Options
                static
                className="absolute mt-1 max-h-60 w-full rounded-md bg-white py-1 text-base shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none sm:text-sm"
              >
                {options.map((option) => (
                  <Listbox.Option
                    key={option.id}
                    className={
                      "relative cursor-default select-none py-2 pl-10 pr-4 hover:bg-gray-100 hover:text-gray-900"
                    }
                    onClick={(e: any) => {
                      if (option.children !== null) {
                        e.preventDefault();
                        setOpenChildFor(option);
                      }
                      if (option.id === openChildFor?.id) {
                        e.preventDefault();
                        setOpenChildFor(null);
                      }
                    }}
                    value={option}
                  >
                    {({ selected }) => (
                      <>
                        {openChildFor?.id === option.id && (
                          <div
                            className={`absolute h-auto max-h-72 w-72 rounded-lg border bg-white ${
                              direction === "right"
                                ? "left-full translate-x-2 rounded-tl-none shadow-md"
                                : "right-full -translate-x-2 rounded-tr-none shadow-md"
                            }`}
                          >
                            {option.children?.map((child) => (
                              <Listbox.Option
                                key={child.id}
                                className={
                                  "relative cursor-default select-none py-2 pl-10 pr-4 hover:bg-gray-100 hover:text-gray-900"
                                }
                                as="div"
                                value={child}
                              >
                                {({ selected }) => (
                                  <>
                                    <span
                                      className={`block truncate ${
                                        selected ? "font-medium" : "font-normal"
                                      }`}
                                    >
                                      {child.label}
                                    </span>
                                    {selected ? (
                                      <span className="absolute inset-y-0 left-0 flex items-center pl-3 text-gray-600">
                                        <CheckIcon className="h-5 w-5" aria-hidden="true" />
                                      </span>
                                    ) : null}
                                  </>
                                )}
                              </Listbox.Option>
                            ))}

                            <div
                              className={`absolute h-0 w-0 border-t-8 border-gray-300 ${
                                direction === "right"
                                  ? "top-0 left-0 -translate-x-2 border-r-8 border-b-8 border-b-transparent border-t-transparent border-l-transparent"
                                  : "top-0 right-0 translate-x-2 border-l-8 border-b-8 border-b-transparent border-t-transparent border-r-transparent"
                              }`}
                            />
                          </div>
                        )}
                        <span
                          className={`block truncate ${selected ? "font-medium" : "font-normal"}`}
                        >
                          {option.label}
                        </span>
                        {selected ? (
                          <span className="absolute inset-y-0 left-0 flex items-center pl-3 text-gray-600">
                            <CheckIcon className="h-5 w-5" aria-hidden="true" />
                          </span>
                        ) : null}
                      </>
                    )}
                  </Listbox.Option>
                ))}
              </Listbox.Options>
            </Transition>
          </div>
        )}
      </Listbox>
    </div>
  );
};