import { useMsal } from "@azure/msal-react";
import { AuthError } from "@azure/msal-browser";
import { AppDispatch } from "app/store";
import Footer from "components/footer";
import Header from "components/header";
import {
  selectLoginApiCallStatus,
  changeLocalStorageKeyforIdToken,
} from "features/login";
import React, { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import {
  clearToken,
  isAdminUser,
  isApproveTier,
  isStandardUser,
  loadAccessToken,
} from "features/auth";
import { TIERS } from "components/auth/constants";

const AuthPage: React.FC = (): JSX.Element => {
  const { instance } = useMsal();
  const dispatch: AppDispatch = useDispatch();
  const navigate = useNavigate();
  const status = useSelector(selectLoginApiCallStatus);

  // TODO 将来的にトークンの取得処理をoperations.ts側に移動させたい。useEffect内で非同期処理を行いたくない。
  useEffect(() => {
    if (status !== "none") {
      // ログイン処理で、何回か本画面が描画される契機があるが、認証処理は一度だけ実施すればよいため認証処理実行済みであれば何もしない
      return;
    }

    (async () => {
      try {
        // ログイン済みの場合、ログイン後の遷移先を決定する
        if (loadAccessToken()) {
          // 第一～第四階層の管理者はライセンス画面へ遷移
          if (
            isApproveTier([
              TIERS.TIER1,
              TIERS.TIER2,
              TIERS.TIER3,
              TIERS.TIER4,
            ]) &&
            isAdminUser()
          ) {
            navigate("/license");
            return;
          }
          // 第五階層の管理者はユーザー画面へ遷移
          if (isApproveTier([TIERS.TIER5]) && isAdminUser()) {
            navigate("/user");
            return;
          }
          // 一般ユーザーはdictationPageへ遷移
          if (isStandardUser()) {
            navigate("/dictations");
            return;
          }
          // それ以外は認証エラー画面へ遷移
          instance.logoutRedirect({
            postLogoutRedirectUri: "/AuthError",
          });
          clearToken();
          return;
        }
        const loginResult = await instance.handleRedirectPromise();
        if (loginResult && loginResult.account) {
          const { homeAccountId, idTokenClaims } = loginResult.account;
          if (idTokenClaims && idTokenClaims.aud) {
            const localStorageKeyforIdToken = `${homeAccountId}-${
              import.meta.env.VITE_B2C_KNOWNAUTHORITIES
            }-idtoken-${idTokenClaims.aud}----`;

            // AADB2Cログイン画面以外から本画面に遷移した場合用にIDトークン取得用キーをstateに保存
            dispatch(
              changeLocalStorageKeyforIdToken({
                localStorageKeyforIdToken,
              })
            );
          }
        }
        // ログインページに遷移し、トークン取得と設定を行う
        // 何らかの原因で、loginResultがnullの場合でも、ログイン画面に遷移する（ログイン画面でトップページに戻る）
        navigate("/login");
      } catch (e) {
        // eslint-disable-next-line
        console.log({ e }); // TODO:loading画面から遷移できない事象の調査用ログ。事象解消後削除（eslint-disable含めて）する。

        // AAD B2Cの多要素認証画面やパスワードリセット画面で「cancel」をクリックすると、handleRedirectPromise()にてエラーが発生するため、
        // それをハンドリングして適切な画面遷移処理を行う。
        if (e instanceof AuthError) {
          // エラーコードはerrorMessageの中の一部として埋め込まれており完全一致で取得するのは筋が悪いため、部分一致で取得する。
          // TODO 他にもAADB2Cのエラーコードを使用する箇所が出てきた場合、定数化すること
          if (e.errorMessage.startsWith("AADB2C90091")) {
            navigate("/");
          }
        }
      }
    })();
  }, [instance, navigate, status, dispatch]);

  return (
    <>
      <Header />
      <h3>loading ...</h3>
      <Footer />
    </>
  );
};

export default AuthPage;
