import { createRouter, createWebHashHistory } from 'vue-router'
import type {
  Router,
  RouteLocationNormalized,
  RouteRecordNormalized,
  RouteRecordRaw
} from 'vue-router'
import { isUrl } from '@/utils/is'
import { omit, cloneDeep, find } from 'lodash-es'

/* Layout */
export const Layout = () => import('@/layout/Layout.vue')

export const getParentLayout = () => {
  return () =>
    new Promise((resolve) => {
      resolve({
        name: 'ParentLayout'
      })
    })
}

export const getRawRoute = (route: RouteLocationNormalized): RouteLocationNormalized => {
  if (!route) return route
  const { matched, ...opt } = route
  return {
    ...opt,
    matched: (matched
      ? matched.map((item) => ({
          meta: item.meta,
          name: item.name,
          path: item.path
        }))
      : undefined) as RouteRecordNormalized[]
  }
}

// 前端控制路由生成
export const generateRoutesByFrontEnd = (
  routes: AppRouteRecordRaw[],
  keys: string[],
  basePath = '/'
): AppRouteRecordRaw[] => {
  const res: AppRouteRecordRaw[] = []

  for (const route of routes) {
    const meta = route.meta ?? {}
    // skip some route
    if (meta.hidden && !meta.canTo) {
      continue
    }

    let data: Nullable<AppRouteRecordRaw> = null

    let onlyOneChild: Nullable<string> = null
    if (route.children && route.children.length === 1 && !meta.alwaysShow) {
      onlyOneChild = (
        isUrl(route.children[0].path)
          ? route.children[0].path
          : pathResolve(pathResolve(basePath, route.path), route.children[0].path)
      ) as string
    }

    // 开发者可以根据实际情况进行扩展
    for (const item of keys) {
      // 通过路径去匹配
      if (isUrl(item) && (onlyOneChild === item || route.path === item)) {
        data = Object.assign({}, route)
      } else {
        const routePath = (onlyOneChild ?? pathResolve(basePath, route.path)).trim()
        if (routePath === item || meta.followRoute === item) {
          data = Object.assign({}, route)
        }
      }
    }

    // recursive child routes
    if (route.children && data) {
      data.children = generateRoutesByFrontEnd(
        route.children,
        keys,
        pathResolve(basePath, data.path)
      )
    }
    if (data) {
      res.push(data as AppRouteRecordRaw)
    }
  }
  return res
}

