import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useField } from '@unform/core';
import { Autocomplete } from './Autocomplete';
import Style from './SelectAutocomplete.style';

interface ISelectAutocompleteProps<T = any> extends React.ComponentProps<any> {
   renderInput?: (params: any) => any;
   name: any;
   prefix?: any;
   fetch?: any;
   placeholder?: string;
   clearable?: boolean;
   getValue?: (i: T) => any;
   title?: any;
}
type SelectDataType<T = any> = string | { label: string; value: T } | null;

function getData<T>(data: SelectDataType<T>): SelectDataType<T> {
   if (!data) {
      return null;
   }

   if (typeof data === 'string') {
      return data;
   }

   return data;
}

function getDataLabel<T>(data: SelectDataType<T>): string {
   if (!data) {
      return '';
   }
   if (typeof data === 'string') {
      return data;
   }

   return data.label;
}

export function SelectAutocomplete<T = any>({
   name,
   fetch,
   title,
   prefix,
   getValue,
   placeholder,
   clearable = true,
   renderInput,
}: ISelectAutocompleteProps<T>): JSX.Element {
   const autocompleteRef = useRef<any>();
   const { registerField, defaultValue = '', error, fieldName } = useField(name);
   const valueRef = useRef<SelectDataType<T>>(getData<T>(defaultValue));
   const [value, setValue] = useState(getDataLabel<T>(defaultValue));

   useEffect(() => {
      registerField({
         name: fieldName,
         ref: valueRef,
         path: 'current' as any,
         setValue(ref: any, _value: string) {
            ref = getData<T>(_value);
         },
         getValue(ref: any): any {
            return valueRef.current;
         },
      });
   }, [fieldName, registerField]);

   function onSelect(i): void {
      valueRef.current = getValue ? getValue(i) : i;
      setValue(getDataLabel(valueRef.current));
   }

   return (
      <Style data-cy={`autocomplete-${name}`}>
         <div className="select-box-autocomplete">
            <Autocomplete
               ref={autocompleteRef}
               name={name}
               title={title}
               fetch={fetch}
               valueSelected={value}
               error={!!error}
               prefix={prefix}
               placeholder={placeholder}
               clearable={clearable}
               cleanAfterSelect
               renderInput={renderInput}
               select={onSelect}
            />
         </div>

         {!!error && (
            <div className="error-input" data-testid="input-error">
               {error}
            </div>
         )}
      </Style>
   );
}
