import React, { useState } from 'react';
import { FormattedMessage, defineMessages, useIntl } from 'react-intl';
import { Redirect } from 'react-router-dom';

import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth';
import { Button, Form, FormActions, FormGroup, Input } from 'soapbox/components/ui';
import { useAppDispatch } from 'soapbox/hooks';

const messages = defineMessages({
  otpCodeHint: { id: 'login.fields.otp_code_hint', defaultMessage: 'Enter the two-factor code generated by your phone app or use one of your recovery codes' },
  otpCodeLabel: { id: 'login.fields.otp_code_label', defaultMessage: 'Two-factor code:' },
  otpLoginFail: { id: 'login.otp_log_in.fail', defaultMessage: 'Invalid code, please try again.' },
});

interface IOtpAuthForm {
  mfa_token: string,
}

const OtpAuthForm: React.FC<IOtpAuthForm> = ({ mfa_token }) => {
  const dispatch = useAppDispatch();
  const intl = useIntl();

  const [isLoading, setIsLoading] = useState(false);
  const [shouldRedirect, setShouldRedirect] = useState(false);
  const [codeError, setCodeError] = useState<string | boolean>('');

  const getFormData = (form: any) => Object.fromEntries(
    Array.from(form).map((i: any) => [i.name, i.value]),
  );

  const handleSubmit = (event: React.FormEvent<Element>) => {
    const { code } = getFormData(event.target);
    dispatch(otpVerify(code, mfa_token)).then(({ access_token }) => {
      setCodeError(false);
      return dispatch(verifyCredentials(access_token as string));
    }).then((account: Record<string, any>) => {
      setShouldRedirect(true);
      return dispatch(switchAccount(account.id));
    }).catch(() => {
      setIsLoading(false);
      setCodeError(true);
    });
    setIsLoading(true);
    event.preventDefault();
  };

  if (shouldRedirect) return <Redirect to='/' />;

  return (
    <div>
      <div className='pb-4 sm:pb-10 mb-4 border-b border-gray-200 dark:border-gray-600 border-solid -mx-4 sm:-mx-10'>
        <h1 className='text-center font-bold text-2xl'>
          <FormattedMessage id='login.otp_log_in' defaultMessage='OTP Login' />
        </h1>
      </div>

      <div className='sm:pt-10 sm:w-2/3 md:w-1/2 mx-auto'>
        <Form onSubmit={handleSubmit}>
          <FormGroup
            labelText={intl.formatMessage(messages.otpCodeLabel)}
            hintText={intl.formatMessage(messages.otpCodeHint)}
            errors={codeError ? [intl.formatMessage(messages.otpLoginFail)] : []}
          >
            <Input
              name='code'
              type='text'
              autoComplete='off'
              autoFocus
              required
            />
          </FormGroup>

          <FormActions>
            <Button
              theme='primary'
              type='submit'
              disabled={isLoading}
            >
              <FormattedMessage id='login.sign_in' defaultMessage='Sign in' />
            </Button>
          </FormActions>
        </Form>
      </div>
    </div>
  );
};

export default OtpAuthForm;
