import router, { asyncRoutes } from '@/router'
import settings from './settings'
import { getToken, setToken, TokenKey } from '@/utils/auth'
import NProgress from 'nprogress'
NProgress.configure({ showSpinner: false }) // NProgress Configuration
import 'nprogress/nprogress.css'
import getPageTitle from '@/utils/getPageTitle'
import { RouterRowTy } from '~/router'
import { useUserStore } from '@/store/user'
import { usePermissionStore } from '@/store/permission'
import Layout from '@/layout'
import { setTree } from '@/utils/validate'
import * as _ from 'lodash'
const modules = import.meta.glob('./views/**/*.vue')
const whiteList = ['/login', '/404', '/401'] // no redirect whitelist
router.beforeEach(async (to: any, from, next: any) => {
  // start progress bar
  if (settings.isNeedNprogress) NProgress.start()
  // set page title
  document.title = getPageTitle(to.meta.title)
  if (!settings.isNeedLogin) setToken(TokenKey, settings.tmpToken)
  const hasToken: string | null = getToken(TokenKey)

  const userStore = useUserStore()
  const permissionStore = usePermissionStore()
  if (hasToken) {
    if (to.path === '/login') {
      // if is logged in, redirect to the home page
      next({ path: '/' })
    } else {
      //judge isGetUserInfo
      const isGetUserInfo: boolean = permissionStore.isGetUserInfo
      if (isGetUserInfo) {
        next()
      } else {
        try {
          let accessRoutes: any = []
          if (settings.isNeedLogin) {
            // get user info
            // note: roles must be a object array! such as: ['admin'] or ,['developer','editor']
            await userStore.getInfo()
            const treeData: any = await userStore.getMenuInfo()
            const typeData = setType(treeData, 'up_auth_id', 'auth_id')
            const menusArray = parseMenuItem(typeData)
            const treeMenu = setTree(menusArray, 'up_auth_id', 'auth_id')
            const dataMenu = _.unionBy(treeMenu, 'auth_id')
            const menus = parseMenu(dataMenu)
            console.log(menus)
            // const { roles }: any = await userStore.getInfo()
            // accessRoutes = await permissionStore.generateRoutes(roles)
            accessRoutes = menus
          } else {
            accessRoutes = asyncRoutes
          }
          // setting constRouters and accessRoutes to vuex , in order to sideBar for using
          permissionStore.M_routes(accessRoutes)
          // dynamically add accessible routes
          //router4 addRoutes destroyed
          accessRoutes.forEach((route: RouterRowTy) => {
            router.addRoute(route)
          })
          //already get userInfo
          permissionStore.M_isGetUserInfo(true)
          // hack method to ensure that addRoutes is complete
          // set the replace: true, so the navigation will not leave a history record
          next({ ...to, replace: true })
        } catch (err) {
          console.log(err)
          await userStore.resetState()
          next(`/login?redirect=${to.path}`)
          if (settings.isNeedNprogress) NProgress.done()
        }
      }
    }
  } else {
    if (whiteList.indexOf(to.path) !== -1) {
      next()
    } else {
      next(`/login?redirect=${to.path}`)
      if (settings.isNeedNprogress) NProgress.done()
    }
  }
})

