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

import type {
  AppRouteRecordRaw,
  ExRouteRecordRaw,
  MenuRecordRaw,
  RouteMeta,
  RouteRecordStringComponent,
} from '../../../@core/base/typings/src';

import {
  filterTree,
  isHttpUrl,
  mapTree,
  sortTree,
} from '../../../@core/base/shared/src/utils';

/**
 * 根据 routes 生成菜单列表
 * @param routes - 路由配置列表
 * @param router - Vue Router 实例
 * @returns 生成的菜单列表
 */
function generateMenus(
  routes: RouteRecordRaw[],
  router: Router,
): MenuRecordRaw[] {
  // 将路由列表转换为一个以 name 为键的对象映射
  const finalRoutesMap: { [key: string]: string } = Object.fromEntries(
    router.getRoutes().map(({ name, path }) => [name, path]),
  );

  let menus = mapTree<ExRouteRecordRaw, MenuRecordRaw>(routes, (route) => {
    // 获取最终的路由路径
    const path = finalRoutesMap[route.name as string] ?? route.path ?? '';

    const {
      meta = {} as RouteMeta,
      name: routeName,
      redirect,
      children = [],
    } = route;
    const {
      activeIcon,
      badge,
      badgeType,
      badgeVariants,
      hideChildrenInMenu = false,
      icon,
      link,
      order,
      title = '',
      query,
    } = meta;

    // 确保菜单名称不为空
    const name = (title || routeName || '') as string;

    // 处理子菜单
    const resultChildren = hideChildrenInMenu
      ? []
      : ((children as MenuRecordRaw[]) ?? []);

    // 设置子菜单的父子关系
    if (resultChildren.length > 0) {
      resultChildren.forEach((child) => {
        child.parents = [...(route.parents ?? []), path];
        child.parent = path;
      });
    }

    // 确定最终路径
    const resultPath = hideChildrenInMenu ? redirect || path : link || path;

    return {
      activeIcon,
      badge,
      badgeType,
      badgeVariants,
      icon,
      name,
      query,
      order,
      parent: route.parent,
      parents: route.parents,
      path: resultPath,
      show: !meta.hideInMenu,
      children: resultChildren,
    };
  });

  // 对菜单进行排序，避免order=0时被替换成999的问题
  menus = sortTree(menus, (a, b) => (a?.order ?? 999) - (b?.order ?? 999));

  // 过滤掉隐藏的菜单项
  return filterTree(menus, (menu) => !!menu.show);
}

/**
 * 转换后端菜单数据为路由数据
 * @param menuList 后端菜单数据
 * @param parent 父级菜单
 * @param nameSet 用于跟踪已使用的 name，防止重复
 * @returns 路由数据
 */
function convertServerMenuToRouteRecordStringComponent(
  menuList: AppRouteRecordRaw[],
  parent = '',
  nameSet: Set<string> = new Set(),
): RouteRecordStringComponent[] {
  const menus: RouteRecordStringComponent[] = [];
  menuList.forEach((menu) => {
    // 处理外链菜单（顶级或子级）
    if (isHttpUrl(menu.path)) {
      // add by 芋艿：如果有 ?_iframe 参数，则作为内嵌页面处理
      // 如果有 _iframe 参数，则使用 iframeSrc；如果没有，则使用 link
      const url = new URL(menu.path);
      let link: string | undefined;
      let iframeSrc: string | undefined;
      if (url.searchParams.has('_iframe')) {
        url.searchParams.delete('_iframe');
        iframeSrc = url.toString();
      } else {
        link = menu.path;
      }

      const urlMenu: RouteRecordStringComponent = {
        component: 'IFrameView',
        meta: {
          hideInMenu: !menu.visible,
          icon: menu.icon,
          iframeSrc,
          link,
          order: menu.sort,
          title: menu.name,
        },
        name: menu.name,
        path: `${menu.id}`,
      };
      menus.push(urlMenu);
      return;
    } else if (menu.children && menu.parentId === 0) {
      menu.component = 'BasicLayout';
    }
    if (menu.component === 'Layout') {
      menu.component = 'BasicLayout';
    }

    if (menu.children && menu.parentId !== 0) {
      menu.component = '';
    }

    // path
    if (parent) {
      menu.path = `${parent}/${menu.path}`;
    }

    if (!menu.path.startsWith('/')) {
      menu.path = `/${menu.path}`;
    }

    // add by 芋艿：防止 name 重复，只有在 name 重复时，才自动添加 id
    let finalName = menu.componentName || menu.name;
    if (nameSet.has(finalName)) {
      finalName = menu.name + menu.id;
      console.error(`menu name duplicate: ${menu.name}, id: ${menu.id}`, menu);
    }
    nameSet.add(finalName);

    // add by 芋艿：处理 menu.component 中的 query 参数
    // https://doc.vben.pro/guide/essentials/route.html#query
    let query: Record<string, string> | undefined;
    // add by 芋艿：防止 component 为 null 时，调用 indexOf 报错；关联
    if (!menu.component) {
      menu.component = '';
    }
    const queryIndex = menu.component.indexOf('?');
    if (queryIndex !== -1) {
      // 提取 query 字符串并解析为对象
      const queryString = menu.component.slice(queryIndex + 1);
      query = Object.fromEntries(new URLSearchParams(queryString).entries());
      // 移除 component 中的 query 部分
      menu.component = menu.component.slice(0, queryIndex);
    }

    const buildMenu: RouteRecordStringComponent = {
      component: menu.component,
      meta: {
        hideInMenu: !menu.visible,
        icon: menu.icon,
        keepAlive: menu.keepAlive,
        order: menu.sort,
        title: menu.name,
        ...(query && { query }),
      },
      name: finalName,
      path: menu.path,
    };

    if (menu.children && menu.children.length > 0) {
      buildMenu.children = convertServerMenuToRouteRecordStringComponent(
        menu.children,
        menu.path,
        nameSet,
      );
    }

    menus.push(buildMenu);
  });
  return menus;
}

export { convertServerMenuToRouteRecordStringComponent, generateMenus };
