import React, { useCallback, useMemo, useState } from 'react';
import { bem } from 'utils/bem';
import { EmptySearch, SearchableMenuWrapper } from '../../components';
import {
  BaseOption as BaseOptionType,
  SearchableCustomSelectProps,
  SearchableSelectProps,
  SelectMenuProps,
  SelectType,
} from '../../types';
import { BaseSelect } from '../base-select';
import { getFilteredOptions } from '../../transducers';
import { BEM_CLASS, SSearchableSelect } from './s-searchable-select';

const classes = bem(BEM_CLASS);

const Root = <T extends BaseOptionType>({
  classNames,
  selectComponents,
  searchPlaceholder,
  popupSearch,
  popupSearchHandler,
  isSearchableFromMenu,
  ...props
}: SearchableSelectProps<T> & SelectMenuProps) => {
  const [searchValue, setSearchValue] = useState('');

  const options = useMemo(() => getFilteredOptions(props.options || [], searchValue), [props.options, searchValue]);

  const selectClassNames = useCallback(
    (className: string) => ({
      ...classNames,

      menu: classes('menu', undefined, classNames?.menu),
      menuPortal: `${className} ${classNames?.menuPortal}`,
    }),
    [classNames]
  );

  const components = useCallback(
    () => ({
      ...selectComponents?.({
        isMenuOpen: props.isMenuOpen,
        openMenu: props.openMenu,
        closeMenu: props.closeMenu,
      }),

      NoOptionsMessage: EmptySearch,
      Menu: SearchableMenuWrapper,
    }),
    [props.closeMenu, props.isMenuOpen, props.openMenu, selectComponents]
  );

  const eraseSearchValue = useCallback(() => {
    setSearchValue('');
  }, [setSearchValue]);

  const customSelectProps = useMemo<SearchableCustomSelectProps>(
    () => ({
      searchPlaceholder: searchPlaceholder,
      isSearchableFromMenu: isSearchableFromMenu,
      popupSearchValue: popupSearch,
      popupSearchHandler: popupSearchHandler,
    }),
    [isSearchableFromMenu, popupSearch, popupSearchHandler, searchPlaceholder]
  );

  return (
    <SSearchableSelect>
      {className => (
        <BaseSelect
          {...props}
          type={SelectType.Base}
          options={searchValue ? options : props.options}
          classNames={selectClassNames(className)}
          selectComponents={components}
          onMenuOpen={eraseSearchValue}
          popupSearch={searchValue}
          popupSearchHandler={setSearchValue}
          customReactSelectProps={customSelectProps}
        />
      )}
    </SSearchableSelect>
  );
};

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