/**
 * @description 动态路由生成器
 * @author yslg
 * @since 2025-10-07
 */

import type { RouteRecordRaw } from 'vue-router';
import type { SysMenu } from '@/types';
import { MenuType } from '@/types/enums';
import { routes } from '@/router';

/**
 * 布局组件映射
 */
const LAYOUT_MAP: Record<string, () => Promise<any>> = {
  // 基础布局（旧版，带侧边栏）
  'BasicLayout': () => import('@/layouts/BasicLayout.vue'),
  // 导航布局（新版，顶部导航+动态侧边栏）
  'NavigationLayout': () => import('@/layouts/NavigationLayout.vue'),
  // 空白布局
  'BlankLayout': () => import('@/layouts/BlankLayout.vue'),
  // 页面布局
  'PageLayout': () => import('@/layouts/PageLayout.vue'),
};

/**
 * 根据菜单生成路由配置
 * @param menus 用户菜单列表
 * @returns Vue Router路由配置数组
 */
export function generateRoutes(menus: SysMenu[]): RouteRecordRaw[] {
  if (!menus || menus.length === 0) {
    return [];
  }
  
  const routes: RouteRecordRaw[] = [];
  const pageRoutes: RouteRecordRaw[] = [];
  
  // 构建菜单树
  const menuTree = buildMenuTree(menus);
  
  // 生成路由
  menuTree.forEach(menu => {
    const route = generateRouteFromMenu(menu);
    
    if (route) {
      routes.push(route);
      
      // 递归提取所有 PAGE 类型的子菜单
      extractPageChildren(route, pageRoutes);
    }
  });
  
  // 将 PAGE 类型的路由添加到路由列表
  routes.push(...pageRoutes);
  
  return routes;
}

/**
 * 递归提取路由中的 PAGE 类型子菜单
 */
function extractPageChildren(route: any, pageRoutes: RouteRecordRaw[]) {
  // 检查当前路由是否有 PAGE 类型的子菜单
  if (route.meta?.pageChildren && Array.isArray(route.meta.pageChildren)) {
    route.meta.pageChildren.forEach((pageMenu: SysMenu) => {
      const pageRoute = generateRouteFromMenu(pageMenu, true); // 作为顶层路由生成
      if (pageRoute) {

        pageRoutes.push(pageRoute);
      } else {
        console.error(`[路由生成] 生成独立PAGE路由失败: ${pageMenu.name}`);
      }
    });
    // 清理临时数据
    delete route.meta.pageChildren;
  }
  
  // 递归检查子路由
  if (route.children && Array.isArray(route.children)) {
    route.children.forEach((childRoute: any) => {
      extractPageChildren(childRoute, pageRoutes);
    });
  }
}

/**
 * 根据单个菜单生成路由
 * @param menu 菜单对象
 * @param isTopLevel 是否是顶层菜单
 * @returns 路由配置
 */
function generateRouteFromMenu(menu: SysMenu, isTopLevel = true): RouteRecordRaw | null {
  // 跳过按钮类型
  if (menu.type === MenuType.BUTTON) {
    return null;
  }
  
  // 跳过静态路由（已经在 router 中定义，不需要再次添加）
  if (menu.component === '__STATIC_ROUTE__') {
    return null;
  }
  
  const route: any = {
    path: menu.url || `/${menu.menuID}`,
    name: menu.menuID,
    meta: {
      title: menu.name,
      icon: menu.icon,
      menuId: menu.menuID,
      parentId: menu.parentID,
      orderNum: menu.orderNum,
      type: menu.type,
      hideInMenu: false,
      requiresAuth: true,
    }
  };
  
  // 检查是否指定了布局（只有顶层菜单才使用布局）
  const layout = isTopLevel ? (menu as any).layout : null;
  const hasChildren = menu.children && menu.children.length > 0;
  
  // 确定路由组件
  if (layout && LAYOUT_MAP[layout]) {
    // 如果指定了布局，使用指定的布局
    route.component = getComponent(layout);
  } else if (hasChildren && isTopLevel) {
    // 如果有子菜单但没有指定布局，根据菜单类型选择默认布局
    if (isTopLevel && menu.type === MenuType.NAVIGATION) {
      route.component = getComponent('NavigationLayout');
    } else if (menu.type === MenuType.SIDEBAR) {
      route.component = getComponent('BlankLayout');
    } else {
      route.component = getComponent('BasicLayout');
    }
  } else {
    // 没有子菜单，也没有指定布局，使用具体的页面组件
    if (menu.component) {
      route.component = getComponent(menu.component);
    } else {
      // 非顶层菜单没有组件时，使用简单的占位组件
      route.component = getComponent('BlankLayout');
    }
  }
  
  // 处理子路由
  if (layout && LAYOUT_MAP[layout] && !hasChildren && menu.component && isTopLevel) {
    // 如果指定了布局但没有子菜单，将页面组件作为子路由
    route.children = [{
      path: '',
      name: `${menu.menuID}_page`,
      component: getComponent(menu.component),
      meta: route.meta
    }];
  } else if (hasChildren) {
    // 处理有子菜单的情况
    route.children = [];
    
    // 分离 PAGE 类型的子菜单和普通子菜单
    const pageChildren: SysMenu[] = [];
    const normalChildren: SysMenu[] = [];
    
    menu.children!.forEach(child => {
      if (child.type === MenuType.PAGE) {
        // PAGE 类型的菜单作为独立路由，不作为子路由
        pageChildren.push(child);
      } else {
        normalChildren.push(child);
      }
    });
    
    // 只将普通子菜单加入 children
    normalChildren.forEach(child => {
      const childRoute = generateRouteFromMenu(child, false);
      if (childRoute) {
        route.children!.push(childRoute);
      }
    });
    
    // PAGE 类型的菜单需要在外层单独处理（不管是哪一层的菜单）
    if (pageChildren.length > 0) {
      // 将 PAGE 类型的子菜单保存到路由的 meta 中，稍后在外层生成
      route.meta.pageChildren = pageChildren;
    }
    
    // 如果没有设置重定向，自动重定向到第一个有URL的子菜单
    if (!route.redirect && route.children.length > 0) {
      const firstChildWithUrl = findFirstMenuWithUrl(normalChildren);
      if (firstChildWithUrl?.url) {
        route.redirect = firstChildWithUrl.url;
      }
    }
  }

  return route;
}

