import React from 'react';
import _ from 'lodash';
import {ThemeProvider} from 'styled-components';
import {IconCheck} from '@simpozio/aha-button/dist';
import {ValidationError} from 'yup';
import defaultSchema from './validSchema';
import {
  FormText,
  BottomText,
  Error,
  Container,
  FormGroup,
  StyledButton,
  StyledField,
  StyledForm,
  DEFAULT_THEME,
  buttonStyles
} from './styles';
import {
  TShortForm,
  TFormErrors,
  TFormValues,
  TFieldPreset,
  TFormFields,
  TCallbackProps
} from '../../types';

const FormShort = ({
  className,
  fields,
  formText,
  bottomText,
  onValidate,
  onValid,
  onChange,
  onSubmit,
  onError,
  validSchema = defaultSchema,
  theme = DEFAULT_THEME,
  styles
}: TShortForm): JSX.Element => {
  const initialValues = {};
  const fieldsPreset = fields;

  _.forIn(fields, ({initialValue}: TFieldPreset, name: string) => {
    _.assign(initialValues, {
      [name]: initialValue
    });
  });

  const handleValidate = (props: TCallbackProps): Promise<TFormErrors> =>
    new Promise(resolve => {
      const values: TFormValues = {};

      _.forIn(props.fields, ({value}, name) => {
        values[name] = value;
      });
      if (_.isFunction(onValidate)) {
        onValidate(props)
          .then(resolve)
          .catch(_.noop);
      }

      const formErrors: TFormErrors = {};

      try {
        validSchema.validateSync(values, {abortEarly: false});
      } catch (errors) {
        _.forEach(errors.inner, (error: ValidationError) => {
          formErrors[error.path] = error.message;
        });
      }

      resolve(formErrors);
    });

  const handleChange = ({
    fields,
    isValid,
    isSubmitted
  }: TCallbackProps): Promise<TFormFields> =>
    new Promise(resolve => {
      _.forIn(fields, ({value}, key) => {
        fields[key].value = _.trim(value);
      });

      if (_.isFunction(onChange)) {
        onChange({fields, isValid, isSubmitted})
          .then((returnedFields: TFormFields) => {
            if (returnedFields && !_.isEmpty(returnedFields)) {
              _.forIn(returnedFields, ({value}, key) => {
                fields[key].value = _.trim(value);
              });
            }

            resolve(fields);
          })
          .catch(_.noop);
      } else {
        resolve(fields);
      }
    });

  return (
    <ThemeProvider theme={theme}>
      <Container styles={styles}>
        <StyledForm
          className={className}
          initialValues={initialValues}
          onChange={handleChange}
          onValid={onValid}
          onValidate={handleValidate}
          onSubmit={onSubmit}
          onError={onError}>
          {({
            fields,
            formError,
            onChange,
            isValid,
            isSubmitting,
            updateForm,
            submitForm
          }): JSX.Element => {
            return (
              <>
                {_.has(fieldsPreset, 'name') && (
                  <FormGroup>
                    <StyledField
                      name="name"
                      placeholder={_.get(fieldsPreset, ['name', 'placeholder'])}
                      label={_.get(fieldsPreset, ['name', 'label'])}
                      field={fields['name']}
                      onChange={onChange}
                      onBlur={updateForm}
                    />
                  </FormGroup>
                )}
                {_.has(fields, 'phone') && (
                  <FormGroup>
                    <StyledField
                      type="tel"
                      placeholder={_.get(fieldsPreset, [
                        'phone',
                        'placeholder'
                      ])}
                      label={_.get(fieldsPreset, ['phone', 'label'])}
                      name="phone"
                      field={fields['phone']}
                      onChange={onChange}
                      onBlur={updateForm}
                    />
                  </FormGroup>
                )}
                {_.has(fields, 'email') && (
                  <FormGroup>
                    <StyledField
                      type="email"
                      name="email"
                      placeholder={_.get(fieldsPreset, [
                        'email',
                        'placeholder'
                      ])}
                      label={_.get(fieldsPreset, ['email', 'label'])}
                      field={fields['email']}
                      onChange={onChange}
                      onBlur={updateForm}
                    />
                  </FormGroup>
                )}
                {formText && (
                  <FormGroup>
                    <FormText>{formText}</FormText>
                  </FormGroup>
                )}
                <FormGroup>
                  <StyledButton
                    outlined
                    icon={<IconCheck />}
                    onClick={submitForm}
                    disabled={!isValid}
                    pending={isSubmitting}
                    styles={buttonStyles}
                  />
                </FormGroup>
                {formError && (
                  <FormGroup>
                    <Error>{formError}</Error>
                  </FormGroup>
                )}
                {bottomText && <BottomText>{bottomText}</BottomText>}
              </>
            );
          }}
        </StyledForm>
      </Container>
    </ThemeProvider>
  );
};

export default FormShort;
