import generateQueryString from '@/lib/generateQueryString';
import trackAnalyticsEvent from '@/lib/trackAnalyticsEvent';
import { useMutation } from '@tanstack/react-query';
import { Formik } from 'formik';
import { useRouter } from 'next/router';
import { useState } from 'react';
import { DISALLOWED_SPECIAL_CHARS, EMAIL_REGEX, checkPassword, getRecaptchaToken } from './helper';
import {
  FieldWrapper,
  FormField,
  FormFieldError,
  FormLabel,
  FormWrapper,
  InteractButton,
  Notice,
  ShowHidePasswordButton,
} from './styles';

const SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL;

interface Values {
  name: string;
  email: string;
  password: string;
}

export const EmailRegisterForm = ({
  onCancel,
  directToStudio = true,
}: {
  directToStudio?: boolean;
  onCancel: () => void;
}) => {
  const router = useRouter();
  const [showPassword, setShowPassword] = useState(false);
  const [message, setMessage] = useState<string | null>(null);

  const { mutate, isLoading, isError, isSuccess } = useMutation(async (values: Values) => {
    trackAnalyticsEvent({
      name: 'Landing Button Clicked',
      properties: {
        text: 'Sign up with Email',
        location: 'Email Register Form',
      },
    });
    const { name, email, password } = values;
    const token = await getRecaptchaToken('register');

    const response = await fetch(`${SERVER_URL}/auth/email/register${generateQueryString(router.query)}`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, password, name, token }),
      credentials: 'include',
    });
    if (response.status === 204) {
      setMessage('Email already registered');
      throw new Error('Registered');
    } else if (response.status === 202) {
      setMessage('Registered! Please check your email for the verification link.');
    } else {
      setMessage('Something went wrong');
      throw new Error('Something went wrong');
    }
    if ((window as any).rdt) (window as any).rdt('track', 'SignUp');
  }, {});

  const validate = (values: Values) => {
    const errors: Partial<Values> = {};
    if (!values.name) {
      errors.name = 'Required';
    } else if (DISALLOWED_SPECIAL_CHARS.test(values.name)) {
      errors.name = 'Invalid name';
    }
    if (!values.email) {
      errors.email = 'Required';
    } else if (!EMAIL_REGEX.test(values.email)) {
      errors.email = 'Invalid email address';
    }
    const error = checkPassword(values.password);
    if (error) {
      errors.password = error;
    }
    return errors;
  };

  return (
    <Formik
      initialValues={{
        name: '',
        email: '',
        password: '',
      }}
      validateOnBlur={false}
      validate={validate}
      onSubmit={(values) => mutate(values)}
    >
      {({ errors, values }) => (
        <FormWrapper>
          <div
            style={{
              display: 'grid',
              gridTemplateColumns: '1fr 2fr',
              width: '100%',
              justifyContent: 'space-between',
              alignItems: 'center',
              gap: '10px',
            }}
          >
            <FieldWrapper>
              <div className="labelWrapper">
                <FormLabel htmlFor="name">Name</FormLabel>
                <FormFieldError name="name" component="div" />
              </div>
              <FormField disabled={isSuccess || isLoading} id="name" name="name" placeholder="name" type="text" />
            </FieldWrapper>
            <FieldWrapper>
              <div className="labelWrapper">
                <FormLabel htmlFor="email">Email</FormLabel>
                <FormFieldError name="email" component="div" />
              </div>
              <FormField disabled={isSuccess || isLoading} id="email" name="email" placeholder="email" type="text" />
            </FieldWrapper>
          </div>
          <FieldWrapper>
            <div className="labelWrapper">
              <FormLabel htmlFor="password">Password</FormLabel>
              <FormFieldError name="password" component="div" />
            </div>
            <div style={{ position: 'relative' }}>
              <FormField
                disabled={isSuccess || isLoading}
                id="password"
                name="password"
                placeholder="password"
                type={showPassword ? 'text' : 'password'}
              />
              <ShowHidePasswordButton
                tabIndex={-1}
                type="button"
                onClick={() => {
                  setShowPassword(!showPassword);
                }}
              >
                {showPassword ? 'HIDE' : 'SHOW'}
              </ShowHidePasswordButton>
            </div>
          </FieldWrapper>
          <div
            style={{
              display: 'flex',
              justifyContent: 'space-between',
              alignItems: 'center',
              marginTop: '1em',
              gap: '10px',
            }}
          >
            <InteractButton
              type="submit"
              disabled={Boolean(isSuccess || isLoading)}
              style={{
                marginTop: 0,
                marginBottom: '0.5rem',
                backgroundColor: !values.email || errors.email || errors.name || errors.password ? 'white' : '',
                borderColor: !values.email || errors.email || errors.name || errors.password ? 'black' : '',
              }}
            >
              {isLoading ? <>Loading...</> : isSuccess ? <>Registered!</> : <>Sign Up</>}
            </InteractButton>
            <InteractButton
              type="button"
              disabled={isSuccess || isLoading}
              style={{ marginTop: 0, marginBottom: '0.5rem' }}
              cancel={true}
              onClick={onCancel}
            >
              Cancel
            </InteractButton>
          </div>

          {message && <Notice className="flash">{message}</Notice>}
        </FormWrapper>
      )}
    </Formik>
  );
};
