import router from '@/router/index'
import { isNavigationFailure, NavigationFailureType ,useRouter} from 'vue-router'
import type { RouteRecordRaw, RouteLocationRaw } from 'vue-router'
import { ElNotification } from 'element-plus'
import { useConfig } from '@/stores/config'
import { useNavTabs } from '@/stores/navTabs'
import { closeShade } from '@/utils/pageShade'
import { adminBaseRoute } from '@/router/static'
import { compact, isEmpty, reverse } from 'lodash-es'
import { isAdminApp } from '@/utils/common'
import { getRouteMenu, dictDataCache } from '@/api/auth'
import { adminBaseRoutePath } from '@/router/static'
const route:any = useRouter()
/**
 * 导航失败有错误消息的路由push
 * @param to — 导航位置，同 router.push
 */
export const routePush = async (to: RouteLocationRaw) => {
    try {
        const failure = await router.push(to)

        if (isNavigationFailure(failure, NavigationFailureType.aborted)) {
            ElNotification({
                message: 'utils.Navigation failed, navigation guard intercepted!',
                type: 'error'
            })
        } else if (isNavigationFailure(failure, NavigationFailureType.duplicated)) {
            // ElNotification({
            //     message: '已在目标页',
            //     type: 'warning'
            // })
        }
    } catch (error) {
        ElNotification({
            message: '导航失败，路由无效',
            type: 'error'
        })
        console.error(error)
    }
}

/**
 * 获取第一个菜单
 */
export const getFirstRoute = (routes: RouteRecordRaw[], menuType = 'tab'): false | RouteRecordRaw => {
    const routerPaths: string[] = []
    const routers = router.getRoutes()
    routers.forEach(item => {
        if (item.path) routerPaths.push(item.path)
    })
    let find: boolean | RouteRecordRaw = false
    for (const key in routes) {
        if (
            routes[key].meta?.type == 'menu' &&
            routes[key].meta?.menu_type == menuType &&
            routerPaths.indexOf(routes[key].path) !== -1
        ) {
            return routes[key]
        } else if (routes[key].children && routes[key].children?.length) {
            find = getFirstRoute(routes[key].children!)
            if (find) return find
        }
    }
    return find
}

/**
 * 打开侧边菜单
 * @param menu 菜单数据
 */
export const onClickMenu = (menu: RouteRecordRaw) => {
    switch (menu.meta?.menu_type) {
        case 'iframe':
        case 'tab':
            routePush({ path: menu.path })
            break
        case 'link':
            window.open(menu.path, '_blank')
            break

        default:
            ElNotification({
                message: 'utils.Navigation failed, the menu type is unrecognized!',
                type: 'error'
            })
            break
    }

    const config = useConfig()
    if (config.layout.shrink) {
        closeShade(() => {
            config.setLayout('menuCollapse', true)
        })
    }
}

/**
 * 处理后台的路由
 */
export const handleAdminRoute = (routes: any) => {
    const viewsComponent = import.meta.glob('/src/views/**/*.vue')
    addRouteAll(viewsComponent, routes, adminBaseRoute.name as string)
    const menuAdminBaseRoute = (adminBaseRoute.path as string) + '/'
    // 更新stores中的路由菜单数据
    const navTabs = useNavTabs()
    navTabs.setTabsViewRoutes(handleMenuRule(routes, menuAdminBaseRoute))
    navTabs.fillAuthNode(handleAuthNode(routes, menuAdminBaseRoute))
}

/**
 * 获取菜单的paths
 */
export const getMenuPaths = (menus: RouteRecordRaw[]): string[] => {
    let menuPaths: string[] = []
    menus.forEach(item => {
        menuPaths.push(item.path)
        if (item.children && item.children.length > 0) {
            menuPaths = menuPaths.concat(getMenuPaths(item.children))
        }
    })
    return menuPaths
}

/**
 * 后台的菜单处理
 */
const handleMenuRule = (routes: any, pathPrefix = '/', type = ['menu', 'menu_dir']) => {
    const menuRule: RouteRecordRaw[] = []
    for (const key in routes) {
        if (routes[key].extend == 'add_rules_only') {
            continue
        }
        if (!type.includes(routes[key].type)) {
            continue
        }
        if (routes[key].type == 'menu_dir' && routes[key].children && !routes[key].children.length) {
            continue
        }
        if (
            ['route', 'menu', 'nav_user_menu', 'nav'].includes(routes[key].type) &&
            ((routes[key].menu_type == 'tab' && !routes[key].component) ||
                (['link', 'iframe'].includes(routes[key].menu_type) && !routes[key].url))
        ) {
            continue
        }
        const currentPath = ['link', 'iframe'].includes(routes[key].menu_type)
            ? routes[key].url
            : pathPrefix + routes[key].path
        let children: RouteRecordRaw[] = []
        if (routes[key].children && routes[key].children.length > 0) {
            children = handleMenuRule(routes[key].children, pathPrefix, type)
        }
        menuRule.push({
            path: currentPath,
            name: routes[key].name,
            component: routes[key].component,
            meta: {
                id: routes[key].id,
                title: routes[key].title,
                icon: routes[key].icon,
                keepalive: routes[key].keepalive,
                menu_type: routes[key].menu_type,
                type: routes[key].type
            },
            children: children
        })
    }
    return menuRule
}

