import $cache from '@/plugins/cache';
import { to as tos } from 'await-to-js';
import router from './router';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';
import { getToken } from '@/utils/auth';
import { isHttp, isPathMatch } from '@/utils/validate';
import { isRelogin } from '@/utils/request';
import useUserStore from '@/store/modules/user';
import { useSettingsStore } from '@/store/modules/settings';
import usePermissionStore from '@/store/modules/permission';

let isFirst = false;

NProgress.configure({ showSpinner: false });
const whiteList = ['/login', '/register', '/social-callback', '/register*', '/register/*'];

const isWhiteList = (path: string) => {
  return whiteList.some((pattern) => isPathMatch(pattern, path));
};

router.beforeEach(async (to, from) => {
  NProgress.start();

  // 已登录
  if (getToken()) {
    if (to.meta.title) useSettingsStore().setTitle(to.meta.title);

    if (to.path === '/login') {
      NProgress.done();
      return { path: '/' };
    }

    if (isWhiteList(to.path)) {
      return true;
    }
    if ((!isFirst && useUserStore().roles.length === 0) || $cache.local.getJSON('isCheckRole') === 'true') {
      isFirst = true;
      isRelogin.show = true;

      const [err] = await tos(useUserStore().getInfo());

      if (err) {
        await useUserStore().logout();
        ElMessage.error(err);
        NProgress.done();
        return { path: '/' };
      }

      isRelogin.show = false;
      const accessRoutes = await usePermissionStore().generateRoutes();
      accessRoutes.forEach((route) => {
        if (!isHttp(route.path)) router.addRoute(route);
      });

      $cache.local.remove('isCheckRole');

      // 确保路由已添加后再跳转
      return { ...to, replace: true };
    }

    return true;
  } else {
    isFirst = false;
  }

  // 未登录
  if (isWhiteList(to.path)) {
    return true;
  }

  const redirect = encodeURIComponent(to.fullPath || '/');
  NProgress.done();
  return { path: `/login?redirect=${redirect}` };
});

router.afterEach(() => {
  NProgress.done();
});
