import { useMemo, useState, type JSX } from 'react';
import { LoginRegisterForm } from './LoginRegiserForm';
import type {
  AuthFactory,
  AuthMode,
  AuthStep,
  AuthType,
} from '../../types/authTypes';
import { OtpVerifyForm } from './OtpVerifyForm';
import { isNumeric } from '@/utils/regexes/isNumeric';
import { CompleteSignUp } from './CompleteSignUp';
import { EnterPasswordForm } from './EnterPasswordForm';
import { UserStatus, type LoginResult } from '../../types/userTypes';
import type { CountryCode } from '@/types/commonTypes';
import { VerifyPhoneNumber } from './VerifyPhoneNumber';
import { useNavigate, useSearchParams } from 'react-router-dom';
import type { GenerateTokenResponse } from '../../api/identityAPI';
import { useAuth } from '@/hooks/useAuth';

export const AuthenticationSteps = (): JSX.Element => {
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const [authMode, setAuthMode] = useState<AuthMode>('register');
  const [authType, setAuthType] = useState<AuthType>('phone');
  const [currentStep, setCurrentStep] = useState<AuthStep>('emailOrPhone');
  const [loginRegisterValue, setLoginRegisterValue] = useState<string>('');
  const [countryCode, setCountryCode] = useState<CountryCode>('+98');
  const [addPhoneCountryCode, setAddPhoneCountryCode] =
    useState<CountryCode>('+98');
  const [addedPhoneNumberValue, setAddedPhoneNumberValue] =
    useState<string>('');
  const [memoryTokenRes, setMemoryTokenRes] = useState<GenerateTokenResponse>();
  const [hasPassword, setHasPassword] = useState(false);
  const { login } = useAuth();

  const authFactory: AuthFactory = useMemo(() => {
    const redirectUrl = searchParams.get('redirect_url');
    const clientId = searchParams.get('client_id');

    if (!clientId) {
      const defaultFactory: AuthFactory = {
        clientId: import.meta.env.VITE_IDENTITY_CLIENT_ID,
        redirectUrl: import.meta.env.VITE_APP_URL,
        isCurrentApplication: function () {
          return this.clientId === import.meta.env.VITE_IDENTITY_CLIENT_ID;
        },
        getFullRedirectUrl: function (token: string) {
          return this.redirectUrl + '?token=' + token;
        },
      };

      return defaultFactory;
    }

    const resFactory: AuthFactory = {
      clientId: clientId,
      redirectUrl: redirectUrl as string,
      isCurrentApplication: function () {
        return this.clientId === import.meta.env.VITE_IDENTITY_CLIENT_ID;
      },
      getFullRedirectUrl: function (token: string) {
        return this.redirectUrl + '?token=' + token;
      },
    };

    return resFactory;
  }, [searchParams]);

  const handleLoginRegister = (value: string, userStatus: UserStatus) => {
    setAuthType(isNumeric(value) ? 'phone' : 'email');

    switch (userStatus) {
      case UserStatus.NotRegistered:
        setAuthMode('register');
        setCurrentStep('verify');
        break;

      case UserStatus.RegisteredWithoutPassword:
        setAuthMode('login');
        setCurrentStep('verify');

        break;

      case UserStatus.RegisteredWithPassword:
        setAuthMode('login');
        setCurrentStep('enterPassword');
        setHasPassword(true);

        break;
    }
  };

  const handleUserLoggedIn = (
    loginResult: LoginResult,
    tokenResponse: GenerateTokenResponse,
  ) => {
    setMemoryTokenRes(tokenResponse);
    // TODO: For now both application scopes can have their tokens
    // later we need to discuss this base on business plan and change it
    // if (authFactory.isCurrentApplication()) {}
    login(tokenResponse);

    if (loginResult.registeredWithOutPhoneNumber) {
      setCurrentStep('addPhoneNumber');
      return;
    }

    if (!loginResult.completedUserInformation) {
      if (!authFactory.isCurrentApplication()) {
        navigate(
          `/signup?returnUrl=${authFactory.getFullRedirectUrl(tokenResponse.refresh_token)}`,
        );
      } else {
        navigate(`/signup`);
      }
      return;
    }

    redirectToReturnUrl(tokenResponse.refresh_token);
  };

  const handlePhoneNumberVerified = () => {
    if (!authFactory.isCurrentApplication()) {
      navigate(
        `/signup?returnUrl=${authFactory.getFullRedirectUrl(memoryTokenRes?.refresh_token as string)}`,
      );
    } else {
      navigate(`/signup`);
    }
  };

  const redirectToReturnUrl = (refreshToken: string) => {
    if (authFactory.isCurrentApplication()) {
      navigate(import.meta.env.VITE_DEFUALT_AUTH_RETURN_URL);
    } else {
      if (authMode === 'register') {
        navigate(
          `/account-created?returnUrl=${authFactory.getFullRedirectUrl(refreshToken)}`,
        );
      } else {
        location.href = authFactory.getFullRedirectUrl(refreshToken);
      }
    }
  };

  return (
    <>
      {currentStep === 'emailOrPhone' && (
        <LoginRegisterForm
          authFactory={authFactory}
          onGoogleAuthenticated={handleUserLoggedIn}
          countryCode={countryCode}
          setCountryCode={setCountryCode}
          loginRegisterValue={loginRegisterValue}
          setLoginRegisterValue={setLoginRegisterValue}
          authType={authType}
          setAuthType={setAuthType}
          onLoginRegisterSubmit={handleLoginRegister}
        />
      )}

      {currentStep === 'verify' && (
        <OtpVerifyForm
          authFactory={authFactory}
          countryCode={countryCode}
          onOTPVerified={handleUserLoggedIn}
          onEditValue={() => setCurrentStep('emailOrPhone')}
          authMode={authMode}
          authType={authType}
          value={loginRegisterValue}
          hasPassword={hasPassword}
          onLoginWithPassword={() => setCurrentStep('enterPassword')}
        />
      )}

      {currentStep === 'enterPassword' && (
        <EnterPasswordForm
          authFactory={authFactory}
          loginRegisterValue={loginRegisterValue}
          countryCode={countryCode}
          authType={authType}
          onLoggedIn={handleUserLoggedIn}
          onEditValue={() => setCurrentStep('emailOrPhone')}
          onLoginWithOTP={() => setCurrentStep('verify')}
          emailOrPhone={loginRegisterValue}
        />
      )}

      {currentStep === 'addPhoneNumber' && (
        <CompleteSignUp
          countryCode={addPhoneCountryCode}
          setCountryCode={setAddPhoneCountryCode}
          value={addedPhoneNumberValue}
          setValue={setAddedPhoneNumberValue}
          email={loginRegisterValue}
          onCompleteSignUp={() => setCurrentStep('addedPhoneNumberVerify')}
        />
      )}

      {currentStep === 'addedPhoneNumberVerify' && (
        <VerifyPhoneNumber
          countryCode={countryCode}
          onEditValue={() => setCurrentStep('addPhoneNumber')}
          value={addedPhoneNumberValue}
          onPhoneNumberVerified={handlePhoneNumberVerified}
        />
      )}
    </>
  );
};
