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

import { useMsal } from '@azure/msal-react';

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 { getAzureInstances } from 'src/services/authService';
import { LoginErrors, type LoginInstance } from 'src/types/login';
import { useLokaliseTranslation } from 'src/utils/i18n';

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

const AzureLogin = (props: AzureLoginProps) => {
  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 showGeneralError = useGeneralError();
  const { enqueueSnackbar } = useHuSnackbar();
  const navigate = useNavigate();
  const { azureLogin } = useAuth();
  const { setPrimary, resetPrimary } = useSettings();
  const { instance } = useMsal();

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

  const handleLogin = async () => {
    try {
      onLogin();
      const { accessToken: azureAccessToken } =
        await instance.acquireTokenPopup({
          scopes: ['profile', 'openid', 'User.Read'],
          redirectUri: '/blank.html',
          prompt: 'login',
        });

      setLoadingCommunities(true);
      const response = await getAzureInstances(azureAccessToken);
      setLoadingCommunities(false);
      if (response.data?.length) {
        setInstances(response.data);
        setAccessToken(azureAccessToken);
        if (response.data.length === 1) {
          await login(azureAccessToken, response.data[0]);
        }
      } else {
        enqueueSnackbar({
          title: t('ERROR_AZURE_GRAPH_API'),
          variant: 'error',
        });
      }
    } catch (err: any) {
      if (err?.message?.includes('interaction_in_progress')) {
        showGeneralError(
          err,
          t('WARNING_AZURE_LOGIN_INTERACTION_IN_PROGRESS'),
          false,
        );
      } else {
        const errorCode = err?.response?.data?.code;
        showGeneralError(
          err,
          t(
            errorCode === LoginErrors.SSO_MORE_THAN_ONE_USER_MATCHING_EMAIL
              ? 'ERROR_SSO_LOGIN_DUPLICATED_EMAIL'
              : 'ERROR_AZURE_LOGIN',
          ),
        );
      }
    } finally {
      onLoginFinally();
    }
  };

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

  const handleSelectInstance = async (huInstance: LoginInstance) => {
    try {
      navigate('');
      await login(accessToken!, huInstance);
      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_AZURE_LOGIN',
        ),
      );
    }
  };

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

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

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

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

export default AzureLogin;
