import React, { useCallback, useMemo, useRef, useState } from 'react';
import { BEM_CLASS, SAutocompleteInput } from './s-autocomplete-input';
import { AutocompleteLoader } from './components';
import { components as selectComponents, GroupBase, SelectInstance } from 'react-select';
import { BgStyle } from 'common/styles/utils';
import { Tooltip } from '../tooltip';
import { ControlProps } from 'react-select/dist/declarations/src/components/Control';
import { Icon } from '../icon';
import { bem } from 'utils/bem';
import { BaseOption } from '../form/select';

interface Props<T extends BaseOption> {
  value?: T[];
  options: T[];
  onChange(values: T[]): void;
  onMenuOpen?(): void;
  onMenuClose?(): void;
  onRequestData?(inputValue: string): void;
  onClickItem?(item: T): void;
  onKeyDown?(event: React.KeyboardEvent, value: string): void;
  maxItemsCount?: number;
  maxTooltipText?: string;
  isLoading?: boolean;
  placeholder?: string;
  withInputIcon?: boolean;
  bgStyle?: BgStyle;
  className?: string;
  hasError?: boolean;
  disabled?: boolean;
  minInputLength?: number;
  autoFocus?: boolean;
}

const classes = bem(BEM_CLASS);

export const AutocompleteInput = React.memo(
  <T extends BaseOption>({
    isLoading,
    value = [],
    onChange,
    options,
    className,
    placeholder,
    onRequestData,
    onClickItem,
    onKeyDown,
    maxItemsCount,
    maxTooltipText,
    withInputIcon = false,
    bgStyle = 'grey',
    hasError = false,
    disabled = false,
    minInputLength = 2,
    autoFocus = false,
    onMenuClose,
  }: Props<T>) => {
    const selectRef = useRef<SelectInstance<unknown, boolean, GroupBase<unknown>>>(null);
    const [inputValue, setInputValue] = useState<string>('');
    const isReachedMax = maxItemsCount === 0 || (!!maxItemsCount && value && value.length >= maxItemsCount);

    const onInputChange = useCallback(
      (input: string) => {
        setInputValue(input);
        onRequestData?.(input);
      },
      [onRequestData]
    );
    const onKeyDownHandler = useCallback(
      (event: React.KeyboardEvent) => {
        onKeyDown && onKeyDown(event, inputValue);
      },
      [inputValue, onKeyDown]
    );

    const components = useMemo(
      () => ({
        DropdownIndicator: () => null,
        LoadingMessage: () => <AutocompleteLoader />,
        LoadingIndicator: () => null,
        ClearIndicator: () => null,
        MultiValueLabel: props => (
          <div onClick={() => onClickItem && onClickItem(props.data)}>
            <selectComponents.MultiValueLabel {...props} />
          </div>
        ),
        Control: ({ children, ...props }: ControlProps<unknown>) => (
          <selectComponents.Control {...props}>
            <>
              {withInputIcon && <Icon name="search" size="general" className={classes('icon')} />}
              {children}
            </>
          </selectComponents.Control>
        ),
      }),
      [onClickItem, withInputIcon]
    );

    const styles = {
      multiValueRemove: (base, state) => {
        return state.data.isFixed ? { ...base, display: 'none' } : base;
      },
    };

    const onChangeSelect = useCallback(
      (value, { action, removedValue }) => {
        switch (action) {
          case 'remove-value':
          case 'pop-value':
            if (removedValue?.isFixed) {
              return;
            }
            break;
        }
        onChange(value);
      },
      [onChange]
    );

    const menuIsOpen = hasError ? false : inputValue.length >= minInputLength;

    const getOptionLabel = useCallback(({ name }) => name, []);
    const getOptionValue = useCallback(({ id }) => id, []);

    return (
      <Tooltip enabled={isReachedMax && !!maxTooltipText} content={maxTooltipText}>
        <div>
          <SAutocompleteInput
            ref={selectRef}
            isLoading={isLoading}
            menuIsOpen={menuIsOpen}
            value={value}
            isMulti={false}
            isInputDisabled={isReachedMax}
            isSearchable={!isReachedMax}
            placeholder={placeholder}
            components={components}
            styles={styles}
            onMenuOpen={onMenuClose}
            onMenuClose={onMenuClose}
            getOptionLabel={getOptionLabel}
            getOptionValue={getOptionValue}
            classNamePrefix="react-select"
            className={`react-select ${className}`}
            bgStyle={bgStyle}
            autoFocus={autoFocus}
            onChange={onChangeSelect}
            onInputChange={onInputChange}
            inputValue={inputValue}
            isDisabled={disabled}
            options={options}
            hasError={hasError}
            filterOption={null}
            noOptionsMessage={() => 'No results'}
            onKeyDown={onKeyDownHandler}
          />
        </div>
      </Tooltip>
    );
  }
);
