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

import { otpVerify, verifyCredentials, switchAccount } from 'soapbox/actions/auth.ts';
import { BigCard } from 'soapbox/components/big-card.tsx';
import Button from 'soapbox/components/ui/button.tsx';
import FormActions from 'soapbox/components/ui/form-actions.tsx';
import FormGroup from 'soapbox/components/ui/form-group.tsx';
import Form from 'soapbox/components/ui/form.tsx';
import Input from 'soapbox/components/ui/input.tsx';
import { useAppDispatch } from 'soapbox/hooks/useAppDispatch.ts';

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 (
    <BigCard title={<FormattedMessage id='login.otp_log_in' defaultMessage='OTP Login' />}>
      <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>
    </BigCard>
  );
};

export default OtpAuthForm;
