import type { RouteRecordRaw } from 'vue-router'
import type { MenuItem } from '@/types/menu'

// Vite glob 懒加载所有视图组件
// 此文件位于 src/utils/，所以 ../views 指向 src/views
const viewModules = import.meta.glob('../views/**/*.vue')

/**
 * 根据字符串路径懒加载 Vue 组件
 * @param componentPath - 如 'dashboard/index' 或 'sdk/detail'
 */
export function loadComponent(componentPath?: string): () => Promise<unknown> {
  if (!componentPath) {
    console.warn('[路由] componentPath 为空')
    return () => import('../views/error/404.vue')
  }

  const key = `../views/${componentPath}.vue`

  if (viewModules[key]) {
    return viewModules[key] as () => Promise<unknown>
  }

  console.warn(`[路由] 未找到组件: ${key}`)
  return () => import('../views/error/404.vue')
}

/**
 * 路径拼接（兼容绝对路径与相对路径）
 */
export function resolvePath(basePath: string, routePath: string): string {
  if (!routePath) return basePath || '/'
  if (routePath.startsWith('/')) return routePath
  const full = `${basePath}/${routePath}`.replace(/\/+/g, '/')
  return full === '' ? '/' : full
}

/**
 * 判断菜单项是否隐藏
 */
function isHidden(item: MenuItem): boolean {
  return !!item.meta?.hidden
}

/**
 * 将菜单树转换为 Vue Router 路由
 * 规则：
 * 1. 顶层菜单作为父路由
 * 2. hidden 子菜单仍然生成路由，但不显示在侧边栏
 * 3. 父路由如果有 visible 子路由，则可配置 redirect
 * 4. 路由默认都挂载在根下（适合 Layout + router-view）
 */
export function flattenMenuToRoutes(menuItems: MenuItem[], parentPath = ''): RouteRecordRaw[] {
  const routes: RouteRecordRaw[] = []

  for (const item of menuItems) {
    // ★ 按钮不生成路由，直接跳过
    if (item.type === 2) continue

    const fullPath = resolvePath(parentPath, item.path)
    const children = (item.children || []).filter((c) => c.type !== 2) // 排除按钮子项

    const visibleChildren = children.filter((child) => !isHidden(child))
    const hiddenChildren = children.filter((child) => isHidden(child))

    // 1) 当前菜单本身生成路由
    // 如果有 component，说明它是一个可访问页面
    if (item.component) {
      routes.push({
        path: fullPath,
        name: item.name,
        component: loadComponent(item.component),
        meta: item.meta,
      } as RouteRecordRaw)
    }

    // 2) 处理子菜单
    // visible 子菜单：正常递归
    if (visibleChildren.length > 0) {
      // 如果父级没有 component，但有可见子路由，可以给父级加 redirect
      // 例如 /sdk -> /sdk/list
      if (!item.component) {
        routes.push({
          path: fullPath,
          redirect: item.redirect || resolvePath(fullPath, visibleChildren[0].path),
          meta: item.meta,
        } as RouteRecordRaw)
      }

      routes.push(...flattenMenuToRoutes(visibleChildren, fullPath))
    }

    // 3) hidden 子菜单：也要生成路由，但不递归进菜单树
    // 因为它们不显示在侧边栏，但需要能直接访问
    for (const child of hiddenChildren) {
      const childFullPath = resolvePath(fullPath, child.path)

      routes.push({
        path: childFullPath,
        name: child.name,
        component: loadComponent(child.component),
        meta: {
          ...child.meta,
          parentPath: fullPath,
          parentTitle: item.meta?.title,
        },
      } as RouteRecordRaw)
    }
  }

  return routes
}
