import type { RouteRecordRaw, Router } from 'vue-router';

import { nextTick } from 'vue';

import { LOGIN_PATH } from '@vben/constants';
import { preferences } from '@vben/preferences';
import { useAccessStore, useUserStore } from '@vben/stores';
import { startProgress, stopProgress } from '@vben/utils';

import { accessRoutes, coreRouteNames } from '#/router/routes';
import { useAuthStore } from '#/store';

import { generateAccess } from './access';

/**
 * 通用守卫配置
 * @param router
 */
function setupCommonGuard(router: Router) {
  // 记录已经加载的页面
  const loadedPaths = new Set<string>();

  router.beforeEach((to) => {
    to.meta.loaded = loadedPaths.has(to.path);

    // 页面加载进度条
    if (!to.meta.loaded && preferences.transition.progress) {
      startProgress();
    }
    return true;
  });

  router.afterEach((to) => {
    // 记录页面是否加载,如果已经加载，后续的页面切换动画等效果不在重复执行

    loadedPaths.add(to.path);

    // 关闭页面加载进度条
    if (preferences.transition.progress) {
      stopProgress();
    }
  });
}

/**
 * 权限访问守卫配置
 * @param router
 */
function setupAccessGuard(router: Router) {
  router.beforeEach(async (to, from) => {
    const accessStore = useAccessStore();
    const userStore = useUserStore();
    const authStore = useAuthStore();

    // 基本路由，这些路由不需要进入权限拦截
    if (coreRouteNames.includes(to.name as string)) {
      if (to.path === LOGIN_PATH && accessStore.accessToken) {
        const redirectPath = decodeURIComponent(
          (to.query?.redirect as string) ||
            userStore.userInfo?.homePath ||
            '/dashboard/analytics',
        );
        return redirectPath;
      }
      return true;
    }

    // accessToken 检查
    if (!accessStore.accessToken) {
      // 明确声明忽略权限访问权限，则可以访问
      if (to.meta.ignoreAccess) {
        return true;
      }

      // 没有访问权限，跳转登录页面
      if (to.fullPath !== LOGIN_PATH) {
        return {
          path: LOGIN_PATH,
          // 如不需要，直接删除 query
          query:
            to.fullPath === preferences.app.defaultHomePath
              ? {}
              : { redirect: encodeURIComponent(to.fullPath) },
          // 携带当前跳转的页面，登录后重新跳转该页面
          replace: true,
        };
      }
      return to;
    }

    // 是否已经生成过动态路由
    if (accessStore.isAccessChecked) {
      // 即使已经检查过，也需要验证当前路径是否能正确解析
      // 如果路径无法解析（比如直接访问 /admin/dashboard/analytics），需要重新解析
      try {
        const resolved = router.resolve(to.path);
        // 如果路由无法解析或者是 404，尝试重新解析或重定向
        if (!resolved.name || resolved.name === 'FallbackNotFound') {
          // 如果路径包含 /admin 前缀，尝试去掉前缀
          let normalizedPath = to.path;
          if (normalizedPath.startsWith('/admin')) {
            normalizedPath = normalizedPath.replace(/^\/admin/, '');
          }

          // 尝试解析去掉前缀后的路径
          const normalizedResolved = router.resolve(normalizedPath);
          if (normalizedResolved.name && normalizedResolved.name !== 'FallbackNotFound') {
            return {
              ...normalizedResolved,
              replace: true,
            };
          }

          // 如果还是无法解析，尝试解析默认首页
          const defaultResolved = router.resolve('/dashboard/analytics');
          if (defaultResolved.name && defaultResolved.name !== 'FallbackNotFound') {
            return {
              ...defaultResolved,
              replace: true,
            };
          }
        }
      } catch (error) {
        console.error('路由解析失败:', error);
      }
      return true;
    }

    // 生成路由表
    // 当前登录用户拥有的角色标识列表
    const userInfo = userStore.userInfo || (await authStore.fetchUserInfo());
    const userRoles = userInfo?.roles ?? [];

    // 生成菜单和路由
    let accessibleMenus: any[] = [];
    let accessibleRoutes: RouteRecordRaw[] = [];
    try {
      const result = await generateAccess({
        roles: userRoles,
        router,
        // 则会在菜单中显示，但是访问会被重定向到403
        routes: accessRoutes,
      });
      accessibleMenus = result.accessibleMenus;
      accessibleRoutes = result.accessibleRoutes;
    } catch (error) {
      console.error('生成路由失败:', error);
      // 如果生成路由失败，使用静态路由并手动添加到 router
      accessibleRoutes = accessRoutes;
      const root = router.getRoutes().find((item) => item.path === '/');
      if (root) {
        const names = root?.children?.map((item) => item.name) ?? [];
        accessibleRoutes.forEach((route) => {
          if (root && !route.meta?.noBasicLayout) {
            if (route.children && route.children.length > 0) {
              delete route.component;
            }
            if (!names?.includes(route.name)) {
              root.children?.push(route);
            }
          } else {
            router.addRoute(route);
          }
        });
        if (root.name) {
          router.removeRoute(root.name);
        }
        router.addRoute(root);
      }
      accessibleMenus = [];
    }

    // 保存菜单信息和路由信息
    accessStore.setAccessMenus(accessibleMenus);
    accessStore.setAccessRoutes(accessibleRoutes);

    accessStore.setIsAccessChecked(true);

    // 等待路由添加到 router 中
    await nextTick();

    // 确定跳转路径
    let redirectPath: string;
    // 优先使用 to.query.redirect（从登录页跳转过来）
    if (to.query?.redirect) {
      redirectPath = decodeURIComponent(to.query.redirect as string);
    } else if (from.query?.redirect) {
      redirectPath = decodeURIComponent(from.query.redirect as string);
    } else if (to.path === '/dashboard/analytics' || to.path === preferences.app.defaultHomePath || to.path === '/') {
      redirectPath = userInfo?.homePath || '/dashboard/analytics';
    } else {
      redirectPath = to.fullPath;
    }

    // 尝试解析路由
    try {
      const resolved = router.resolve(redirectPath);
      // 检查路由是否存在（有 name 或者匹配到了路由）
      if (resolved.name && resolved.name !== 'FallbackNotFound') {
        return {
          ...resolved,
          replace: true,
        };
      }
      // 如果解析的路由是404，说明路由不存在，尝试查找默认首页
      if (resolved.name === 'FallbackNotFound') {
        // 尝试解析默认首页
        const defaultResolved = router.resolve('/dashboard/analytics');
        if (defaultResolved.name && defaultResolved.name !== 'FallbackNotFound') {
          return {
            ...defaultResolved,
            replace: true,
          };
        }
      }
    } catch (error) {
      console.error('路由解析失败:', error);
    }

    // 如果解析失败，尝试通过路由名称查找
    // 查找 Analytics 路由（dashboard/analytics 的路由名称）
    const analyticsRoute = router.getRoutes().find(
      (route) => route.name === 'Analytics' || route.path === '/dashboard/analytics',
    );
    if (analyticsRoute) {
      return {
        name: analyticsRoute.name || undefined,
        path: analyticsRoute.path,
        replace: true,
      };
    }

    // 如果还是找不到，跳转到默认首页路径
    return {
      path: '/dashboard/analytics',
      replace: true,
    };
  });
}

/**
 * 项目守卫配置
 * @param router
 */
function createRouterGuard(router: Router) {
  /** 通用 */
  setupCommonGuard(router);
  /** 权限访问 */
  setupAccessGuard(router);
}

export { createRouterGuard };
