import { RefObject, useEffect, useMemo, useRef, useState } from 'react';

import {
  MdClose,
  MdEdit,
  MdKeyboardArrowDown,
  MdKeyboardArrowUp,
} from 'react-icons/md';

import { SelectList, SelectListModel } from '@/components/select/SelectList';
import { isNullOrUndefined } from '@/utils/validator';
import { Button, Flex, Input } from '@/ui';

export type SelectSingleProps = {
  options?: object[];
  value?: number | string;
  onChange?: (value: number | string | undefined) => void;
  keyKey?: string;
  keyValue?: string;
  ref?: RefObject<any>;
  // if set add capability to add the search item
  onCreate?: (data: string) => void;
  // if a suggestion exist at the auto compleat
  suggestion?: string;
};

export const SelectSingle = ({
  options,
  onChange,
  value,
  ref,
  keyKey = 'id',
  keyValue = keyKey,
  suggestion,
  onCreate,
}: SelectSingleProps) => {
  const [showList, setShowList] = useState(false);
  const transformedOption = useMemo(() => {
    return options?.map((element) => {
      return {
        id: element[keyKey],
        name: element[keyValue],
      } as SelectListModel;
    });
  }, [options, keyKey, keyValue]);
  const [hasSuggestion, setHasSuggestion] = useState<boolean>(
    onCreate && suggestion ? true : false
  );
  const [currentSearch, setCurrentSearch] = useState<string | undefined>(
    onCreate ? suggestion : undefined
  );
  useEffect(() => {
    console.log(`Update suggestion : ${onCreate} ${suggestion} ==> ${onCreate ? suggestion : undefined} .. ${onCreate && !isNullOrUndefined(suggestion) ? true : false}`);
    setCurrentSearch(onCreate ? suggestion : undefined);
    setHasSuggestion(onCreate && !isNullOrUndefined(suggestion) ? true : false);
  }, [suggestion]);
  const refFocus = ref ?? useRef<HTMLInputElement | null>(null);
  const selectedOptions = useMemo(() => {
    if (isNullOrUndefined(value)) {
      return undefined;
    }
    return transformedOption?.find((data) => data.id === value);
  }, [value, transformedOption]);

  const selectValue = (data?: SelectListModel) => {
    const tmpData = data?.id == selectedOptions?.id ? undefined : data;
    setShowList(false);
    if (onChange) {
      onChange(tmpData?.id);
    }
  };
  if (!transformedOption) {
    return <></>; // TODO: <Spinner />;
  }
  function onChangeInput(value: string): void {
    setHasSuggestion(false);
    if (value === '') {
      setCurrentSearch(undefined);
    } else {
      setCurrentSearch(value);
    }
  }
  const onRemoveItem = () => {
    setHasSuggestion(false);
    if (selectedOptions) {
      if (onChange) {
        onChange(undefined);
      }
    }
    if (!showList || selectedOptions) {
      refFocus?.current?.focus();
    }
  };

  const createNewItem = !onCreate
    ? undefined
    : (data: string) => {
      onCreate(data);
      setCurrentSearch(undefined);
      setHasSuggestion(false);
    };

  return (
    <Flex direction="column" width="full" gap="0px">
      <Flex>
        <Input
          ref={refFocus}
          style={{
            width: "full",
            backgroundColor: showList || !selectedOptions ? undefined : 'green.500',
            borderRadius: "5px 0 0 5px",
          }}
          onChange={(e) => onChangeInput(e.target.value)}
          //onFocus={() => setShowList(true)}
          //onBlur={() => setTimeout(() => setShowList(false), 200)}
          value={
            showList ? (currentSearch ?? '') : (selectedOptions?.name ?? (hasSuggestion ? `suggest: ${currentSearch}` : ''))
          }
        />
        <Button
          onClick={onRemoveItem}
          // TODO: variant="outline"
          style={{
            borderRadius: "0 5px 5px 0",
            borderWidth: "1px 1px 1px 0",
          }}
        >
          {
            selectedOptions ? (
              <MdClose color="gray.300" />
            ) : showList ? (
              <MdKeyboardArrowUp color="gray.300" />
            ) : hasSuggestion ? (
              <MdEdit color="gray.300" />
            ) : (
              <MdKeyboardArrowDown color="gray.300" />
            )}
        </Button>
      </Flex>
      {
        showList && (
          <SelectList
            options={transformedOption}
            selected={selectedOptions ? [selectedOptions] : []}
            search={currentSearch}
            onSelectValue={selectValue}
            onCreate={createNewItem}
          />
        )
      }
    </Flex >
  );
};