// 后端控制路由生成
export const generateRoutesByServer = (allRoutes: AppRouteRecordRaw[], customRoutes: AppCustomRouteRecordRaw[], parentRoute?: AppCustomRouteRecordRaw): AppRouteRecordRaw[] => {
  const res: AppRouteRecordRaw[] = []
  customRoutes.sort((a:AppCustomRouteRecordRaw, b:AppCustomRouteRecordRaw) => {
    return a?.props?.sort && b?.props?.sort ? a.props.sort - b.props.sort : 0
  })

  for (const route of customRoutes) {
    const { props, nodeName } = route
    const { routeName, url = '', icon, permission = '' } = props;

    // 权限
    let _permission = permission;
    if(permission&& typeof permission === 'string') {
      if((permission as any).includes('[')){ // 字符串数组
        _permission = JSON.parse(permission);
      } else { // 逗号分割的字符串
        _permission = (permission as any).split(',');
      }
    }

    // 路由
    let match: boolean = false;
    if (routeName) {
      const matchRoute = find(allRoutes, { name: routeName }) || find(allRoutes, { menuId: routeName })
      if (matchRoute) {
        match = true
        // 没有父级 & 没有子级
        if (!parentRoute && !route?.childs?.length) {
          // 通用节点
          const data2: AppRouteRecordRaw =  {
            path: urlPathResolve(matchRoute.path),
            component: Layout,
            name: `${matchRoute.name}PName`,
            meta: {},
            children: [
              {
                path: 'index',
                component: matchRoute.component,
                name: matchRoute.name,
                meta: {
                  title: nodeName ?? matchRoute?.meta?.title,
                  icon: icon ?? matchRoute?.meta?.icon,
                  permission: _permission,
                  type:matchRoute?.meta?.type,
                  sort:matchRoute?.meta?.sort,
                }
              }
            ]
          }
          res.push(data2 as AppRouteRecordRaw)
        } else {
          // 通用节点
          const data: AppRouteRecordRaw = {
            path: matchRoute.path,
            component: matchRoute.component,
            name: matchRoute.name,
            meta: {
              title: nodeName ?? matchRoute?.meta?.title,
              type:matchRoute?.meta?.type,
              sort:matchRoute?.meta?.sort,
              permission: _permission
            }
          }
          // 父节点
          if (matchRoute.redirect) {
            data.redirect = matchRoute.redirect
            data.meta.icon = icon ?? matchRoute?.meta?.icon
            data.meta.alwaysShow = true
          }
          // recursive child routes
          if (route?.childs?.length) {
            data.children = generateRoutesByServer(allRoutes, route.childs, route)
          }
          res.push(data as AppRouteRecordRaw)
        }
      }
    }
    // 未匹配上时, 当目录创建
    if (!match) {
      const data1: AppRouteRecordRaw = {
        path: urlPathResolve(url),
        component: Layout,
        name: routeName ? routeName : url,
        meta: {
          title: nodeName
        }
      }
      // 不存在父级菜单
      if (!parentRoute) {
        data1.meta.icon = icon
        data1.meta.alwaysShow = route?.childs?.length ? true : false
      }
      // recursive child routes
      if (route?.childs?.length) {
        data1.children = generateRoutesByServer(allRoutes, route.childs, route)
      }
      res.push(data1 as AppRouteRecordRaw)
    }
  }
  return res
}

const urlPathResolve = (path: string) => {
  if (isUrl(path)) return path
  const menuPath = path.startsWith('/') || !path ? path : `/${path}`
  return menuPath
}

export const pathResolve = (parentPath: string, path: string) => {
  if (isUrl(path)) return path
  const childPath = path.startsWith('/') || !path ? path : `/${path}`
  return `${parentPath}${childPath}`.replace(/\/\//g, '/').trim()
}

// 路由降级
export const flatMultiLevelRoutes = (routes: AppRouteRecordRaw[]) => {
  const modules: AppRouteRecordRaw[] = cloneDeep(routes)
  for (let index = 0; index < modules.length; index++) {
    const route = modules[index]
    if (!isMultipleRoute(route)) {
      continue
    }
    promoteRouteLevel(route)
  }
  return modules
}

// 层级是否大于2
const isMultipleRoute = (route: AppRouteRecordRaw) => {
  if (!route || !Reflect.has(route, 'children') || !route.children?.length) {
    return false
  }

  const children = route.children

  let flag = false
  for (let index = 0; index < children.length; index++) {
    const child = children[index]
    if (child.children?.length) {
      flag = true
      break
    }
  }
  return flag
}

// 生成二级路由
const promoteRouteLevel = (route: AppRouteRecordRaw) => {
  let router: Router | null = createRouter({
    routes: [route as RouteRecordRaw],
    history: createWebHashHistory()
  })

  const routes = router.getRoutes()
  addToChildren(routes, route.children || [], route)
  router = null

  route.children = route.children?.map((item) => omit(item, 'children'))
}

// 添加所有子菜单
const addToChildren = (
  routes: RouteRecordNormalized[],
  children: AppRouteRecordRaw[],
  routeModule: AppRouteRecordRaw
) => {
  for (let index = 0; index < children.length; index++) {
    const child = children[index]
    const route = routes.find((item) => item.name === child.name)
    if (!route) {
      continue
    }
    routeModule.children = routeModule.children || []
    if (!routeModule.children.find((item) => item.name === route.name)) {
      routeModule.children?.push(route as unknown as AppRouteRecordRaw)
    }
    if (child.children?.length) {
      addToChildren(routes, child.children, routeModule)
    }
  }
}
