import generateQueryString from '@/lib/generateQueryString';
import trackAnalyticsEvent from '@/lib/trackAnalyticsEvent';
import { AccountContext } from '@/lib/useAccount';
import { blue700, gray700, red500, yellow } from '@/styles/colors';
import { keyframes } from '@emotion/react';
import styled from '@emotion/styled';
import Link from 'next/link';
import { useCallback, useContext, useEffect, useMemo, useState } from 'react';
import ErrorModal from './ErrorModal';
import {
  H1,
  LearnMoreButton,
  LinkLike,
  OrLine,
  Paragraph,
  StartButton,
  UnderMessage,
  WidgetInput,
} from './QuickstartWidget';
import SineCycle from './SineCycle';
import Tooltip from './Tooltip';
import { RecaptchaTerms } from './auth/RecaptchaTerms';
import { EMAIL_REGEX, checkPassword, getRecaptchaToken } from './auth/helper';
const SERVER_URL = process.env.NEXT_PUBLIC_SERVER_URL;

const wipeBackground = keyframes`
  0% {
    background-color: #ffffffff;
  }
  100% {
    background: #ffffff00;
  }
`;

const pulseBorder = keyframes`
  0% {
    /* transform: scale(1.02); */
    outline: 11px solid ${yellow}00;
  }
  50% {
    /* transform: scale(1.01); */
    outline: 6px solid ${yellow}ff;
  }
  100% {
    /* transform: scale(1.0); */
    outline: 1px solid ${yellow}00;
  }
`;

const Wrapper = styled.div`
  display: contents;
`;

const WipeAnimation = styled.div`
  display: block;
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  pointer-events: none;
  z-index: 5;
  outline: 4px solid transparent;
  background-color: #ffffff00;
  border-radius: 10px;
  transition: opacity 0.25s ease;
  animation:
    ${wipeBackground} 1s linear,
    ${pulseBorder} 2s linear infinite;
`;

const ModeToggleLink = styled(LinkLike)`
  font-size: 18px;
  font-weight: 500;
  text-decoration: none;
  &:hover {
    text-decoration: underline;
  }
`;

const Footer = styled.div`
  text-align: center;
`;

export const InputTitle = styled.h4`
  font-size: 16px;
  font-weight: 500;
  margin: 0;
`;

const InputGrid = styled.div`
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr 1fr;
  column-gap: 20px;
  row-gap: 15px;
  .full {
    grid-column: 1 / 3;
  }
  @media screen and (max-width: 800px) {
    > * {
      grid-column: 1 / 3;
    }
  }
`;

const InputWrapper = styled.div``;

const SubmitSection = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  margin-top: 10px;
`;

const LegalText = styled.p`
  font-size: 13px;
  color: ${gray700};
  margin: 0;
  margin-right: 70px;
  @media screen and (max-width: 800px) {
    margin-right: 20px;
  }
`;

const SocialButton = styled.button`
  border: 1px solid ${gray700};
  border-radius: 4px;
  background-color: white;
  padding: 10px 20px;
  font-size: 18px;
  text-align: left;
  display: flex;
  align-items: center;
  justify-content: space-between;
  & + & {
    margin-top: 10px;
  }
  &:hover {
    background-color: #e5f3ff;
    border-color: ${blue700};
    cursor: pointer;
  }
`;

const validateInputs = (name: string, email: string, password: string) => {
  const errors: { field: string; message: string }[] = [];
  if (!name) {
    errors.push({
      field: 'name',
      message: 'Please enter your name',
    });
  }
  if (!email.trim()) {
    errors.push({
      field: 'email',
      message: 'Please enter an email',
    });
  }
  if (!password) {
    errors.push({
      field: 'password',
      message: 'Please enter a password',
    });
  }
  if (!EMAIL_REGEX.test(email)) {
    errors.push({
      field: 'email',
      message: 'Please enter a valid email',
    });
  }
  const passwordError = checkPassword(password);
  if (passwordError) {
    errors.push({
      field: 'password',
      message: passwordError,
    });
  }
  return errors;
};

const bounce = keyframes`
  0%, 50%, 100% {
    transform: translateY(0);
  }
  30% {
    transform: translateY(-10px);
  }
  80% {
    transform: translateY(-5px);
  }
`;

const ErrorExclamationMark = styled.span`
  width: 18px;
  height: 18px;
  border-radius: 10px;
  margin-left: 5px;
  color: white;
  background-color: ${red500};
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: help;
  animation: ${bounce} 0.5s;