/**
 * 查找第一个有URL的菜单
 * @param menus 菜单列表
 * @returns 第一个有URL的菜单
 */
function findFirstMenuWithUrl(menus: SysMenu[]): SysMenu | null {
  for (const menu of menus) {
    if (menu.type !== MenuType.BUTTON) {
      if (menu.url) {
        return menu;
      }
      if (menu.children && menu.children.length > 0) {
        const found = findFirstMenuWithUrl(menu.children);
        if (found) return found;
      }
    }
  }
  return null;
}

/**
 * 根据组件名称获取组件
 * @param componentName 组件名称/路径
 * @returns 组件异步加载函数
 */
function getComponent(componentName: string) {
  // 检查是否是布局组件
  if (LAYOUT_MAP[componentName]) {
    return LAYOUT_MAP[componentName];
  }
  
  // 处理页面组件路径
  let componentPath = componentName;
  
  // 如果不是以@/开头的完整路径，则添加@/views/前缀
  if (!componentPath.startsWith('@/')) {
    // 确保路径以/开头
    if (!componentPath.startsWith('/')) {
      componentPath = '/' + componentPath;
    }
    // 添加@/views前缀
    componentPath = '@/views' + componentPath;
  }
  
  // 将@/别名转换为相对路径，因为Vite动态导入可能无法正确解析别名
  if (componentPath.startsWith('@/')) {
    componentPath = componentPath.replace('@/', '../');
  }
  
  // 如果没有.vue扩展名，添加它
  if (!componentPath.endsWith('.vue')) {
    componentPath += '.vue';
  }
  
  
  // 动态导入组件
  return () => {
    return import(/* @vite-ignore */ componentPath)
      .then(module => {
        return module;
      })
      .catch(error => {
        // 返回404组件
        return import('@/views/error/404.vue').catch(() => 
          Promise.resolve({ 
            template: `<div class="component-error">
              <h3>组件加载失败</h3>
              <p>无法加载组件: ${componentPath}</p>
              <p>原始组件名: ${componentName}</p>
              <p>错误: ${error instanceof Error ? error.message : String(error)}</p>
            </div>`,
            style: `
              .component-error {
                padding: 20px;
                text-align: center;
                color: #f56565;
                background: #fed7d7;
                border-radius: 4px;
              }
            `
          })
        );
      });
  };
}

/**
 * 将静态路由转换为菜单项
 * @param routes 静态路由数组
 * @returns 菜单项数组
 */
