import clsx from "clsx";
import { useEffect, useState } from "react";
import { GroupBase, StylesConfig } from "react-select";
import ReactSelect from "react-select";
import Option from "@/interfaces/option";

interface Props {
  defaultValue?: Option | Option[];
  options: Option[];
  value?: Option | Option[] | null;
  isLoading?: boolean;
  loadOptions: (inputValue: string) => void;
  onMenuScrollToBottom: (event: WheelEvent | TouchEvent) => void;
  disabled?: boolean;
  placeholder?: string;
  isClearable?: boolean;
  styles?: StylesConfig<Option, boolean, GroupBase<Option>>;
  className?: string;
  label?: string;
  flat?: boolean;
}

interface MultiProps {
  isMulti: true;
  onChange: (value: Option[] | null) => void;
}

interface SingleProps {
  isMulti?: false;
  onChange: (value: Option | null) => void;
}

export default function AsyncSelect({
  value,
  isMulti,
  defaultValue,
  options,
  loadOptions,
  onMenuScrollToBottom,
  placeholder,
  disabled,
  onChange,
  styles,
  isClearable,
  isLoading,
  label,
  className,
  flat,
}: Props & (MultiProps | SingleProps)) {
  const [target, setTarget] = useState<HTMLElement>();
  const [inputValue, setInputValue] = useState("");
  
  //Implemented a debounce to prevent the API from being called too frequently
  useEffect(() => {
    const timer = setTimeout(() => {
      loadOptions(inputValue);
    }, 200);
    return () => clearTimeout(timer);
  }, [inputValue, loadOptions]);

  useEffect(() => {
    if (document) setTarget(document.body);
  }, []);

  return (
    <div className="w-full flex flex-col gap-3">
      {label && (
        <label className="font-normal text-base text-mti-gray-dim">
          {label}
        </label>
      )}
      <ReactSelect
        isMulti={isMulti}
        className={
          styles
            ? undefined
            : clsx(
                "placeholder:text-mti-gray-cool border-mti-gray-platinum w-full border bg-white text-sm font-normal focus:outline-none",
                disabled &&
                  "!bg-mti-gray-platinum/40 !text-mti-gray-dim cursor-not-allowed",
                flat ? "rounded-md" : "px-4 py-4 rounded-full",
                className
              )
        }
        isLoading={isLoading}
        filterOption={null}
        loadingMessage={() => "Loading..."}
        onInputChange={(inputValue) => {
          setInputValue(inputValue);
        }}
        options={options}
        value={value}
        onChange={onChange as any}
        placeholder={placeholder}
        menuPortalTarget={target}
        defaultValue={defaultValue}
        onMenuScrollToBottom={onMenuScrollToBottom}
        styles={
          styles || {
            menuPortal: (base) => ({ ...base, zIndex: 9999 }),
            control: (styles) => ({
              ...styles,
              paddingLeft: "4px",
              border: "none",
              outline: "none",
              ":focus": {
                outline: "none",
              },
            }),
            option: (styles, state) => ({
              ...styles,
              backgroundColor: state.isFocused
                ? "#D5D9F0"
                : state.isSelected
                ? "#7872BF"
                : "white",
              color: state.isFocused ? "black" : styles.color,
            }),
          }
        }
        isDisabled={disabled}
        isClearable={isClearable}
      />
    </div>
  );
}