function parseMenuItem(data) {
  const menus: any = []
  data.map((item) => {
    if (item.show_type == 1) {
      if (item.up_auth_id == '1568') {
        menus.push({
          auth_id: item.auth_id,
          up_auth_id: item.up_auth_id,
          path: item.route_info,
          name: item.auth_ident,
          meta: {
            title: item.auth_name,
            elSvgIcon: item.show_icon ?? 'Fold',
            show_index: item.show_index,
            qid: item.queryTemplateID,
          },
          component: Layout,
          hidden: !item.is_show,
        })
      } else {
        menus.push({
          auth_id: item.auth_id,
          up_auth_id: item.up_auth_id,
          path: item.route_info,
          name: item.auth_ident,
          meta: {
            title: item.auth_name,
            elSvgIcon: item.show_icon ?? 'Fold',
            show_index: item.show_index,
            qid: item.queryTemplateID,
          },
          component: { render: () => h(resolveComponent('router-view')) },
          hidden: !item.is_show,
        })
      }
    } else if (item.show_type == 2) {
      menus.push({
        auth_id: item.auth_id,
        up_auth_id: item.up_auth_id,
        path: item.route_info,
        name: item.auth_ident,
        meta: {
          title: item.auth_name,
          elSvgIcon: item.show_icon ?? 'Fold',
          show_index: item.show_index,
          qid: item.queryTemplateID,
          other: item.other ?? null,
        },
        component: modules[`./views${item.file_link}`],
        // component: () => import('./views' + item.file_link),
        hidden: !item.is_show,
      })
    }
  })

  return menus
}

function setType(arr, parentKey, key) {
  const datas: any = []
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length; j++) {
      if (arr[i][key] == arr[j][parentKey]) {
        if (arr[j].show_type == 3) {
          datas.push(arr[j])
          arr[i].other = datas
        }
      }
    }
  }
  return arr
}

function parseMenu(arr: Array<any>) {
  const menus: any = arr
  // arr.forEach((item) => {
  //   const res = parseItem(item)
  //   menus.push(res)
  // })
  const newMenus = menus.flat()
  newMenus.push({
    path: '/userManagement',
    component: Layout,
    name: 'UserManagement',
    redirect: '/userManagement/permission',
    //using el svg icon, the elSvgIcon first when at the same time using elSvgIcon and icon
    meta: { title: '权限管理', elSvgIcon: 'Fold', show_index: 2 },
    children: [
      {
        path: '/userManagement/permission',
        name: 'Permission',
        meta: { title: '权限项管理' },
        component: () => import('@/views/userManagement/permission/index.vue'),
      },
      {
        path: '/userManagement/role',
        name: 'Role',
        meta: { title: '角色管理' },
        redirect: '/userManagement/role',
        component: {
          render: () => h(resolveComponent('router-view')),
        },
        children: [
          {
            path: '/userManagement/role',
            name: 'Role',
            hidden: true,
            component: () => import('@/views/userManagement/role/index.vue'),
          },
          {
            path: '/userManagement/role/auth',
            name: 'Auth',
            hidden: true,
            meta: { title: '角色授权' },
            component: () => import('@/views/userManagement/role/auth.vue'),
          },
        ],
      },
      {
        path: '/userManagement/account',
        name: 'Account',
        meta: { title: '账号管理' },
        redirect: '/userManagement/account',
        component: {
          render: () => h(resolveComponent('router-view')),
        },
        children: [
          {
            path: '/userManagement/account',
            component: () => import('@/views/userManagement/account/index.vue'),
            hidden: true,
          },
          {
            path: '/userManagement/account/accountAuth',
            name: 'AccountAuth',
            hidden: true,
            meta: { title: '账号权限' },
            component: () => import('@/views/userManagement/account/auth.vue'),
          },
        ],
      },
      {
        path: '/userManagement/accountGroup',
        name: 'AccountGroup',
        meta: { title: '账号组管理' },
        component: () =>
          import('@/views/userManagement/accountGroup/index.vue'),
      },
      {
        path: '/userManagement/application',
        name: 'Application',
        meta: { title: '应用管理' },
        component: () => import('@/views/userManagement/application/index.vue'),
      },
    ],
  })
  const allMenus = newMenus.length
    ? newMenus.sort((a, b) => a.meta.show_index - b.meta.show_index)
    : []
  allMenus.push({
    path: '/:pathMatch(.*)',
    redirect: '/404',
    hidden: true,
  })
  allMenus[0].redirect = allMenus[0].path
  allMenus[0].path = '/'
  return allMenus
}

router.afterEach(() => {
  if (settings.isNeedNprogress) NProgress.done()
})
