import React, { useCallback, useEffect, useRef, useState } from 'react';
import { useField } from '@devesharp/unform-core';
import { FormStyle } from '../styles';
import { IPropsButtonsGroup, getValue, IPropsButtonsGroupOption } from './ButtonGroup.interface';
import Style, { ButtonStyle } from './ButtonGroup.style';

export const ButtonsGroup: React.FunctionComponent<IPropsButtonsGroup> = (props: IPropsButtonsGroup) => {
   if (props.name) {
      return <ButtonsGroupWithUnform {...props} />;
   }

   return <ButtonsGroupWithoutUnform {...props} />;
};

const ButtonsGroupWithUnform: React.FunctionComponent<IPropsButtonsGroup> = (props: IPropsButtonsGroup) => {
   const { fieldName, registerField, defaultValue = null, error, clearError } = useField(props.name);
   const inputRef = useRef(getValue(defaultValue));
   const [value, setValue] = useState(getValue(defaultValue));

   useEffect(() => {
      registerField({
         name: fieldName,
         ref: inputRef,
         path: 'current' as any,
         clearValue(ref) {
            ref.current = null;
            setValue(ref.current);
         },
         setValue(ref, v) {
            ref.current = v || null;

            if (props.multiSelection && !(v instanceof Array)) {
               ref.current = [];
            }

            setValue(ref.current);
         },
         getValue(ref) {
            return ref.current;
         },
      });
   }, [fieldName, registerField]);

   const onSelectItem = useCallback(
      function onSelectItem(newValue: any, currentOption) {
         if (error) clearError();
         setValue(newValue);
         inputRef.current = newValue;
         if (props.onSelect) props.onSelect(newValue, currentOption);
      },
      [error],
   );

   return (
      <ButtonsGroupWithoutUnform
         {...props}
         onSelect={onSelectItem}
         defaultVale={defaultValue}
         value={value}
         error={error}
      />
   );
};

const ButtonsGroupWithoutUnform: React.FunctionComponent<IPropsButtonsGroup> = ({
   options,
   name,
   value,
   title,
   variant,
   error,
   multiSelection = false,
   allowEmpty = false,
   onSelect,
   activeBtnStyle,
   activeTextStyle,
   rounded,
   separate,
   fullLine,
   outline,
   oneLine,
   inactiveBtnStyle,
   inactiveTextStyle,
   ...rest
}: IPropsButtonsGroup) => {
   const select = useCallback(
      (option: IPropsButtonsGroupOption): void => {
         let newValue: any;
         if (multiSelection) {
            const currentValue = !Array.isArray(value) ? [] : [...value];

            if (currentValue.indexOf(option.value) === -1) {
               currentValue.push(option.value);
            } else {
               currentValue.splice(currentValue.indexOf(option.value), 1);
            }

            newValue = currentValue;
         } else if (allowEmpty) {
            newValue = value === option.value ? null : option.value;
         } else {
            newValue = option.value;
         }

         if (onSelect) onSelect(newValue, option);
      },
      [value, onSelect],
   );

   return (
      <FormStyle>
         <Style fullLine={fullLine} oneLine={oneLine}>
            {title && <div className="input-title">{title}</div>}

            <div className={`btn-group btn-selects ${!!error && 'has-error'}`}>
               {options &&
                  options.map((option, index) => (
                     <ButtonSingle
                        index={index}
                        btnLength={options.length}
                        select={select}
                        rounded={rounded}
                        option={option}
                        fullLine={fullLine}
                        separate={separate}
                        key={option.value}
                        variant={variant}
                        outline={outline}
                        activeBtnStyle={activeBtnStyle}
                        activeTextStyle={activeTextStyle}
                        inactiveBtnStyle={inactiveBtnStyle}
                        inactiveTextStyle={inactiveTextStyle}
                        active={
                           multiSelection
                              ? Array.isArray(value) && value.indexOf(option.value) !== -1
                              : value === option.value
                        }
                     />
                  ))}
            </div>

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

const ButtonSingle = React.memo(function ButtonSingle({
   option,
   select,
   active,
   variant,
   index,
   btnLength,
   rounded,
   separate,
   fullLine,
   outline,
}: any): JSX.Element {
   return (
      <ButtonStyle
         className={`btn ${active && 'active'}`}
         onClick={() => select(option)}
         variant={variant}
         active={!!active}
         startBtn={index == 0}
         startRounded={index == 0 && rounded}
         endRounded={btnLength - 1 == index && rounded}
         endBtn={btnLength - 1 == index}
         outline={outline}
         rounded={separate && rounded}
         separate={separate}
         data-testid={`button-${option.name}`}
         data-active={!!active}
      >
         {option.name}
      </ButtonStyle>
   );
});
