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

import type {
  AuthorityDataList,
  ComponentRecordType,
  GenerateMenuAndRoutesOptions,
  RouteMeta,
  RouteRecordStringComponent,
} from '@vben-core/typings';

import { mapTree } from '@vben-core/shared/utils';

/**
 * 动态生成路由 - 后端方式
 */
async function generateRoutesByBackend(
  options: GenerateMenuAndRoutesOptions,
): Promise<RouteRecordRaw[]> {
  const {
    fetchMenuListAsync,
    layoutMap = {},
    pageMap = {},
    routes: dynamicRoutes,
  } = options;

  try {
    const menuRoutes = await fetchMenuListAsync?.();
    // console.log('menuRoutes:', menuRoutes);
    // [{
    //   "menu_id": 1,
    //   "menu_name": "systemManage",
    //   "menu_key": "_systemManage",
    //   "component": "/layout",
    //   "active_menu": null,
    //   "parent_id": 0,
    //   "order_num": 99,
    //   "menu_type": 1,
    //   "visible": 0,
    //   "perms": null,
    //   "icon": "ii-system",
    //   "path": "/systemmanage",
    //   "redirect": null,
    //   "hidden_header": 0,
    //   "remark": "系统管理",
    //   "no_cache": 0,
    //   "api_parameter": null,
    //   "api_url": null
    // },]
    if (!menuRoutes) {
      return [];
    }

    const normalizePageMap: ComponentRecordType = {};

    for (const [key, value] of Object.entries(pageMap)) {
      normalizePageMap[normalizeViewPath(key)] = value;
    }

    // 转换接口权限数据
    const processMenuRoutes = processMenuData(
      menuRoutes as AuthorityDataList[],
    );

    const routes = convertRoutes(
      processMenuRoutes as unknown as RouteRecordStringComponent[],
      layoutMap,
      normalizePageMap,
    );

    // console.log('menuRoutes:', menuRoutes);
    // console.log('processMenuRoutes:', processMenuRoutes);

    // 合并动态路由和后端路由
    const finalRoutes = [...dynamicRoutes, ...routes];
    // console.log('finalRoutes:', finalRoutes);

    return finalRoutes;
  } catch (error) {
    console.error(error);
    throw error;
  }
}

function convertRoutes(
  routes: RouteRecordStringComponent[],
  layoutMap: ComponentRecordType,
  pageMap: ComponentRecordType,
): RouteRecordRaw[] {
  return mapTree(routes, (node) => {
    const route = node as unknown as RouteRecordRaw;
    const { component, name } = node;

    if (!name) {
      console.error('route name is required', route);
    }

    // layout转换
    if (component && layoutMap[component]) {
      route.component = layoutMap[component];
      // 页面组件转换
    } else if (component) {
      const normalizePath = normalizeViewPath(component);
      const pageKey = normalizePath.endsWith('.vue')
        ? normalizePath
        : `${normalizePath}.vue`;
      if (pageMap[pageKey]) {
        route.component = pageMap[pageKey];
      } else {
        console.error(`route component is invalid: ${pageKey}`, route);
        route.component = pageMap['/_core/fallback/not-found.vue'];
      }
    }

    return route;
  });
}

function normalizeViewPath(path: string): string {
  // 去除相对路径前缀
  const normalizedPath = path.replace(/^(\.\/|\.\.\/)+/, '');

  // 确保路径以 '/' 开头
  const viewPath = normalizedPath.startsWith('/')
    ? normalizedPath
    : `/${normalizedPath}`;

  // 这里耦合了vben-admin的目录结构
  return viewPath.replace(/^\/views/, '');
}

/**
 * 菜单类型枚举
 */
const MenuType = {
  /** 目录 */
  DIRECTORY: 1,
  /** 菜单 */
  MENU: 2,
  /** 按钮 */
  BUTTON: 3,
  /** API接口 */
  API: 4,
} as const;

/**
 * 处理接口返回的权限数据
 * 1.分离按钮和菜单权限；
 * 2.将按钮生成权限组，存入store中
 * 3.将数据库字段转为系统所用字段，并递归生成菜单树
 */

function processMenuData(routes: AuthorityDataList[]) {
  // 使用语义化的枚举值过滤按钮类型
  // const buttonTempArr = routes.filter(
  //   (item) => item.menu_type === MenuType.BUTTON,
  // );

  const menuTempArr = routes.filter((item) =>
    [MenuType.DIRECTORY, MenuType.MENU].includes(item.menu_type),
  );

  // const apiTempArr = routes.filter((item) => item.menu_type === MenuType.API);

  const menuTree = convertToTree(menuTempArr);

  // console.log('api list:', apiTempArr);
  // console.log('button list:', buttonTempArr);
  // console.log('menu list:', menuTempArr);
  // console.log('menu tree:', menuTree);

  return menuTree;
}

