import React, {useState, useCallback, useEffect, useRef} from 'react';
import {View, KeyboardAvoidingView, Keyboard} from 'react-native';
import {useTranslation} from 'react-i18next';
import {useSafeAreaInsets} from 'react-native-safe-area-context';
import {useDispatch} from 'react-redux';
import {useMutation} from '@tanstack/react-query';
import {
  InputClassic,
  Button,
  Typography,
  InputPassword,
  Spinner,
  Pressable,
  Dialog,
  DismissKeyboard,
  TextInputType,
} from '@components';
import {useBackHandler} from '@hooks/useBackHandler';
import {Navigation} from '@interfaces/navigation';
import {OTP2faToken} from '@modules/login/interfaces';
import {useEmailLogin, useSocialLogin} from '@modules/login/hooks/useAuth';
import {resetPassword} from '@modules/login/services';
import {CommunityHeader} from '@modules/login/components/CommunityHeader';
import {closeSessionExpiredDialog} from '@modules/app/redux';
import {showSnackbar} from '@redux/dispatchers';
import {Screens} from '@shared/constants';
import {useTheme} from '@shared/theme';
import {commonStyles} from '@shared/styles';

import {styles} from './styles';

function Login({
  navigation,
  route: {
    params: {
      instance,
      socialNetwork,
      accessToken,
      nonce,
      fullName,
      identifier,
      singleInstance,
    },
  },
}: Navigation<Screens.LOGIN>) {
  const {
    id: instanceId,
    logo,
    userHasEmail,
    otpAfterRegularLogin,
    useJanusForClassicLogin,
  } = instance;
  const {t} = useTranslation();
  const dispatch = useDispatch();
  const {theme} = useTheme();
  const {top: paddingTop} = useSafeAreaInsets();
  const passwordRef = useRef<Nullable<TextInputType>>(null);
  const [password, setPassword] = useState('');
  const [passwordError, setPasswordError] = useState('');
  const [confirmationModal, setConfirmationModal] = useState(false);
  const [isPreparingSession, setIsPreparingSession] = useState(false);
  const {
    isLoading: isLoadingLogin,
    dispatchLogin,
    clearLoginError,
  } = useEmailLogin({
    onSuccess: () => {
      // This is to show the spinner while the app is creating the session and redirecting to the home screen
      setIsPreparingSession(true);
    },
    onMustChangePassword: loginResponse => {
      setPassword('');
      setPasswordError('');
      navigation.replace(Screens.UPDATE_PASSWORD, {loginResponse, identifier});
    },
    onError: (errorText?: string) => {
      passwordRef.current?.clear();
      setPassword('');
      setPasswordError(errorText || t('authentication.wrong_password'));
    },
    otpAfterRegularLogin,
    useJanusForClassicLogin,
    onOTPSuccess: ({init2faToken}: OTP2faToken) => {
      setPasswordError('');
      navigation.navigate(Screens.OTP_MESSAGE, {
        instance,
        identifier: identifier!,
        init2faToken,
      });
    },
  });
  const {dispatchSocialLogin} = useSocialLogin();
  const isLoading = isLoadingLogin || isPreparingSession;

  const onPasswordChange = (text: string) => {
    setPassword(text);
    // Clear error when user starts typing
    if (passwordError) {
      setPasswordError('');
    }
  };

  const onLogin = useCallback(() => {
    dispatch(closeSessionExpiredDialog());

    if (!password?.trim().length) {
      setPasswordError(t('authentication.required_field'));
      return;
    }

    identifier && dispatchLogin({identifier, password, instanceId});
  }, [dispatch, dispatchLogin, identifier, instanceId, password, t]);

  const onTouchOutside = useCallback(() => {
    clearLoginError();
    setConfirmationModal(false);
  }, [clearLoginError]);

  const onGoBack = useCallback(() => {
    onTouchOutside();
    navigation.goBack();
    return true;
  }, [navigation, onTouchOutside]);

  useBackHandler(onGoBack);

  useEffect(() => {
    if (socialNetwork && accessToken) {
      dispatchSocialLogin({
        accessToken,
        fullName,
        nonce,
        socialNetwork,
        instanceId,
      });
    }
    // To avoid multiple SSO logins
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  const {mutate: onRecoverPassword, isPending: isLoadingReset} = useMutation({
    mutationFn: resetPassword,
    onSuccess: () =>
      showSnackbar({
        title: t(
          userHasEmail
            ? 'authentication.email_sent_to_you'
            : 'authentication.email_sent_to_admin',
        ),
        variant: 'success',
        ...(!userHasEmail && {
          description: t('authentication.email_sent_to_admin_desc'),
        }),
      }),
  });
  const onConfirmation = () => {
    setConfirmationModal(false);
    onRecoverPassword({employeeInternalId: identifier!, instanceId});
  };
  const onForgotPassword = () => {
    Keyboard.dismiss();
    setConfirmationModal(true);
  };
  const onPasswordFocus = () => setPasswordError('');

  return socialNetwork ? (
    <View style={styles.loadingContainer}>
      <Spinner />
    </View>
  ) : (
    <DismissKeyboard
      style={[
        commonStyles.flex,
        {backgroundColor: theme.background.layout.default},
      ]}>
      <KeyboardAvoidingView behavior="padding" style={commonStyles.flex}>
        <View style={[styles.container, {paddingTop}]}>
          <View style={styles.logoContentContainer}>
            <CommunityHeader logo={logo} instanceName={instance.name} />
          </View>
          <InputClassic
            label={t('authentication.user')}
            value={identifier}
            disabled
            style={styles.moreMargin}
            autoCorrect={false}
          />
          <InputPassword
            ref={passwordRef}
            label={t('authentication.password')}
            onSubmitEditing={onLogin}
            onChangeText={onPasswordChange}
            autoCorrect={false}
            autoCapitalize="none"
            isError={!!passwordError}
            helper={passwordError}
            autoFocus
            onFocus={onPasswordFocus}
          />
          <View style={[styles.flexStart, styles.moreMargin]}>
            <Pressable onPress={onForgotPassword} style={styles.flexStart}>
              <Typography
                color={theme.graphics.hugo[400]}
                style={styles.underline}>
                {t('authentication.forgot_password')}
              </Typography>
            </Pressable>
          </View>
          <Button
            text={t('authentication.login')}
            onPress={onLogin}
            isLoading={isLoading}
          />
          <Button
            variant="secondary"
            text={t(
              `${
                singleInstance
                  ? 'general.back'
                  : 'authentication.select_community'
              }`,
            )}
            onPress={onGoBack}
            disabled={isLoading || isLoadingReset}
          />
        </View>
      </KeyboardAvoidingView>
      <Dialog
        isVisible={confirmationModal}
        onClose={onTouchOutside}
        title={t('authentication.forgot_password_question')}
        footer={{
          primaryButton: {
            onPress: onConfirmation,
            text: t('authentication.send_email'),
          },
          secondaryButton: {
            onPress: onTouchOutside,
            text: t('general.cancel'),
          },
        }}>
        <Typography>
          {t(
            userHasEmail
              ? 'authentication.confirmation_email_to_you'
              : 'authentication.confirmation_email_to_admin',
          )}
        </Typography>
      </Dialog>
    </DismissKeyboard>
  );
}

export default Login;
