import React, { useState, useEffect } from 'react';
import ReCAPTCHA from 'react-google-recaptcha';

import Atom from '../../Atom';
import {
  SignUpFormBody,
  Input,
  Subheading,
  CheckboxWrapper,
  CheckboxInput,
  CheckWrapper,
  CheckBoxDescription,
  SubTerms,
  SignUpButtonWrapper,
  LogInQuestion,
  LogInAnswer,
  ValidationButton,
  SignupErrorText,
  SubmittingFormText,
  StyledButton,
  Link,
} from './StylingComponents';

const { Spinner, ErrorMessage } = Atom;

type Props = {
  doSubmit: Function,
  signUpError: boolean,
  submittingForm: boolean,
  isForEvent: boolean,
  +className?: string,
  userExists: boolean,
  checkEmailValidation: Function,
  isAutoApproved: any,
};

const LiteSignupFormUI = ({
  doSubmit,
  signUpError,
  submittingForm,
  isForEvent,
  className,
  userExists,
  checkEmailValidation,
  isAutoApproved,
}: Props) => {
  const [emailIsEnd2End, setEmailIsEnd2End] = useState(false);
  const [nameIsValid, setNameIsValid] = useState(false);
  const [emailIsValid, setEmailIsValid] = useState(false);
  const [jobTitleIsValid, setJobTitleIsValid] = useState(false);
  const [organisationIsValid, setOrganisationIsValid] = useState(false);
  const [loadRecaptcha, setLoadRecaptcha] = useState(false);

  const formRef: { current: any } = React.createRef();
  const nameRef = React.createRef();
  const emailRef = React.createRef();
  const jobTitleRef = React.createRef();
  const organisationRef = React.createRef();
  const tcRef = React.createRef();
  const recaptchaRef = React.createRef();
  const hiddenValidationRef = React.createRef();

  const confirmedManualApproval = !isAutoApproved && isAutoApproved !== null;
  const autoApprovalFields = !nameIsValid || !emailIsValid;
  const manualApprovalFields = autoApprovalFields || !jobTitleIsValid || !organisationIsValid;
  const disableFields = confirmedManualApproval
    ? manualApprovalFields
    : autoApprovalFields;

  useEffect(() => {
    // For accessibility reasons, for manual approvals, focus on job title input
    if (confirmedManualApproval) {
      jobTitleRef.current.focus();
    }
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [isAutoApproved]);

  const blurEmailField = async () => {
    // Regex check added as ref validity check is inconsistent
    const emailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (!emailRef.current.validity.valid || !emailRegex.test(emailRef.current.value)) {
      return setEmailIsValid(false);
    }
    const email = emailRef.current.value.toString().toLowerCase().trim();
    await checkEmailValidation(email);

    const end2EndEmailRegex = /testing\+[0-9]+@apolitical.co$/;
    setEmailIsEnd2End(end2EndEmailRegex.test(email));
    return setEmailIsValid(true);
  };

  const onEmailChange = () => {
    tcRef.current.checked = false;
    return setEmailIsValid(false);
  };

  const onChangeField = (ref, stateSetter, stateObject) => {
    if (stateObject !== ref.current.validity.valid) {
      stateSetter(ref.current.validity.valid);
    }
  };

  const transformFormData = (formData) => {
    const arrayifiedData = [...formData.entries()];
    const transformedData = {};
    arrayifiedData.forEach(([key, value]) => {
      transformedData[key] = value;
    });

    return {
      name: transformedData.full_name,
      email: transformedData.email_address.toString().toLowerCase().trim(),
      jobTitle: transformedData.job_title,
      organization: transformedData.organization,
      bioLink: transformedData.url,
      optIn: transformedData.marketing
        ? transformedData.marketing === 'on'
        : false,
      expectation: transformedData.expectation,
      page: window.location.pathname,
      'g-recaptcha-response': transformedData['g-recaptcha-response'],
    };
  };

  const handleData = () => {
    try {
      if (formRef && formRef.current) {
        if (!formRef.current.checkValidity()) {
          if (hiddenValidationRef && hiddenValidationRef.current) {
            hiddenValidationRef.current.click();
          }
          return;
        }

        if (recaptchaRef && recaptchaRef.current) {
          if (!recaptchaRef.current.getValue()) {
            recaptchaRef.current.execute();
            return;
          }
        }

        const signupData = transformFormData(new FormData(formRef.current));
        doSubmit(signupData);
      }
    } catch (err) {
      // eslint-disable-next-line no-console
      console.log('ERR: ', err);
    }
  };

  const handleSubmitEvent = (event) => {
    event.preventDefault();
    handleData();
  };

  return (
    <SignUpFormBody
      ref={formRef}
      className={className}
      data-testid="sign-up-form"
    >
      <Input
        type="text"
        inputName="full_name"
        placeholder="Full Name"
        required
        labelChildren={<p>Full Name*</p>}
        parentRef={nameRef}
        onChange={() => onChangeField(nameRef, setNameIsValid, nameIsValid)}
        data-testid="sign-up-name-input"
        onFocus={() => setLoadRecaptcha(true)}
      />
      <Input
        type="email"
        inputName="email_address"
        placeholder="name@organisation.com"
        required
        labelChildren={<p>Work Email*</p>}
        parentRef={emailRef}
        onBlur={blurEmailField}
        onChange={onEmailChange}
        data-testid="sign-up-email-input"
        onFocus={() => setLoadRecaptcha(true)}
      />
      {confirmedManualApproval && (
        <>
          <Input
            type="text"
            inputName="job_title"
            placeholder="Sr. Policy Analyst"
            required
            labelChildren={<p>Job Title*</p>}
            parentRef={jobTitleRef}
            onChange={() => onChangeField(jobTitleRef, setJobTitleIsValid, jobTitleIsValid)}
            data-testid="sign-up-title-input"
          />
          <Input
            type="text"
            inputName="organization"
            id="organization"
            placeholder="Energy and Securty, BEIS"
            required
            labelChildren={<p>Department & Organisation*</p>}
            parentRef={organisationRef}
            onChange={() => {
              onChangeField(
                organisationRef,
                setOrganisationIsValid,
                organisationIsValid,
              );
            }}
            data-testid="sign-up-org-input"
          />
          <Input
            type="url"
            inputName="url"
            placeholder="https://organisation.com/bio"
            labelChildren={(
              <>
                <p>Link to Official Bio / Linkedin</p>
                <Subheading>(If using personal email)</Subheading>
              </>
            )}
            data-testid="sign-up-url-input"
          />
        </>
      )}

      {isForEvent && (
        <Input
          type="text"
          inputName="expectation"
          numberAllowed
          placeholder="What do you want to know?"
          labelChildren={(
            <>
              <p>What do you want to know</p>
              <Subheading>
                Optional, but we will use your response to build the session!
              </Subheading>
            </>
          )}
        />
      )}

      <CheckboxWrapper>
        <CheckboxInput
          type="checkbox"
          name="terms"
          id="terms"
          value="accepted"
          required
          ref={tcRef}
          data-testid="sign-up-terms-checkbox"
        />
        <CheckWrapper>
          <CheckBoxDescription>
            I accept Apolitical&apos;s
            <Link
              href="https://about.apolitical.co/terms-and-conditions"
              data-gtm-event-context={
                isForEvent ? 'EventPage' : 'HomePageSignupForm'
              }
              data-gtm-event-type="terms-of-service-click"
              className="gtm-trackable"
            >
              Terms of service
            </Link>
            and
            <Link
              href="https://about.apolitical.co/privacy-policy"
              data-gtm-event-context={
                isForEvent ? 'EventPage' : 'HomePageSignupForm'
              }
              data-gtm-event-type="privacy-policy-click"
              className="gtm-trackable"
            >
              Privacy policy.
            </Link>
          </CheckBoxDescription>
          <SubTerms>
            As part of our service you will receive relevant policy, network and platform emails
          </SubTerms>
        </CheckWrapper>
      </CheckboxWrapper>
      <CheckboxWrapper>
        <CheckboxInput
          type="checkbox"
          name="marketing"
          id="marketing"
          data-testid="sign-up-marketing-checkbox"
        />
        <CheckWrapper>
          <CheckBoxDescription>
            I want to receive updates about relevant professional
            opportunities and promotions, such as jobs, partner events and trainings.
          </CheckBoxDescription>
        </CheckWrapper>
      </CheckboxWrapper>

      {signUpError && (
        <SignupErrorText data-testid="sign-up-form-error">
          We&apos;re really sorry, but we&apos;ve had a problem trying to sign you up.
          This could be an issue with our system, so we suggest you try again later.
        </SignupErrorText>
      )}
      {userExists && (
        <ErrorMessage
          validationMessage={(
            <>
              Looks like this email has been used to sign up to Apolitical
              before, try login instead. If you&apos;re still having issues,
              contact
              <Link
                href="mailto:concierge@apolitical.co"
                data-gtm-event-context={
                  isForEvent ? 'EventPage' : 'HomePageSignupForm'
                }
                data-gtm-event-type="concierge-email-click"
                className="gtm-trackable"
              >
                concierge@apolitical.co
              </Link>
            </>
          )}
        />
      )}
      {submittingForm ? (
        <>
          <Spinner />
          <SubmittingFormText>Submitting form...</SubmittingFormText>
        </>
      ) : (
        <SignUpButtonWrapper>
          <StyledButton
            data-gtm-event-context={
              isForEvent ? 'EventPage' : 'HomePageSignupForm'
            }
            data-gtm-event-type="signup-submit-click"
            className="gtm-trackable"
            onClick={handleSubmitEvent}
            disabled={disableFields}
            data-testid="sign-up-button"
          >
            Join for free
          </StyledButton>
          <ValidationButton ref={hiddenValidationRef} />
        </SignUpButtonWrapper>
      )}
      {!isForEvent && (
        <>
          <LogInQuestion>Already have an account?</LogInQuestion>
          <LogInAnswer
            variant="secondary"
            href="/user-onboarding/login"
            data-gtm-event-context={
              isForEvent ? 'EventPage' : 'HomePageSignupForm'
            }
            data-gtm-event-type="login-click"
          >
            Log In
          </LogInAnswer>
        </>
      )}
      {!emailIsEnd2End && loadRecaptcha && (
        <ReCAPTCHA
          ref={recaptchaRef}
          onChange={handleData}
          sitekey="6LdlFYwUAAAAABpknjihdSkky59MlE9-92II97aM"
          size="invisible"
          badge="bottomright"
        />
      )}
    </SignUpFormBody>
  );
};

LiteSignupFormUI.defaultProps = {
  className: '',
};

export default LiteSignupFormUI;