function convertRoutesToMenus(routes: RouteRecordRaw[]): SysMenu[] {
  const menus: SysMenu[] = [];
  
  routes.forEach(route => {
    // 处理有子路由的情况（现在静态路由都有布局组件）
    if (route.children && route.children.length > 0) {
      route.children.forEach(child => {
        // 只处理有 meta.menuType 的子路由
        if (child.meta?.menuType !== undefined) {
          const menu: SysMenu = {
            menuID: child.name as string || child.path.replace(/\//g, '-'),
            parentID: '0',
            name: child.meta.title as string || child.name as string,
            url: route.path, // 使用父路由的路径
            type: child.meta.menuType as MenuType,
            orderNum: (child.meta.orderNum as number) || -1,
            // 标记为静态路由，避免重复生成路由
            component: '__STATIC_ROUTE__', // 特殊标记
          };
          
          menus.push(menu);
        }
      });
    }
    // 处理没有子路由的情况（兼容性保留）
    else if (route.meta?.menuType !== undefined) {
      const menu: SysMenu = {
        menuID: route.name as string || route.path.replace(/\//g, '-'),
        parentID: '0',
        name: route.meta.title as string || route.name as string,
        url: route.path,
        type: route.meta.menuType as MenuType,
        orderNum: (route.meta.orderNum as number) || -1,
        // 标记为静态路由，避免重复生成路由
        component: '__STATIC_ROUTE__', // 特殊标记
      };
      
      menus.push(menu);
    }
  });
  
  return menus;
}

/**
 * 构建菜单树结构
 * @param menus 菜单列表
 * @returns 菜单树
 */
export function buildMenuTree(menus: SysMenu[]): SysMenu[] {
  // 将静态路由转换为菜单项
  const staticMenus = convertRoutesToMenus(routes);
  
  // 合并动态菜单和静态菜单
  const allMenus = [...staticMenus, ...menus];

  if (allMenus.length === 0) {
    return [];
  }
  
  const menuMap = new Map<string, SysMenu>();
  const rootMenus: SysMenu[] = [];
  const maxDepth = allMenus.length; // 最多遍历len层
  
  // 创建菜单映射
  allMenus.forEach(menu => {
    if (menu.menuID) {
      menuMap.set(menu.menuID, { ...menu, children: [] });
    }
  });
  
  // 循环构建树结构，最多遍历maxDepth次
  for (let depth = 0; depth < maxDepth; depth++) {
    let hasChanges = false;
    
    allMenus.forEach(menu => {
      if (!menu.menuID) return;
      
      const menuNode = menuMap.get(menu.menuID);
      if (!menuNode) return;
      
      // 如果节点已经在树中，跳过
      if (isNodeInTree(menuNode, rootMenus)) {
        return;
      }
      
      if (!menu.parentID || menu.parentID === '0' || menu.parentID === '') {
        // 根菜单
        if (!isNodeInTree(menuNode, rootMenus)) {
          rootMenus.push(menuNode);
          hasChanges = true;
        }
      } else {
        // 子菜单
        const parent = menuMap.get(menu.parentID);
        if (parent && isNodeInTree(parent, rootMenus)) {
          if (!parent.children) {
            parent.children = [];
          }
          if (!parent.children.includes(menuNode)) {
            parent.children.push(menuNode);
            hasChanges = true;
          }
        }
      }
    });
    
    // 如果没有变化，说明树构建完成
    if (!hasChanges) {
      break;
    }
  }
  
  // 按orderNum排序
  const sortMenus = (menus: SysMenu[]): SysMenu[] => {
    return menus
      .sort((a, b) => (a.orderNum || 0) - (b.orderNum || 0))
      .map(menu => ({
        ...menu,
        children: menu.children ? sortMenus(menu.children) : []
      }));
  };
  
  return sortMenus(rootMenus);
}

// 检查节点是否已经在树中
function isNodeInTree(node: SysMenu, tree: SysMenu[]): boolean {
  for (const treeNode of tree) {
    if (treeNode.menuID === node.menuID) {
      return true;
    }
    if (treeNode.children && isNodeInTree(node, treeNode.children)) {
      return true;
    }
  }
  return false;
}

/**
 * 根据权限过滤菜单
 * @param menus 菜单列表
 * @param permissions 用户权限列表
 * @returns 过滤后的菜单列表
 */
export function filterMenusByPermissions(
  menus: SysMenu[], 
  permissions: string[]
): SysMenu[] {
  if (!menus || menus.length === 0) {
    return [];
  }
  
  return menus
    .filter(() => {
      // 如果菜单没有设置权限要求，则默认显示
      // 这里可以根据实际业务需求调整权限检查逻辑
      return true; // 暂时返回true，后续可以根据菜单的权限字段进行过滤
    })
    .map(menu => {
      if (menu.children && menu.children.length > 0) {
        return {
          ...menu,
          children: filterMenusByPermissions(menu.children, permissions)
        };
      }
      return menu;
    });
}

/**
 * 查找路由路径对应的菜单
 * @param menus 菜单树
 * @param path 路由路径
 * @returns 匹配的菜单
 */
export function findMenuByPath(menus: SysMenu[], path: string): SysMenu | null {
  for (const menu of menus) {
    if (menu.url === path) {
      return menu;
    }
    
    if (menu.children && menu.children.length > 0) {
      const found = findMenuByPath(menu.children, path);
      if (found) {
        return found;
      }
    }
  }
  
  return null;
}

/**
 * 获取菜单路径数组（面包屑导航用）
 * @param menus 菜单树
 * @param targetMenuId 目标菜单ID
 * @returns 菜单路径数组
 */
export function getMenuPath(menus: SysMenu[], targetMenuId: string): SysMenu[] {
  const path: SysMenu[] = [];
  
  function findPath(menuList: SysMenu[]): boolean {
    for (const menu of menuList) {
      path.push(menu);
      
      if (menu.menuID === targetMenuId) {
        return true;
      }
      
      if (menu.children && menu.children.length > 0) {
        if (findPath(menu.children)) {
          return true;
        }
      }
      
      path.pop();
    }
    
    return false;
  }
  
  findPath(menus);
  return path;
}

/**
 * 获取第一个可访问的菜单URL（用于登录后跳转）
 * @param menus 菜单树
 * @returns 第一个可访问的菜单URL，如果没有则返回 null
 */
export function getFirstAccessibleMenuUrl(menus: SysMenu[]): string | null {
  if (!menus || menus.length === 0) {
    return null;
  }
  
  return "/home";
}
