import React, {
   useRef,
   useEffect,
   InputHTMLAttributes,
   useState,
   useImperativeHandle,
   useCallback,
   useMemo,
} from 'react';
import { useField } from '@unform/core';
import * as _ from 'lodash';
import { ISelectProps } from './Select.interface';

const ReactNative = navigator && navigator.product == 'ReactNative';

export const SelectCore = React.forwardRef<InputHTMLAttributes<any>, ISelectProps>(function SelectCore(
   props,
   inputRef: any,
) {
   if (props.name) {
      return <SelectCoreWithUnform {...props} ref={inputRef} />;
   }

   return <SelectCoreWithoutUnform {...props} ref={inputRef} value={props.value ?? null} />;
});

export const SelectCoreWithUnform = React.forwardRef<InputHTMLAttributes<any>, ISelectProps>(
   function SelectCoreWithUnform(props, inputRef: any) {
      const ref = useRef<any>();
      useImperativeHandle(inputRef, () => ref.current, []);

      const { fieldName, registerField, defaultValue = null, error, clearError } = useField(props.name);
      const inputValueRef = useRef(
         ReactNative
            ? // apenas resgatar valor, se existir nas options
              props.options.find((i) => _.isEqual(i.value, defaultValue))?.value ?? null
            : JSON.stringify(defaultValue),
      );
      const [value, setValue] = useState<any>(ReactNative ? defaultValue : undefined);

      useEffect(() => {
         registerField({
            name: fieldName,
            ref: inputValueRef,
            path: 'current' as any,
            clearValue(_ref) {
               _ref.current = null;

               if (ReactNative) {
                  setValue(null);
               }
            },
            setValue(_ref, v) {
               _ref.current = JSON.stringify(v);

               if (ReactNative) {
                  _ref.current = v;
                  setValue(v);
               } else {
                  ref.current.value = JSON.stringify(v);
               }
            },
            getValue(ref) {
               if (ReactNative) {
                  return ref.current;
               }

               return JSON.parse(ref.current);
            },
         });
      }, [fieldName, registerField, props.options]);

      const onChange = useCallback(
         function onSelectItem(newValue: any) {
            if (error) clearError();
            clearError();
            inputValueRef.current = newValue;
            if (ReactNative) {
               setValue(newValue);
            }
            if (props.onChange) props.onChange(newValue);
         },
         [error],
      );

      return (
         <SelectCoreWithoutUnform
            {...props}
            ref={ref}
            onChange={onChange}
            value={value}
            error={error}
            defaultValue={defaultValue}
         />
      );
   },
);

export const SelectCoreWithoutUnform = React.forwardRef<InputHTMLAttributes<any>, ISelectProps>(
   function SelectCoreWithoutUnform(props, inputRef: any) {
      const ref = useRef(null);
      useImperativeHandle(inputRef, () => ref.current, []);

      const PureComponent = useMemo(() => props.as, [props.as]) as any;

      return <PureComponent {...props} ref={ref} />;
   },
);
