import React, { useCallback, useMemo } from 'react';
import CreatableSelect, { MultiValue as ReactSelectMultiValue, SelectComponentsConfig } from 'react-select';
import {
  BaseControl,
  BaseGroup,
  BaseOption,
  IndicatorContainer,
  MenuList,
  MenuPortal,
  MultiValueContainer,
  MultiValuePlaceholder,
  MultiValueRemove,
  SearchableMenuWrapper,
  SelectContainer,
  SingleValue,
  ValueContainer,
} from '../components';
import {
  BaseCreatableSelectProps,
  BaseGroup as BaseGroupType,
  BaseOption as BaseOptionType,
  MenuPlacement,
  MultiCustomReactSelectProps,
} from '../types';
import { noop } from 'lodash';
import { SELECT_ID } from 'common/components/select/constants';

const Root = <T extends BaseOptionType, P extends {}>({
  classNames,
  placement = MenuPlacement.Auto,
  valueHandler,
  selectComponents,
  dataSelector,
  customReactSelectProps,
  valueContainerLabel,
  ...selectProps
}: BaseCreatableSelectProps<T, P>) => {
  const handleChange = useCallback(
    (option: ReactSelectMultiValue<T>) => {
      valueHandler(option.map(({ id }) => id));
    },
    [valueHandler]
  );

  const components: SelectComponentsConfig<T, true, BaseGroupType<T>> = useMemo(
    () => ({
      Control: BaseControl,
      ValueContainer: ValueContainer,
      SingleValue: SingleValue,
      IndicatorSeparator: null,
      DropdownIndicator: IndicatorContainer,
      Menu: SearchableMenuWrapper,
      MenuList: MenuList,
      Group: BaseGroup,
      Option: BaseOption,
      MultiValueContainer: MultiValueContainer,
      MultiValueRemove: MultiValueRemove,
      Placeholder: MultiValuePlaceholder,
      ClearIndicator: () => null,
      SelectContainer: SelectContainer,

      ...selectComponents?.({
        isMenuOpen: false,
        openMenu: noop,
        closeMenu: noop,
      }),

      MenuPortal: MenuPortal,
    }),
    [selectComponents]
  );

  const customSelectProps = useMemo<MultiCustomReactSelectProps>(
    () => ({
      handleMenu: noop,
      classNames: classNames,
      closeMenu: noop,
      portalPlacement: placement,
      dataSelector: dataSelector,
      valueContainerLabel: valueContainerLabel,
      ...customReactSelectProps,
    }),
    [classNames, customReactSelectProps, dataSelector, placement, valueContainerLabel]
  );

  return (
    <CreatableSelect
      id={SELECT_ID}
      ref={selectProps.selectRef}
      getOptionLabel={({ value }) => value}
      options={selectProps.options}
      menuPortalTarget={document.body}
      menuShouldBlockScroll={false}
      captureMenuScroll={false}
      blurInputOnSelect={false}
      isMulti
      menuIsOpen={false}
      tabSelectsValue={false}
      backspaceRemovesValue
      {...selectProps}
      onChange={handleChange}
      components={components}
      // @ts-ignore
      customSelectProps={customSelectProps}
    />
  );
};

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