import React, { useCallback, useEffect, useMemo, useState } from 'react';
import {
  AutocompleteMultiSelectProps,
  BaseOption as BaseOptionType,
  MultiSelectType,
  SelectMenuProps,
} from '../../types';
import { BaseMultiSelect } from '../base-multi-select';
import { BEM_CLASS, SAutocompleteMultiSelect } from './s-autocomplete-multi-select';
import { bem } from 'utils/bem';

const classes = bem(BEM_CLASS);

const Root = <T extends BaseOptionType, P extends {}>({
  openMenu,
  closeMenu,
  isMenuOpen,
  showMenuOnFocus,
  valueHandler,
  onEditFinished,
  selectComponents,
  selectContainer,
  maxItemsLength,
  classNames,
  value,
  ...selectProps
}: AutocompleteMultiSelectProps<T, P> & SelectMenuProps) => {
  const [inputValue, setInputValue] = useState('');

  const isMaxItems = useMemo(() => Array.isArray(value) && maxItemsLength && maxItemsLength <= value.length, [
    maxItemsLength,
    value,
  ]);

  const handleChange = useCallback(
    (value: (string | number)[]) => {
      if (showMenuOnFocus && maxItemsLength && value.length < maxItemsLength) {
        openMenu();
      } else {
        closeMenu();
      }

      valueHandler(value);
    },
    [showMenuOnFocus, maxItemsLength, openMenu, closeMenu, valueHandler]
  );

  const handleKeyDown = useCallback(
    (event: React.KeyboardEvent<HTMLDivElement>) => {
      if (event.key === 'Enter' && !isMenuOpen) {
        onEditFinished?.();
      }
      selectProps.onKeyDown?.(event);
    },
    [isMenuOpen, onEditFinished, selectProps]
  );

  const handleOnFocus = useCallback(() => {
    if (!showMenuOnFocus) return;

    if (!isMenuOpen && !isMaxItems) {
      openMenu();
    }
  }, [isMenuOpen, openMenu, showMenuOnFocus, isMaxItems]);

  const components = useCallback(
    () => ({
      ...selectComponents?.({
        isMenuOpen,
        openMenu: openMenu,
        closeMenu: closeMenu,
      }),
      DropdownIndicator: () => null,
      IndicatorsContainer: () => null,
    }),
    [closeMenu, isMenuOpen, openMenu, selectComponents]
  );

  const selectClassNames = useMemo(
    () => ({
      ...classNames,
      control: classes('control', undefined, classNames?.control),
    }),
    [classNames]
  );

  useEffect(() => {
    const minSearchLength = selectProps.minSearchLength || 0;

    if (inputValue && inputValue.length >= minSearchLength) {
      openMenu();
    } else {
      closeMenu();
    }
  }, [closeMenu, inputValue, openMenu, selectProps.minSearchLength]);

  const handleSearchInput = useCallback(
    (input: string) => {
      if (isMaxItems) return;

      setInputValue(input);
    },
    [isMaxItems]
  );

  return (
    <SAutocompleteMultiSelect>
      {selectContainer?.({ ...selectProps, classNames: selectClassNames }) || (
        <BaseMultiSelect
          {...selectProps}
          type={MultiSelectType.Base}
          isSearchable={true}
          closeMenuOnSelect
          inputValue={inputValue}
          onInputChange={handleSearchInput}
          isSearchableFromMenu={false}
          value={value}
          valueHandler={handleChange}
          onKeyDown={handleKeyDown}
          onFocus={handleOnFocus}
          selectComponents={components}
          openMenu={openMenu}
          closeMenu={closeMenu}
          isMenuOpen={isMenuOpen}
          classNames={selectClassNames}
        />
      )}
    </SAutocompleteMultiSelect>
  );
};

export const AutocompleteMultiSelect = React.memo(Root) as typeof Root;