`;

const LoadingAnimation = styled.div<{ active: boolean }>`
  position: absolute;
  z-index: 2;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: ${({ active }) => (active ? '#ffffffaa' : '#ffffff00')};
  border-radius: 10px;

  pointer-events: ${({ active }) => (active ? 'auto' : 'none')};
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  backdrop-filter: blur(${({ active }) => (active ? 5 : 0)}px);
  transition:
    backdrop-filter 0.5s,
    background-color 0.5s;
  font-size: 24px;
  font-weight: 600;
  > * {
    position: relative;
    top: ${({ active }) => (active ? 0 : 20)}px;
    opacity: ${({ active }) => (active ? 1 : 0)};
    transition:
      top 0.5s ease,
      opacity 0.5s;
  }
`;

const InputError = ({ children }: { children: React.ReactNode[] | React.ReactNode }) => {
  return (
    <Tooltip immediate enabled message={children}>
      <ErrorExclamationMark>!</ErrorExclamationMark>
    </Tooltip>
  );
};

const AuthWidget = () => {
  const [mode, setMode] = useState<'log-in' | 'sign-up' | 'reset-password' | 'verify-email'>('sign-up');

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');
  const [errors, setErrors] = useState<{ field: string; message: string }[]>([]);
  const [authFailed, setAuthFailed] = useState(false);
  const [authLoading, setAuthLoading] = useState(false);
  const [resetPasswordLoading, setResetPasswordLoading] = useState(false);
  const { refetch: refetchAccount } = useContext(AccountContext);

  const handleSignUp = useCallback(async () => {
    setAuthLoading(true);
    trackAnalyticsEvent({
      name: 'Landing Button Clicked',
      properties: {
        text: 'Sign up with Email',
        location: 'Quickstart Auth Widget',
      },
    });
    const validationErrors = validateInputs(name, email, password);
    setErrors(validationErrors);
    if (validationErrors.length) {
      setAuthLoading(false);
      return;
    }
    const token = await getRecaptchaToken('register');
    const response = await fetch(
      `${SERVER_URL}/auth/email/register${generateQueryString({
        back_to_landing: 'true',
      })}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email, password, name, token }),
        credentials: 'include',
      }
    );
    setAuthLoading(false);
    if (response.status === 204) {
      setAuthFailed(true);
      setErrors([
        {
          field: 'email',
          message: 'Email already registered',
        },
      ]);
      return;
    } else if (response.status === 202) {
      setMode('verify-email');
    } else {
      setAuthFailed(true);
    }
  }, [name, email, password]);

  const handleLogIn = useCallback(async () => {
    setAuthLoading(true);
    setAuthFailed(false);
    trackAnalyticsEvent({
      name: 'Landing Button Clicked',
      properties: {
        text: 'Sign up with Email',
        location: 'Quickstart Auth Widget',
      },
    });
    const validationErrors = validateInputs('placeholder-name', email, password);
    setErrors(validationErrors);
    if (validationErrors.length) {
      setAuthLoading(false);
      return;
    }
    const token = await getRecaptchaToken('login');

    const loginResponse = await fetch(
      `${SERVER_URL}/auth/email/login${generateQueryString({
        back_to_landing: 'true',
      })}`,
      {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify({ email, password, token }),
        credentials: 'include',
      }
    );
    // Convert response to text
    const contents = await loginResponse.text();

    if (loginResponse.status === 200) {
      // don't set authLoading to false - this will happen automatically when `account` is updated.
      setTimeout(() => refetchAccount(), 500);
    } else if (loginResponse.status === 403) {
      setErrors([
        {
          field: 'email',
          message: 'Please verify for your email.',
        },
      ]);
      setEmail(email);
      setAuthFailed(true);
      setAuthLoading(false);
    } else {
      setAuthFailed(true);
      setAuthLoading(false);
    }
  }, [email, password]);

  const handleResetPassword = useCallback(async () => {
    const validationErrors = validateInputs('placeholder-name', email, '123ValidPlaceholderPassword');
    setErrors(validationErrors);
    if (validationErrors.length > 0) {
      setAuthFailed(true);
      return;
    }
    setResetPasswordLoading(true);
    const token = await getRecaptchaToken('forgot_password');

    const response = await fetch(`${SERVER_URL}/auth/email/forgot`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({ email, token }),
      credentials: 'include',
    });

    setResetPasswordLoading(false);
    if (response.status === 200) {
      setMode('reset-password');
    } else {
      setAuthFailed(true);
    }
  }, [email]);

  const firstEmailError = useMemo(() => errors.filter((e) => e.field === 'email').map((e) => e.message)[0], [errors]);
  const firstPasswordError = useMemo(
    () => errors.filter((e) => e.field === 'password').map((e) => e.message)[0],
    [errors]
  );
  const firstNameError = useMemo(() => errors.filter((e) => e.field === 'name').map((e) => e.message)[0], [errors]);

  useEffect(() => {
    setAuthFailed(false);
    setErrors((errors) => errors.filter((e) => e.field !== 'name'));
  }, [name]);

  useEffect(() => {
    setAuthFailed(false);
    setErrors((errors) => errors.filter((e) => e.field !== 'email'));
  }, [email]);

  useEffect(() => {
    setAuthFailed(false);
    setErrors((errors) => errors.filter((e) => e.field !== 'password'));
  }, [password]);

  useEffect(() => {
    setAuthFailed(false);
    setErrors([]);
  }, [mode]);

  const [hideWipe, setHideWipe] = useState(false);
  const anythingLoading = authLoading || resetPasswordLoading;

  const [fastRefreshAuth, setFastRefreshAuth] = useState(false);
  useEffect(() => {
    if (fastRefreshAuth) {
      const interval = setInterval(() => {
        refetchAccount();
      }, 3000);
      return () => clearInterval(interval);
    }
  }, [fastRefreshAuth]);

  return (
    <Wrapper onClick={(e) => setHideWipe(true)}>
      <WipeAnimation style={{ opacity: hideWipe ? 0 : 1 }} />
      <LoadingAnimation active={anythingLoading}>
        <SineCycle color={'black'} />
      </LoadingAnimation>
      {mode === 'sign-up' ? (
        <>
          {authFailed && (
            <ErrorModal
              onClick={() => setAuthFailed(false)}
              message={
                <span style={{ color: 'white', textAlign: 'center' }}>
                  {errors.length > 0
                    ? `Error: ${errors[0].message}`
                    : "We couldn't sign you up. Please check for errors and try again."}
                </span>
              }
            />
          )}
          <H1>Sign Up</H1>
          <Paragraph>A free account is required, and won't interrupt your import.</Paragraph>
          <SocialButton
            onClick={() => {
              setFastRefreshAuth(true);
              trackAnalyticsEvent({
                name: 'Landing Button Clicked',
                properties: {
                  text: 'Sign up with Google',
                  location: 'Auth Modal',
                },
              });
              window.open(
                `${SERVER_URL}/auth/google/signup?back_to_landing=true`,
                undefined,
                'popup,top=200,left=200,width=800,height=560'
              );
            }}
          >
            Sign Up with Google <img src="/images/icons/Google.svg" height={24} width={24} alt="Google Logo" />
          </SocialButton>
          <SocialButton
            onClick={() => {
              setFastRefreshAuth(true);
              trackAnalyticsEvent({
                name: 'Landing Button Clicked',
                properties: {
                  text: 'Sign up with Facebook',
                  location: 'Auth Modal',
                },
              });
              window.open(
                `${SERVER_URL}/auth/facebook/signup?back_to_landing=true`,
                undefined,
                'popup,top=200,left=200,width=800,height=560'
              );
            }}
          >
            Sign Up with Facebook <img src="/images/icons/Facebook.svg" height={24} width={24} alt="Facebook logo" />
          </SocialButton>
          <OrLine>Or</OrLine>
          <InputGrid>
            <InputWrapper>
              <InputTitle>Name {firstNameError && <InputError>{firstNameError}</InputError>}</InputTitle>
              <WidgetInput
                value={name}
                onChange={(e) => setName(e.target.value)}
                withError={!!firstNameError}
                placeholder="What do people call you?"
              />
            </InputWrapper>
            <InputWrapper>
              <InputTitle>Email {firstEmailError && <InputError>{firstEmailError}</InputError>}</InputTitle>
              <WidgetInput
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                withError={!!firstEmailError}
                placeholder="hello@example.com"
              />
            </InputWrapper>
            <InputWrapper className="full">
              <InputTitle>Password {firstPasswordError && <InputError>{firstPasswordError}</InputError>}</InputTitle>
              <WidgetInput
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                onKeyDown={(e) => e.key === 'Enter' && handleLogIn()}
                withError={!!firstPasswordError}
                placeholder="Enter a password"
                type="password"
              />
            </InputWrapper>
          </InputGrid>
          <SubmitSection>
            <LegalText>
              By signing up, you confirm that you have read and agree to our{' '}
              <Link href="/terms-of-service" target="_blank">
                Terms of Service
              </Link>{' '}
              and{' '}
              <Link href="/privacy-policy" target="_blank">
                Privacy Policy
              </Link>
              .
            </LegalText>
            <StartButton onClick={handleSignUp} emphasized={true} disabled={errors.length > 0}>
              Sign Up
            </StartButton>
          </SubmitSection>
          <Footer>
            <ModeToggleLink onClick={() => setMode('log-in')}>Already have an account? Log In instead.</ModeToggleLink>
          </Footer>
        </>
      ) : mode === 'log-in' ? (
        <>
          {authFailed && (
            <ErrorModal
              onClick={() => setAuthFailed(false)}
              message={
                <span style={{ color: 'white', textAlign: 'center' }}>
                  {errors.length > 0
                    ? `Error: ${errors[0].message}`
                    : "We couldn't log you in. Please try again later."}
                </span>
              }
            />
          )}
          <H1>Log In</H1>
          <Paragraph>Logging in won't interrupt your import.</Paragraph>
          <SocialButton
            onClick={() => {
              setFastRefreshAuth(true);
              trackAnalyticsEvent({
                name: 'Landing Button Clicked',
                properties: {
                  text: 'Log in with Google',
                  location: 'Auth Modal',
                },
              });
              window.open(
                `${SERVER_URL}/auth/google?back_to_landing=true`,
                undefined,
                'popup,top=200,left=200,width=800,height=560'
              );
            }}
          >
            Log In with Google <img src="/images/icons/Google.svg" height={24} width={24} alt="Google Logo" />
          </SocialButton>
          <SocialButton
            onClick={() => {
              setFastRefreshAuth(true);
              trackAnalyticsEvent({
                name: 'Landing Button Clicked',
                properties: {
                  text: 'Log in with Facebook',
                  location: 'Auth Modal',
                },
              });
              window.open(
                `${SERVER_URL}/auth/facebook?back_to_landing=true`,
                undefined,
                'popup,top=200,left=200,width=800,height=560'
              );
            }}
          >
            Log In with Facebook <img src="/images/icons/Facebook.svg" height={24} width={24} alt="Facebook logo" />
          </SocialButton>
          <OrLine>Or</OrLine>
          <InputGrid>
            <InputWrapper style={{ gridColumn: '1 / 3' }}>
              <InputTitle>Email</InputTitle>
              <WidgetInput
                type="email"
                value={email}
                onChange={(e) => setEmail(e.target.value)}
                placeholder="hello@example.com"
              />
            </InputWrapper>
            <InputWrapper style={{ gridColumn: '1 / 3' }}>
              <InputTitle>Password</InputTitle>
              <WidgetInput
                type="password"
                value={password}
                onChange={(e) => setPassword(e.target.value)}
                onKeyDown={(e) => e.key === 'Enter' && handleLogIn()}
                placeholder="Enter your password"
              />
            </InputWrapper>
          </InputGrid>
          <SubmitSection>
            <LearnMoreButton onClick={() => handleResetPassword()}>Forgot Password</LearnMoreButton>
            <StartButton onClick={handleLogIn} disabled={errors.length > 0} emphasized={true}>
              Log In
            </StartButton>
          </SubmitSection>
          <Footer>
            <ModeToggleLink onClick={() => setMode('sign-up')}>Don't have an account? Sign Up instead.</ModeToggleLink>
          </Footer>
        </>
      ) : mode === 'reset-password' ? (
        <>
          <H1>Check your email</H1>
          <div>
            <Paragraph>
              We've sent a password reset link to <strong>{email}</strong>.
            </Paragraph>
            <Paragraph>
              Please open the link, update your password, then return here. (Remember to check your spam folder)
            </Paragraph>
          </div>
          <Footer style={{ display: 'flex', justifyContent: 'center' }}>
            <StartButton emphasized={true} onClick={() => setMode('log-in')}>
              Done
            </StartButton>
          </Footer>
        </>
      ) : mode === 'verify-email' ? (
        <>
          <H1>Check your email</H1>
          <div>
            <Paragraph>
              We've sent a verification link to <strong>{email}</strong>.
            </Paragraph>
            <Paragraph>Please open the link, then return here. (Remember to check your spam folder)</Paragraph>
          </div>
          <Footer>
            <ModeToggleLink onClick={() => setMode('sign-up')}>Go back</ModeToggleLink>
          </Footer>
        </>
      ) : (
        <div>Error: invalid auth widget mode {mode}</div>
      )}
      <UnderMessage style={{ color: 'white', justifyContent: 'center', display: 'flex' }}>
        <RecaptchaTerms />
      </UnderMessage>
    </Wrapper>
  );
};
export default AuthWidget;
function apiFetch(arg0: string, arg1: string) {
  throw new Error('Function not implemented.');
}