// 转换为菜单结构
function convertToTree(routes: AuthorityDataList[]) {
  const tree: AuthorityDataList[] = [];
  const map = new Map();

  routes.forEach((route) => {
    map.set(route.menu_id, { ...route, children: [] });
  });

  // 根据parent_id 递归生成路由树
  routes.forEach((route) => {
    const node = map.get(route.menu_id);
    if (route.parent_id === 0) {
      // 顶级节点直接加入tree
      tree.push(node);
    } else {
      // 非顶级节点加入到父节点的children中
      const parent = map.get(route.parent_id);
      if (parent) {
        parent.children.push(node);
      }
    }
  });

  // 递归排序
  function sortTree(nodes: AuthorityDataList[]) {
    return nodes
      .sort((a, b) => a.order_num - b.order_num)
      .map((node) => {
        if (node.children && node.children.length > 0) {
          node.children = sortTree(node.children);
        }
        return node;
      });
  }

  const sortedTree = sortTree(tree);

  interface RouteItem {
    children?: RouteItem[];
    component?: string;
    meta: RouteMeta;
    parent?: string; // 当前菜单的直接父级路径
    parents?: string[]; // 当前菜单的所有父级路径
    name: string; // 菜单名称
    path: string; // 菜单路径
  }

  // 递归生成路由树
  function generateRoutes(nodes: AuthorityDataList[]): RouteItem[] {
    return nodes.map((node) => {
      const route: RouteItem = {
        path: node.path,
        name: node.menu_key,
        component: node.component,
        meta: {
          title: node.menu_key,
          icon: node.icon,
          hideInMenu: node.visible === 1,
          keepAlive: node.no_cache === 0,
          hideInBreadcrumb: node.hidden_header === 1,
          hideInTab: node.hidden_header === 1,
          // affixTab: node.affix_tab === 1,
          // affixTabOrder: node.affix_tab_order,
          // maxNumOfOpenTab: node.max_num_of_open_tab,
          // menuVisibleWithForbidden: node.menu_visible_with_forbidden === 1,
          // noBasicLayout: node.no_basic_layout === 1,
          // openInNewWindow: node.open_in_new_window === 1,
          order: node.order_num,
          query: node.api_parameter,
          // redirect: node.redirect,
          authority: node.perms ? node.perms.split(',') : [],
          // hideChildrenInMenu: node.visible === 1,
        },
      };

      // 处理直接父级路径
      const parent =
        node.parent_id === 0
          ? null
          : routes.find((n) => n.menu_id === node.parent_id)?.path || '';

      if (parent) route.parent = parent;

      // 递归处理子节点
      if (node.children?.length) {
        route.children = generateRoutes(node.children);
      }

      return route;
    });
  }
  const treeRoutes = generateRoutes(sortedTree);

  // 递归处理父级路径 parents
  function handleParentPaths(routes: RouteItem[]) {
    // 扁平化所有路由，包括子路由
    function flattenRoutes(items: RouteItem[]): RouteItem[] {
      const result: RouteItem[] = [];
      for (const item of items) {
        result.push(item);
        if (item.children && item.children.length > 0) {
          result.push(...flattenRoutes(item.children));
        }
      }
      return result;
    }

    // 标准化路径格式
    function normalizePath(path: string): string {
      return path.startsWith('/') ? path : `/${path}`;
    }

    // 获取所有父级路径
    function getAllParentPaths(
      route: RouteItem,
      allRoutes: RouteItem[],
    ): string[] {
      const parentPaths: string[] = [];
      const visitedPaths = new Set<string>();
      let currentPath = route.parent ? normalizePath(route.parent) : null;

      while (currentPath && !visitedPaths.has(currentPath)) {
        visitedPaths.add(currentPath);
        parentPaths.unshift(currentPath);
        const parentRoute = allRoutes.find(
          (r) => normalizePath(r.path) === currentPath,
        );
        currentPath = parentRoute?.parent
          ? normalizePath(parentRoute.parent)
          : null;
      }

      return parentPaths;
    }

    // 一次性扁平化所有路由
    const allFlattenedRoutes = flattenRoutes(routes);

    function processRoutes(routesToProcess: RouteItem[]): RouteItem[] {
      return routesToProcess.map((route) => {
        const newRoute = { ...route };

        if (newRoute.parent) {
          newRoute.parent = normalizePath(newRoute.parent);
          newRoute.parents = getAllParentPaths(newRoute, allFlattenedRoutes);
        }
        // 递归处理子路由，但使用同一个扁平化路由数组
        if (newRoute.children && newRoute.children.length > 0) {
          newRoute.children = processRoutes(newRoute.children);
        }

        return newRoute;
      });
    }

    return processRoutes(routes);
  }

  const handledTreeRoutes = handleParentPaths(treeRoutes);

  return handledTreeRoutes;
}

export { generateRoutesByBackend };
