import { useMsal } from "@azure/msal-react";
import { AppDispatch } from "app/store";
import { isIdToken } from "common/token";
import {
  clearToken,
  isAdminUser,
  isApproveTier,
  isStandardUser,
  loadAccessToken,
  loadRefreshToken,
} from "features/auth";
import { loginAsync, selectLocalStorageKeyforIdToken } from "features/login";
import React, { useCallback, useEffect } from "react";
import Footer from "components/footer";
import Header from "components/header";
import { useTranslation } from "react-i18next";
import { useDispatch, useSelector } from "react-redux";
import { useNavigate } from "react-router-dom";
import { isErrorObject } from "common/errors";
import { TIERS } from "components/auth/constants";

const LoginPage: React.FC = (): JSX.Element => {
  const { instance } = useMsal();
  const dispatch: AppDispatch = useDispatch();
  const navigate = useNavigate();
  const [, i18n] = useTranslation();
  const localStorageKeyforIdToken = useSelector(
    selectLocalStorageKeyforIdToken
  );

  // ログイン後の遷移先を決定する
  const navigateToLoginedPage = useCallback(() => {
    // 第一～第四階層の管理者はライセンス画面へ遷移
    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();
  }, [instance, navigate]);

  const tokenSet = useCallback(
    async (idToken: string) => {
      // ログイン処理呼び出し
      const { meta, payload } = await dispatch(loginAsync({ idToken }));

      // ログイン失敗した場合、B2Cをログアウトしてからエラーページに遷移する
      if (meta.requestStatus === "rejected") {
        if (isErrorObject(payload)) {
          // 未同意の規約がある場合は利用規約同意画面に遷移する
          if (payload.error.code === "E010209") {
            navigate("/terms");
            return;
          }
        }
        instance.logoutRedirect({
          postLogoutRedirectUri: "/AuthError",
        });
      }
      if (meta.requestStatus === "fulfilled") {
        const accessToken = loadAccessToken();
        const refreshToken = loadRefreshToken();
        const url = `${
          import.meta.env.VITE_DESK_TOP_APP_SCHEME
        }:login?accessToken=${accessToken}&refreshToken=${refreshToken}&language=${
          i18n.language
        }`; // カスタムURLスキーム
        const a = document.createElement("a");
        a.href = url;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);

        // ログイン成功した場合、適切なページに遷移する
        navigateToLoginedPage();
      }
    },
    [dispatch, i18n.language, instance, navigate, navigateToLoginedPage]
  );

  useEffect(() => {
    // idTokenStringがあるか⇒認証中
    // accessTokenがある場合⇒ログイン済み
    // どちらもなければ直打ち
    (async () => {
      if (loadAccessToken()) {
        navigateToLoginedPage();
        return;
      }

      // AADB2Cのログイン画面とLoginPageを経由していない場合はトップページに遷移する
      if (!localStorageKeyforIdToken) {
        navigate("/");
        return;
      }
      const idTokenString = localStorage.getItem(localStorageKeyforIdToken);

      if (idTokenString === null) {
        navigate("/");
        return;
      }

      if (idTokenString) {
        const idTokenObject = JSON.parse(idTokenString);
        if (isIdToken(idTokenObject)) {
          await tokenSet(idTokenObject.secret);
        }
      }
    })();
    // 画面描画後のみ実行するため引数を設定しない
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

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

export default LoginPage;
