import { useEffect, useState } from 'react';
import { useNavigate } from 'react-router-dom';

import { useGoogleLogin } from '@react-oauth/google';

import * as HuAuth from '@material-hu/components/composed-components/auth';
import { type ButtonProps } from '@material-hu/components/design-system/Buttons/Button';
import useHuSnackbar from '@material-hu/components/design-system/Snackbar';

import { useAuth } from 'src/contexts/JWTContext';
import { useSettings } from 'src/contexts/SettingsContext';
import useGeneralError from 'src/hooks/useGeneralError';
import { getGoogleInstances } from 'src/services/authService';
import { LoginErrors, type LoginInstance } from 'src/types/login';
import { useLokaliseTranslation } from 'src/utils/i18n';

export type GoogleLoginProps = ButtonProps & {
  onLogin: () => void;
  onLoginFinally: () => void;
};

const GoogleLogin = (props: GoogleLoginProps) => {
  const { onLogin = () => null, onLoginFinally = () => null } = props;

  const [instances, setInstances] = useState<LoginInstance[]>([]);
  const [accessToken, setAccessToken] = useState<string | null>(null);
  const [loadingCommunities, setLoadingCommunities] = useState(false);

  const { t } = useLokaliseTranslation('authentication');
  const { enqueueSnackbar } = useHuSnackbar();
  const navigate = useNavigate();
  const showGeneralError = useGeneralError();
  const { googleLogin } = useAuth();
  const { setPrimary, resetPrimary } = useSettings();

  const googleLoginHook = useGoogleLogin({
    onSuccess: async ({ access_token }) => {
      try {
        setLoadingCommunities(true);
        const response = await getGoogleInstances(access_token);
        setLoadingCommunities(false);
        if (response.data?.length) {
          setInstances(response.data);
          setAccessToken(access_token);
          if (response.data.length === 1) {
            await login(access_token, response.data[0]);
          }
        } else {
          enqueueSnackbar({
            title: t('GOOGLE_NO_COMMUNITY'),
            variant: 'error',
          });
        }
      } catch (err: any) {
        const errorCode = err?.response?.data?.code;
        showGeneralError(
          err,
          t(
            errorCode === LoginErrors.SSO_MORE_THAN_ONE_USER_MATCHING_EMAIL
              ? 'ERROR_SSO_LOGIN_DUPLICATED_EMAIL'
              : 'ERROR_GOOGLE_LOGIN',
          ),
        );
      } finally {
        onLoginFinally();
      }
    },
    onError: err => {
      showGeneralError(err, t('ERROR_GOOGLE_LOGIN'));
    },
    onNonOAuthError: () => {
      onLoginFinally();
    },
  });

  const login = async (newAccessToken: string, instance: LoginInstance) => {
    if (!googleLogin) throw new Error('googleLogin is not available');
    setPrimary(instance.color);
    const body = {
      accessToken: newAccessToken,
      instanceId: instance.id,
    };
    await googleLogin(body);
  };

  const handleSelectInstance = async (instance: LoginInstance) => {
    try {
      navigate('');
      await login(accessToken!, instance);
      closeSelectInstanceDrawer();
    } catch (err: any) {
      const errorCode = err?.response?.data?.code;
      showGeneralError(
        err,
        t(
          errorCode === LoginErrors.SSO_MORE_THAN_ONE_USER_MATCHING_EMAIL
            ? 'ERROR_SSO_LOGIN_DUPLICATED_EMAIL'
            : 'ERROR_GOOGLE_LOGIN',
        ),
      );
    }
  };

  const handleCancelInstance = () => {
    navigate('');
    setInstances([]);
  };

  useEffect(() => {
    resetPrimary();
  }, [resetPrimary]);

  const handleLogin = () => {
    onLogin();
    googleLoginHook();
  };

  const {
    drawer: selectInstanceDrawer,
    showDrawer: showSelectInstanceDrawer,
    closeDrawer: closeSelectInstanceDrawer,
  } = HuAuth.useSelectIntanceDrawer({
    onClose: handleCancelInstance,
    loading: loadingCommunities,
    instances,
    onSelectInstance: (instance: { name: string; logo: string }) => {
      handleSelectInstance(instance as LoginInstance);
    },
    showSearch: false,
  });

  useEffect(() => {
    if (instances.length > 1) {
      showSelectInstanceDrawer(true);
    }
  }, [instances]);

  return (
    <>
      <HuAuth.SSOButton
        type="Google"
        onClick={handleLogin}
      />
      {selectInstanceDrawer}
    </>
  );
};

export default GoogleLogin;
