import { UseComboboxReturnValue } from 'downshift';
import React, { useRef, ChangeEvent } from 'react';

import { InputContainer, SelectedItemText } from './Styled';
import { BaseOption } from '../types';
import { SelectProps } from '.';
import { getThemeState } from '../../Input/utils';
import Affix from '../../Input/Affix';
import StyledInput, { InputWrapper } from '../../Input/StyledInput';
import SuffixIcon from '../SuffixIcon';
import { useHover } from '../../../utils/hooks';

type QueryInputComponentProps<T extends BaseOption> = {
  selectedItem: T | undefined;
} & Pick<UseComboboxReturnValue<T>, 'getInputProps' | 'isOpen'> &
  Pick<
    SelectProps<T>,
    | 'selectedOptionRenderer'
    | 'id'
    | 'autoComplete'
    | 'clearable'
    | 'query'
    | 'onQueryChange'
    | 'value'
    | 'onChange'
    | 'disabled'
    | 'prefix'
    | 'loading'
    | 'invalid'
    | 'placeholder'
    | 'size'
    | 'onFocus'
    | 'onBlur'
  >;

const getOptionText = <T extends BaseOption>({ option }: { option: T }) =>
  option.text;

const QueryInput = <T extends BaseOption>({
  selectedItem,
  getInputProps,
  isOpen,
  selectedOptionRenderer = getOptionText,
  id,
  autoComplete,
  clearable,
  value,
  onChange,
  query,
  onQueryChange,
  disabled,
  prefix,
  loading,
  invalid,
  placeholder,
  size = 'medium',
  onFocus,
  onBlur,
}: QueryInputComponentProps<T>) => {
  const inputWrapperRef = useRef<HTMLDivElement>(null);
  const isHoveringInput = useHover(inputWrapperRef);

  const readonly = onQueryChange === undefined;
  const removeShown =
    clearable === true && value !== undefined && isHoveringInput;
  const selectedItemText =
    selectedItem !== undefined
      ? selectedOptionRenderer({ option: selectedItem })
      : '';
  const isEditing = query !== undefined && query.length > 0;

  const inputProps = getInputProps({
    onChange: (e: ChangeEvent<HTMLInputElement>): void => {
      onQueryChange?.(e.target.value);
    },
    onBlur,
    onFocus,
    ref: undefined,
  });

  return (
    <InputWrapper
      themeSize={size}
      themeState={getThemeState({ disabled, invalid })}
      ref={inputWrapperRef}
      data-test-id="query-input"
    >
      <Affix affix={prefix} themeSize={size} />
      <InputContainer themePaddingLeft={prefix === undefined ? size : 'none'}>
        <StyledInput
          {...inputProps}
          value={query ?? ''}
          disabled={disabled}
          readOnly={readonly}
          autoComplete={autoComplete}
          id={id}
          placeholder={selectedItemText === '' ? placeholder : ''}
          themePaddingLeft="none"
          themePaddingRight="none"
        />
        <SelectedItemText data-test-id="selected-item-text">
          {isEditing ? '' : selectedItemText}
        </SelectedItemText>
      </InputContainer>
      <Affix
        affix={
          <SuffixIcon
            loading={loading}
            open={isOpen}
            onChange={onChange}
            removeShown={removeShown}
          />
        }
        themeSize={size}
        themeMarginLeft="auto"
      />
    </InputWrapper>
  );
};

export default QueryInput;