/**
 * 处理权限节点
 * @param routes 路由数据
 * @param prefix 节点前缀
 * @returns 组装好的权限节点
 */
const handleAuthNode = (routes: any, prefix = '/') => {
    const authNode: Map<string, string[]> = new Map([])
    assembleAuthNode(routes, authNode, prefix, prefix)
    return authNode
}
const assembleAuthNode = (routes: any, authNode: Map<string, string[]>, prefix = '/', parent = '/') => {
    const authNodeTemp = []
    for (const key in routes) {
        if (routes[key].type == 'button') authNodeTemp.push(prefix + routes[key].name)
        if (routes[key].children && routes[key].children.length > 0) {
            assembleAuthNode(routes[key].children, authNode, prefix, prefix + routes[key].name)
        }
    }
    if (authNodeTemp && authNodeTemp.length > 0) {
        authNode.set(parent, authNodeTemp)
    }
}

/**
 * 动态添加路由-带子路由
 * @param viewsComponent
 * @param routes
 * @param parentName
 * @param analyticRelation 根据 name 从已注册路由分析父级路由
 */
export const addRouteAll = (
    viewsComponent: Record<string, any>,
    routes: any,
    parentName: string,
    analyticRelation = false
) => {
    for (const idx in routes) {
        if (routes[idx].extend == 'add_menu_only') {
            continue
        }
        if (
            (routes[idx].menu_type == 'tab' && viewsComponent[routes[idx].component]) ||
            routes[idx].menu_type == 'iframe'
        ) {
            addRouteItem(viewsComponent, routes[idx], parentName, analyticRelation)
        }

        if (routes[idx].children && routes[idx].children.length > 0) {
            addRouteAll(viewsComponent, routes[idx].children, parentName, analyticRelation)
        }
    }
}

/**
 * 动态添加路由
 * @param viewsComponent
 * @param route
 * @param parentName
 * @param analyticRelation 根据 name 从已注册路由分析父级路由
 */
export const addRouteItem = (
    viewsComponent: Record<string, any>,
    route: any,
    parentName: string,
    analyticRelation: boolean
) => {
    let path = '',
        component
    if (route.menu_type == 'iframe') {
        path = (isAdminApp() ? adminBaseRoute.path : '') + '/iframe/' + encodeURIComponent(route.url)
        component = () => import('@/layouts/common/router-view/iframe.vue')
    } else {
        path = parentName ? route.path : '/' + route.path
        component = viewsComponent[route.component]
    }

    if (route.menu_type == 'tab' && analyticRelation) {
        const parentNames = getParentNames(route.name)
        if (parentNames.length) {
            for (const key in parentNames) {
                if (router.hasRoute(parentNames[key])) {
                    parentName = parentNames[key]
                    break
                }
            }
        }
    }

    const routeBaseInfo: RouteRecordRaw = {
        path: path,
        name: route.name,
        component: component,
        meta: {
            ...route,
            title: route.title,
            extend: route.extend,
            icon: route.icon,
            keepalive: route.keepalive,
            menu_type: route.menu_type,
            type: route.type,
            url: route.url,
            addtab: true
        }
    }
    if (parentName) {
        router.addRoute(parentName, routeBaseInfo)
    } else {
        router.addRoute(routeBaseInfo)
    }
}

// 刷新菜单
export const getMenu = () => {
    getRouteMenu().then((res: any) => {
        const handlerMenu = (data: any) => {
            data.forEach((item: any) => {
                item.routePath =
                    item.routePath[0] == '/' ? item.routePath.substring(1, item.routePath.length) : item.routePath
                item.path = item.routePath
                item.name = item.routePath
                item.keepalive = item.routePath
                item.component = item.routeName
                    ? item.routeName.indexOf('/src/views/') > -1
                        ? item.routeName
                        : `/src/views/${item.routeName}/index.vue`
                    : ''
                item.type = item.children && item.children.length > 0 ? 'menu_dir' : 'menu'
                item.menu_type = item.children && item.children.length > 0 ? null : 'tab'
                if (item.children) {
                    handlerMenu(item.children)
                }
            })
        }
        handlerMenu(res.data)
        handleAdminRoute(res.data)
        if (route?.params?.to) {
            const lastRoute = JSON.parse(route.params.to as string)
            if (lastRoute.path != adminBaseRoutePath) {
                let query = !isEmpty(lastRoute.query) ? lastRoute.query : {}
                routePush({ path: lastRoute.path, query: query })
                return
            }
        }
    })
}

/**
 * 根据name字符串，获取父级name组合的数组
 * @param name
 */
const getParentNames = (name: string) => {
    const names = compact(name.split('/'))
    const tempNames = []
    const parentNames = []
    for (const key in names) {
        tempNames.push(names[key])
        if (parseInt(key) != names.length - 1) {
            parentNames.push(tempNames.join('/'))
        }
    }
    return reverse(parentNames)
}
