import { hasAuthority } from '@vue2-client/utils/authority-utils'
import { loginIgnore } from '@vue2-client/router/index'
import { checkAuthorization, METHOD, request } from '@vue2-client/utils/request'
import NProgress from 'nprogress'
import { logout } from '@vue2-client/services/user'
import {
  startLogin,
  checkSingleAuthorization,
} from '@vue2-client/utils/login'
import AES from '@vue2-client/utils/EncryptUtil'
import Vue from 'vue'
import { funcToRouter, loadRoutes } from '@vue2-client/utils/routerUtil'
import { indexedDB } from '@vue2-client/utils/indexedDB'
import { microDispatch } from '@vue2-client/utils/microAppUtils'

NProgress.configure({ showSpinner: false })

/**
 * 进度条开始
 * @param to
 * @param form
 * @param next
 */
const progressStart = (to, form, next) => {
  // start progress bar
  if (!NProgress.isStarted()) {
    NProgress.start()
  }
  next()
}

/**
 * 登录守卫
 * @param to
 * @param form
 * @param next
 * @param options
 */
const loginGuard = (to, form, next, options) => {
  if (window.__MICRO_APP_ENVIRONMENT__) {
    window.microApp.dispatch({ type: '子应用发送给主应用的数据', to: to.path })
  }
  const urlParams = new URLSearchParams(window.location.search)
  const LoginTicket = urlParams.get('LoginTicket')
  // 如果是需要我们自己登陆的项目
  const token = urlParams.get('token')
  // 如果是v2 的项目 资源管理和营收分开库的那种项目 传递用户信息进来
  const tokenV2 = urlParams.get('tokenV2')
  // 如果是 v4 的父项目，通过localStorage传递信息
  const V4_LOGIN_DATA_KEY = localStorage.getItem('v4LoginData')
  if (LoginTicket) {
    const loginTicket = decodeURIComponent(LoginTicket)
    const { AESDecrypt } = AES
    const info = AESDecrypt(loginTicket, '3KMKqvgwR8ULbR8Z')
    const { store, message, router } = options
    // 单页面通常是嵌入到v3的项目中，没有单独的清除按钮，所以需要清除indexedDB
    indexedDB.clear()
    if (
      (!loginIgnore.includes(to) || to.name === '404') &&
      !checkSingleAuthorization('SinglePage', loginTicket)
    ) {
      localStorage.setItem('SinglePage_TOKEN', loginTicket)
      startLogin({
        ...info,
        pathname: window.location.pathname.replace(process.env.VUE_APP_PUBLIC_PATH, ''),
        store,
        router,
      })
    } else {
      const roles = store.getters['account/roles']
      let user = {}
      try {
        user = JSON.parse(localStorage.getItem(process.env.VUE_APP_USER_KEY))
      } catch (e) {
        user = localStorage.getItem(process.env.VUE_APP_USER_KEY)
      }
      const setUser = store._mutations['account/setUser'][0]
      setUser(user)
      if (roles.length === 0 && !loginIgnore.includes(to)) {
        message.warning('登录已失效，请重新登录')
        logout().finally((res) => {
          next({ path: '/login' })
        })
      } else {
        next()
      }
    }
  } else if (token) {
    const { AESDecrypt } = AES
    const info = AESDecrypt(token, '3KMKqvgwR8ULbR8Z')
    const { store, message, router } = options
    // 单页面通常是嵌入到v3的项目中，没有单独的清除按钮，所以需要清除indexedDB
    indexedDB.clear()
    if (
      (!loginIgnore.includes(to) || to.name === '404') &&
      !checkSingleAuthorization('SinglePage', token)
    ) {
      localStorage.setItem('SinglePage_TOKEN', token)
      startLogin({
        ...info,
        pathname: window.location.pathname.replace(process.env.VUE_APP_PUBLIC_PATH, ''),
        store,
        router,
      })
    } else {
      const roles = store.getters['account/roles']
      let user = {}
      try {
        user = JSON.parse(localStorage.getItem(process.env.VUE_APP_USER_KEY))
      } catch (e) {
        user = localStorage.getItem(process.env.VUE_APP_USER_KEY)
      }
      const setUser = store._mutations['account/setUser'][0]
      setUser(user)
      if (roles.length === 0 && !loginIgnore.includes(to)) {
        message.warning('登录已失效，请重新登录')
        logout().finally((res) => {
          next({ path: '/login' })
        })
      } else {
        next()
      }
    }
  } else if (tokenV2) {
    const { AESDecrypt } = AES
    const info = AESDecrypt(tokenV2, '3KMKqvgwR8ULbR8Z')
    request(`/rs/user/${info.name}/${info.password}/智慧燃气`, METHOD.GET).then(
      res => {
        const curUser = {
          name: res.name,
          username: res.name,
          orgid: res.name,
          avatar: '',
          ename: res.ename,
          id: res.id,
          orgName: res.f_fengongsi,
          contact: '',
          phone: '',
          orgs: res.orgs
        }
        Vue.$store.commit('account/setUser', Object.assign(curUser, res))
        const login = {
          f: res,
          jwt: res.id,
          r: res.roles
        }
        Vue.$store.commit('account/setLogin', login)
        loadRoutes(funcToRouter(res.functions))
        next()
      }
    )
  } else if (V4_LOGIN_DATA_KEY) {
    const v4LoginData = JSON.parse(localStorage.getItem('userInfo'))
    const curUser = {
      name: v4LoginData.name,
      username: v4LoginData.name,
      orgid: v4LoginData.name,
      avatar: '',
      ename: v4LoginData.ename,
      id: v4LoginData.id,
      orgName: v4LoginData.orgs,
      contact: '',
      phone: '',
      orgs: v4LoginData.orgs
    }
    Vue.$store.commit('account/setUser', Object.assign(curUser, v4LoginData))
    const login = {
      f: v4LoginData,
      jwt: v4LoginData.id,
      r: v4LoginData.r || v4LoginData.permissions
    }
    Vue.$store.commit('account/setLogin', login)
    Vue.$store.commit('account/setPermissions', v4LoginData.r)
    Vue.$store.commit('account/setRoles', v4LoginData.rolestr?.split(','))
    if (!Vue.$store.state?.setting?.menuData || Vue.$store.state?.setting?.menuData?.length === 0) {
      loadRoutes(funcToRouter(v4LoginData.functions))
    }
    next()
  } else {
    const { message } = options
    if (
      (!loginIgnore.includes(to) || to.name === '404') &&
      !checkAuthorization()
    ) {
      message.warning('登录已失效，请重新登录')
      next({ path: '/login' })
    } else {
      // const roles = store.getters['account/roles']
      // if (roles.length === 0 && !loginIgnore.includes(to)) {
      //   message.warning('登录已失效，请重新登录')
      //   logout().finally((res) => {
      //     next({ path: '/login' })
      //   })
      // } else {
      next()
      // }
    }
  }
}

