import React, { useEffect, useImperativeHandle, useLayoutEffect, useRef, useState } from 'react';
import * as _ from 'lodash';
import {
   AutocompletePure,
   IAutocompleteItem,
   IComponentAutoCompleteAs,
   IPropsAutoComplete,
   IRefAutoCompleteAs,
} from '../AutocompletePure';
import { CloseBtn } from '../CloseBtn';
import { Input } from '../Input';
import { UnformInput } from '../UnformInput';
import { ISelectCompleteProps } from './SelectAutocomplete.interface';
import * as S from './SelectAutocomplete.style';

const InputAutoComplete = React.forwardRef<IRefAutoCompleteAs, IComponentAutoCompleteAs<ISelectCompleteProps>>(
   function InputAutoComplete(
      {
         _handleInputChange,
         _openAutoComplete,
         _closeAutoComplete,
         _loading,
         onChange,
         value: valueExternal,
         placeholder,
         name,
         ...rest
      },
      ref,
   ): JSX.Element {
      const inputRef = useRef<HTMLInputElement>();

      const [typing, setTyping] = useState(false);
      const [textSelected, setTextSelected] = useState('');
      const [_value, setValue] = useState<any>(null);
      const value = valueExternal || _value;
      const [error, setError] = useState();

      useLayoutEffect(() => {
         if (!_.isEqual(valueExternal, value)) {
            setValue(valueExternal);
            setTextSelected(valueExternal?.name);
         }
      }, [valueExternal]);

      useImperativeHandle(ref, () => ({
         onSelect(item) {
            inputRef.current.value = '';
            if (rest.onInput) rest.onInput('');

            setTyping(false);

            setTextSelected(item.name);

            setValue(
               item
                  ? {
                       name: item?.name,
                       value: item?.value,
                    }
                  : null,
            );

            if (onChange) onChange(item);
         },
      }));

      function onInput(v: string): void {
         setTyping(inputRef.current.value != '');
         _handleInputChange(v);
         if (rest.onInput) rest.onInput(v);
      }

      function clearInput(): void {
         setTextSelected('');
         setValue(null);
         if (onChange) onChange(null);
      }

      function onFocus(e: any): void {
         _openAutoComplete();
         if (rest.onFocus) rest.onFocus(e);
      }

      function onBlur(e: any): void {
         _closeAutoComplete();
         inputRef.current.value = '';
         setTyping(false);
         if (rest.onBlur) rest.onBlur(e);
      }

      function onChangeUnform(item: IAutocompleteItem): void {
         setValue(
            item
               ? {
                    name: item?.name,
                    value: item?.value,
                 }
               : null,
         );
         setTextSelected(item?.name);
         if (onChange) onChange(item);
      }

      function onError(e: any): void {
         setError(e);
      }

      return (
         <>
            {!!name && <UnformInput name={name} value={value} onChange={onChangeUnform} onError={onError} />}
            <Input
               {...rest}
               ref={inputRef}
               error={error}
               onInput={onInput}
               onFocus={onFocus}
               onBlur={onBlur}
               loading={_loading}
               placeholder={!textSelected && !typing ? placeholder : ''}
               data-testid="autocomplete--input"
               className="focus"
               prefix={
                  <>
                     {!typing && (
                        <div className="text-selected" data-testid="text-selected-label">
                           {textSelected}
                        </div>
                     )}
                  </>
               }
               suffix={
                  <>
                     {textSelected && (
                        <CloseBtn
                           size={13}
                           color="#444"
                           onClick={clearInput}
                           data-testid="select-autocomplete--clear"
                        />
                     )}
                  </>
               }
            />
         </>
      );
   },
);

export function SelectAutocomplete(props: IPropsAutoComplete<ISelectCompleteProps>): JSX.Element {
   return (
      <S.Container className="select-autocomplete">
         <AutocompletePure {...props} as={InputAutoComplete} />
      </S.Container>
   );
}
