import React from 'react';
import PropTypes from 'prop-types';
import { withFormsy, propTypes as formsyPropTypes } from 'formsy-react';
import { FormControlSelect } from '../../core/atoms/formControlSelect/FormControlSelect';
import { FormGroup } from '../../core/molecules/formGroup/FormGroup';

const propTypes = {
  ...formsyPropTypes,
  children: PropTypes.node,
  disabled: PropTypes.bool,
  /**
   * Object of props passed to the <FormGroup> component
   */
  groupProps: PropTypes.object,
  helper: PropTypes.node,
  isMulti: PropTypes.bool,
  label: PropTypes.node,
  onChange: PropTypes.func,
  options: PropTypes.array,
  placeholder: PropTypes.string,
  /**
   * Object of props passed to the <FormControlSelect> component
   */
  selectProps: PropTypes.object,
};

const defaultProps = {
  children: null,
  disabled: false,
  groupProps: {},
  helper: null,
  isMulti: false,
  label: null,
  onChange: () => {},
  options: [],
  placeholder: null,
  selectProps: {},
};

export const FieldSelectUI = ({
  // Formsy props
  getErrorMessage,
  getValue,
  isFormSubmitted,
  isPristine,
  isRequired,
  isValid,
  setValue,

  // Global props
  children,
  disabled,
  groupProps,
  helper,
  label,
  onChange,
  placeholder,

  // Custom props
  isMulti,
  isGroupOption,
  isCreatable,
  options,
  selectProps,
}) => {
  const [isTouched, setIsTouched] = React.useState(false);
  const [isFocused, setIsFocused] = React.useState(false);

  const isFeedbackVisible = (isTouched && !isPristine()) || isFormSubmitted();
  const isError = !isValid() && isFeedbackVisible;

  const value = getValue();
  const getDefaultValue = () => {
    if (isGroupOption) {
      const optionsConcat = options
        .reduce((acc, cur) => (cur.options ? [...acc, ...cur.options] : [...acc]), []);

      return (
        Array.isArray(value)
          ? value.map((val) => optionsConcat.find((x) => (x.value === val)))
          : optionsConcat.find((x) => (x.value === value))
      );
    }

    return (
      Array.isArray(value)
        ? value.map((val) => options.find((x) => x.value === val)) // Multi
        : options.find((x) => (x.value === value)) // Single
    );
  };

  const handleChange = (opt) => {
    // Multi
    if (Array.isArray(opt)) {
      const fieldValue = !opt.length ? null : opt.map((x) => x.value);
      setValue(fieldValue);
      onChange(fieldValue);
      return;
    }

    // Single
    const fieldValue = opt ? opt.value : null;
    setValue(fieldValue);
    onChange(fieldValue);
  };

  const handleFocus = () => {
    setIsFocused(true);
    setIsTouched(true);
  };

  const handleBlur = () => {
    setIsFocused(false);
  };

  return (
    <FormGroup
      label={label}
      helper={helper}
      isOptional={!isRequired()}
      validationState={!isFocused && isError ? 'danger' : null}
      feedbackMessage={isFeedbackVisible && getErrorMessage()}
      {...groupProps}
    >
      <FormControlSelect
        isDisabled={disabled}
        placeholder={placeholder}
        defaultValue={getDefaultValue()}
        options={options}
        onChange={handleChange}
        onFocus={handleFocus}
        onBlur={handleBlur}
        menuPortalTarget={document.body}
        isMulti={isMulti}
        isDanger={!isFocused && isError}
        isClearable
        isCreatable={isCreatable}
        isGroupOption={isGroupOption}
        isValidNewOption={isCreatable ? (inputValue) => !!inputValue : undefined}
        {...selectProps}
      />
      {children}
    </FormGroup>
  );
};

FieldSelectUI.propTypes = propTypes;
FieldSelectUI.defaultProps = defaultProps;

export const FieldSelect = withFormsy(FieldSelectUI);