/**
 * 权限守卫
 * @param to
 * @param form
 * @param next
 * @param options
 */
const authorityGuard = (to, form, next, options) => {
  const { store, message } = options
  const permissions = store.getters['account/permissions']
  const roles = store.getters['account/roles']
  if (!hasAuthority(to, permissions, roles)) {
    message.warning(`对不起，您无权访问页面: ${to.fullPath}，请联系管理员`)
    next({ path: '/403' })
    // NProgress.done()
  } else {
    next()
  }
}

/**
 * 混合导航模式下一级菜单跳转重定向
 * @param to
 * @param from
 * @param next
 * @param options
 * @returns {*}
 */
const redirectGuard = (to, from, next, options) => {
  const { store } = options
  const getFirstChild = (routes) => {
    const route = routes[0]
    if (!route.children || route.children.length === 0) {
      return route
    }
    return getFirstChild(route.children)
  }
  if (store.state.setting.layout === 'mix') {
    const firstMenu = store.getters['setting/firstMenu']
    if (firstMenu.find((item) => item.fullPath === to.fullPath)) {
      store.commit('setting/setActivatedFirst', to.fullPath)
      const subMenu = store.getters['setting/subMenu']
      if (subMenu.length > 0) {
        const redirect = getFirstChild(subMenu)
        return next({ path: redirect.fullPath })
      }
    }
  }
  next()
}

/**
 * 进度条结束
 */
const progressDone = () => {
  // finish progress bar
  NProgress.done()
}

const microAppGuard = () => {
  microDispatch({ type: 'microMounted', appName: window.__MICRO_APP_NAME__ })
}

export default {
  beforeEach: [progressStart, loginGuard, authorityGuard, redirectGuard],
  afterEach: [progressDone, microAppGuard],
}
