import { Button, Stack, TextField, Typography, Box } from '@mui/material';
import { useEffect, useRef, useState, type Dispatch } from 'react';
import { useTranslation } from 'react-i18next';
import { isNumeric } from '@/utils/regexes/isNumeric';
import type { AuthFactory, AuthType } from '../../types/authTypes';
import { isEmail } from '@/utils/regexes/isEmail';
import { AuthenticationCard } from '../AuthenticationCard';
import { CountryCodeSelector } from '../../../../components/CountryCodeSelector';
import type { LoginResult, UserStatus } from '../../types/userTypes';
import { getUserStatusByPhoneNumberOrEmail } from '../../api/authorizationAPI';
import type { CountryCode } from '@/types/commonTypes';
import { isPhoneNumber } from '@/utils/regexes/isValidPhoneNumber';
import { useToast } from '@rkheftan/harmony-ui';
import { useApi } from '@/hooks/useApi';
import type { GenerateTokenResponse } from '../../api/identityAPI';
import { GoogleAuthenticationV2 } from './GoogleAuthenticationV2';
import { replacePersianWithRealNumbers } from '@/utils/replacePersianWithRealNumbers';

export interface LoginRegisterFormProps {
  loginRegisterValue: string;
  setLoginRegisterValue: Dispatch<string>;
  countryCode: CountryCode;
  setCountryCode: Dispatch<CountryCode>;
  authType: AuthType;
  setAuthType: Dispatch<AuthType>;
  onLoginRegisterSubmit: (value: string, userStatus: UserStatus) => void;
  onGoogleAuthenticated: (
    loginResult: LoginResult,
    tokenResponse: GenerateTokenResponse,
  ) => void;
  authFactory: AuthFactory;
}

export function LoginRegisterForm({
  loginRegisterValue,
  setLoginRegisterValue,
  countryCode,
  setCountryCode,
  authType,
  setAuthType,
  onLoginRegisterSubmit,
  onGoogleAuthenticated,
  authFactory,
}: LoginRegisterFormProps) {
  const { t, i18n } = useTranslation('authentication');
  const textFieldRef = useRef<HTMLDivElement>(null);
  const inputRef = useRef<HTMLInputElement>(null);
  const [error, setError] = useState<string>();
  const [touched, setTouched] = useState<boolean>(false);
  const inputError: boolean = touched && !!error;
  const [menuAnchorEl, setMenuAnchorEl] = useState<HTMLElement | null>(null);
  const toast = useToast();
  const { loading: userStatusLoading, execute: execUserStatus } = useApi(
    getUserStatusByPhoneNumberOrEmail,
  );

  useEffect(() => {
    if (textFieldRef.current) {
      const inputBaseElement =
        textFieldRef.current.querySelector('.MuiInputBase-root');
      if (inputBaseElement) {
        setMenuAnchorEl(inputBaseElement as HTMLElement);
      }
    }
  }, []);

  const handleInputChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    let newValue = event.target.value;
    newValue = replacePersianWithRealNumbers(newValue);

    setLoginRegisterValue(newValue);

    // If the new value contains only digits (or is empty), it's a phone number
    if (isNumeric(newValue)) {
      setAuthType('phone');
    } else {
      setAuthType('email');
    }
  };

  const handleBlur = () => {
    setTouched(true);
    validateInput(loginRegisterValue, authType);
  };

  const validateInput = (
    value: string,
    authType: AuthType,
    setErrors: boolean = true,
  ): boolean => {
    if (!value) {
      if (setErrors) setError(t('loginForm.thisFieldIsRequired'));
      return false;
    }

    if (authType === 'email' && !isEmail(value)) {
      if (setErrors) setError(t('loginForm.emailIsInvalid'));
      return false;
    }

    if (authType === 'phone' && !isPhoneNumber(countryCode, value)) {
      if (setErrors) setError(t('loginForm.phoneNumberIsInvalid'));
      return false;
    }

    if (setErrors) setError(undefined);
    return true;
  };

  const handleSubmit = async () => {
    if (validateInput(loginRegisterValue, authType, false)) {
      let newValue = loginRegisterValue;

      if (
        authType === 'phone' &&
        countryCode === '+98' &&
        newValue.startsWith('09')
      ) {
        newValue = newValue.substring(1);
        setLoginRegisterValue(newValue);
      }

      const res = await execUserStatus({
        phoneNumber: authType === 'phone' ? countryCode + newValue : undefined,
        email: authType === 'email' ? newValue : undefined,
      });

      if (!res) {
        return;
      }

      if (res.success) {
        onLoginRegisterSubmit(newValue, res.userStatus);
      } else {
        toast({ message: res.message, severity: 'error' });
      }
    } else {
      inputRef.current?.focus();
      validateInput(loginRegisterValue, authType);
    }
  };

  const showAdornment = authType === 'phone' && loginRegisterValue.length > 0;

  return (
    <AuthenticationCard>
      <Box
        component="form"
        onSubmit={(e) => {
          e.preventDefault();
          e.stopPropagation();
          if (!userStatusLoading) {
            void handleSubmit();
          }
        }}
      >
        <Stack spacing={1}>
          <Typography variant="h5">{t('loginForm.title')}</Typography>
          <Typography variant="body2" color="text.secondary">
            {t('loginForm.description')}
          </Typography>
        </Stack>

        <TextField
          ref={textFieldRef}
          inputRef={inputRef}
          label={t('loginForm.emailOrPhoneLabel')}
          value={loginRegisterValue}
          onChange={handleInputChange}
          onBlur={handleBlur}
          error={inputError}
          helperText={inputError ? error : ''}
          autoFocus
          slotProps={{
            htmlInput: { dir: 'auto', sx: { lineHeight: 1.5 } },
            input: {
              endAdornment: i18n.dir() === 'rtl' && (
                <CountryCodeSelector
                  value={countryCode}
                  onChange={setCountryCode}
                  show={showAdornment}
                  menuAnchor={menuAnchorEl}
                  onCloseFocusRef={inputRef}
                />
              ),
              startAdornment: i18n.dir() === 'ltr' && (
                <CountryCodeSelector
                  value={countryCode}
                  onChange={setCountryCode}
                  show={showAdornment}
                  menuAnchor={menuAnchorEl}
                  onCloseFocusRef={inputRef}
                />
              ),
            },
          }}
          sx={{ my: 4 }}
        />

        <Stack spacing={2}>
          <Button loading={userStatusLoading} type="submit">
            {t('loginForm.submitButton')}
          </Button>

          <GoogleAuthenticationV2
            authFactory={authFactory}
            onGoogleAuthenticated={onGoogleAuthenticated}
            disabled={userStatusLoading}
          />
        </Stack>
      </Box>
    </AuthenticationCard>
  );
}
