import qs from 'qs'
import axios from '@/common/services/axios-instance'
// eslint-disable-next-line no-restricted-imports
import orginAxios from 'axios'
import store from '@/common/store'
import { router } from '@/common/router-ready'
import CryptoJS from 'crypto-js'

import Vue from 'vue'
import smcrypto from 'sm-crypto'
import { sdLocalStorage } from '@/common/services/storage-service'
import { setUserInfo, setUserPerms, getUserInfo } from '@/common/store-mixin'
import { Modal } from 'ant-design-vue'
import sdLoginModal from './sd-login-modal.vue'
let state = 'fulfilled' //  刷新token的promise状态
let promise // 刷新token的promise
/**
 * 加密（需要先加载js/common/aes.js文件）
 * @param word
 * @returns {*}
 */
function encrypt(word) {
  var key = window.CryptoJS.enc.Utf8.parse('abcdefgabcdefg12')
  var srcs = window.CryptoJS.enc.Utf8.parse(word)
  var encrypted = window.CryptoJS.AES.encrypt(srcs, key, {
    mode: window.CryptoJS.mode.ECB,
    padding: window.CryptoJS.pad.Pkcs7,
  })
  return encrypted.toString()
}

// 判断开关参数，如果未开，则不进行加密
if (
  sdLocalStorage.getItem('IS_OPEN_ENCRY') &&
  sdLocalStorage.getItem('IS_OPEN_ENCRY').toString() === 'true'
) {
  orginAxios.interceptors.request.use((config) => {
    // 加密

    // 判断是否有params
    const params = []
    if (config.params) {
      for (const key in config.params) {
        if (config.params[key] !== undefined && config.params[key] !== null) {
          params.push(key + '=' + config.params[key])
        }
      }
    }
    const notdata = 'notdata'
    let url = config.url
    // 将params拼接到url上
    if (params.length > 0) {
      if (url.includes('?')) {
        url = url + '&' + params.join('&')
      } else {
        url = url + '?' + params.join('&')
      }
    }

    config.headers.encryptionParams = encrypt(
      `${config.method}$*$${url}$*$${config.data ? JSON.stringify(config.data) : notdata}`
    )

    return config
  })
}

const errorinfo = {
  1001: '用户账号未激活',
  1002: '用户账号已被锁定',
  1003: '用户名或密码错误',
  1011: '无效的令牌',
  1021: '用户信息不存在',
  1030: '您的IP地址不在被允许范围内',
}
class LoginService {
  getClientId() {
    const clientKey = 'WE.Client_ID'
    let clientId = sdLocalStorage.getItem(clientKey)
    if (!clientId) {
      clientId = CryptoJS.lib.WordArray.random(16).toString()
      sdLocalStorage.setItem(clientKey, clientId)
    }
    return clientId
  }

  getTokens() {
    return store.state.sd.login.tokens
  }

  getTokensNoBear() {
    return {
      ...store.state.sd.login.tokens,
      access_token: this.getTokens().access_token.replace('Bearer ', ''),
    }
  }

  setTokens(value) {
    if (value.access_token) {
      value.access_token = 'Bearer ' + value.access_token
      value.time_stamp = new Date().getTime()
    }
    store.commit('sd/login/setTokens', value)
  }

  doLogout() {
    axios
      .post('api/logout', {
        token: this.getTokens().refresh_token,
        clientId: this.getClientId(),
      })
      .then(() => {
        this.setTokens({})
        store.commit('sd/common/clearUserInfo')
        store.commit('sd/common/clearUserPerms')
        // url中有参数（?xxx#/xxx）时，将参数清空
        if (window.location.search) {
          location.href = '?' + router.resolve({ path: '/sd-login' }).href
        } else {
          router.push('/sd-thirdparty-login')
        }
      })
  }

  encryptBySm4(ottId, ottToken, password) {
    const key = CryptoJS.MD5(ottToken).toString(CryptoJS.enc.Hex)
    var salt = CryptoJS.lib.WordArray.random(64 / 8)
    // @ts-ignore
    var key2 = CryptoJS.EvpKDF(key, salt, { keySize: 4 }).toString(CryptoJS.enc.Hex)
    // @ts-ignore
    var encryptData = smcrypto.sm4.encrypt(CryptoJS.MD5(password).toString(CryptoJS.enc.Hex), key2)
    // @ts-ignore
    var pwd = CryptoJS.format.OpenSSL.stringify({
      // @ts-ignore
      ciphertext: CryptoJS.enc.Hex.parse(encryptData),
      salt: salt,
    })
    pwd = pwd + '*' + ottId
    return pwd
  }

  doLogin(user, pass, extension) {
    // 调用获取一次性令牌接口
    return orginAxios.get('api/ott').then((ottResponse) => {
      // 获取服务端返回的一次性令牌信息
      const ott = ottResponse.data
      return orginAxios
        .post(`api/login`, {
          username: user,
          password: this.encryptBySm4(ott.id, ott.token, pass),
          device: 'WE',
          extension,
          clientId: this.getClientId(),
        })
        .then((res) => {
          if (res.data.licenseCode === 1100) {
            Modal.warning({
              title: '系统未注册',
              content:
                '尊敬的用户，系统检查到您当前使用的系统没有获得合法的授权注册码或注册码已过期，请联系管理员！',
            })
          }
          // 获取服务端返回数据
          const auth = res.data
          // 获取access_token
          // 存储到store里，供全局使用
          this.setTokens(auth)
          return 'Bearer ' + auth.access_token
        })
        .catch((e) => {
          let m = errorinfo[e.response?.data?.code] || e.response?.data?.message || '登录失败'
          if (e.response?.data?.freeLoginAttempt) {
            m = '用户名或密码错误，剩余尝试次数' + e.response.data.freeLoginAttempt + '次'
          }
          return Promise.reject(new Error(m))
        })
    })
  }

  ssoLogin(data) {
    if (data.loginName && data.password) {
      // 如果包含用户名密码，直接走原来的
      return this.doLogin(data.loginName, data.password)
    }
    if (data.sdTokenData) {
      this.setTokens(JSON.parse(decodeURIComponent(data.sdTokenData)))
      return Promise.resolve()
    }
    return orginAxios
      .get('api/thirdparty-login?' + qs.stringify(data))
      .then((res) => {
        const auth = res.data
        this.setTokens(auth)
        return 'Bearer ' + auth.access_token
      })
      .catch((e) => {
        return Promise.reject(new Error(errorinfo[e.response?.data?.code] || '单点失败'))
      })
  }

  refreshToken(code) {
    if (state === 'fulfilled') {
      // token不是更新状态
      state = 'pending'
      if ([2051, 2052].includes(code)) {
        promise = this.doLoginModal(code).finally(() => {
          state = 'fulfilled'
        })
      } else
        promise = orginAxios
          .post(
            'api/refresh',
            qs.stringify({ token: this.getTokens().refresh_token, clientId: this.getClientId }),
            {
              headers: { 'content-type': 'application/x-www-form-urlencoded' },
            }
          )
          .then((res) => {
            // 获取服务端返回数据
            const auth = res.data
            // 获取access_token
            // 存储到store里，供全局使用
            this.setTokens(auth)
            return 'Bearer ' + auth.access_token
          })
          .catch((e) => {
            // 刷新失败这里弹出用户名密码框重新登陆获取token,后面处理
            return this.doLoginModal()
          })
          .finally(() => {
            state = 'fulfilled'
          })
    }
    return promise
  }

  doLoginModal(code) {
    let mixin
    const p = new Promise(function(resolve, reject) {
      mixin = {
        data() {
          return {
            code,
          }
        },
        methods: {
          loginSuccess() {
            resolve()
            this.$destroy()
          },
          handleCancel() {
            reject(new Error('取消登录'))
            this.$destroy()
          },
        },
      }
    })

    const c = { ...sdLoginModal, store }
    // @ts-ignore
    c.mixins.push(mixin)
    const vm = new Vue(c).$mount()
    document.body.appendChild(vm.$el)
    return p
  }

  getQrCode() {
    return orginAxios('api/framework/v1/qrlogin/getqrcode').then((res) => {
      return res.data
    })
  }

  checkQrCode(code) {
    return orginAxios('api/framework/v1/qrlogin/checkqrcode?code=' + code)
      .then((res) => {
        if (res.data.success) {
          const auth = res.data.data
          // 获取access_token
          if (auth.access_token) {
            // 存储到store里，供全局使用
            this.setTokens(auth)
          }
        }
        return res.data
      })
      .catch((e) => {
        return e.response.data
      })
  }

  getRunAsHeader(runAs) {
    if (!runAs) return {}
    return {
      'X-RUN-AS': runAs,
    }
  }

  getRunAs() {
    return qs.parse(window.location?.search?.replace('?', '')).srcTrustId?.toString()
  }

  /**
   * 获取用户信息
   * @param {string} runAs 兼职身份
   */
  getUserInfo(runAs = this.getRunAs() || undefined) {
    return axios
      .post(
        'api/framework/v1/user-manager/userInfos-with-trustor',
        {},
        {
          headers: this.getRunAsHeader(runAs),
        }
      )
      .then((res) => {
        let hierarchicalInfo = JSON.parse(sdLocalStorage.getItem('hierarchicalInfo') || '{}')
        const authGroup = JSON.parse(res.data.attrs.authGroup || '{}')
        if (
          hierarchicalInfo.account &&
          !(
            hierarchicalInfo.account === res.data.account &&
            hierarchicalInfo.authGroupId === authGroup.id
          )
        ) {
          sdLocalStorage.removeItem('recentUser')
        }
        hierarchicalInfo = {
          account: res.data.account,
          authGroupId: authGroup.id,
        }
        sdLocalStorage.setItem('hierarchicalInfo', JSON.stringify(hierarchicalInfo))
        const roleCodes = res.data.roles.map((r) => r.code)
        const roleInfo = {
          // 系统管理员（或下级系统管理员）
          isSysAdmin: roleCodes.includes('ADMINISTRATOR') || roleCodes.includes('SUB_ADMIN'),
          // 安全管理员（或下级安全管理员）
          isSecAdmin:
            roleCodes.includes('SECURITYADMINISTRATOR') || roleCodes.includes('SUB_SECURITY_ADMIN'),
          // 安全审计员
          isSecAudit: roleCodes.includes('SECURITYAUDITOR'),
        }
        setUserInfo({ ...getUserInfo(), ...res.data, ...roleInfo }, runAs)
        return res.data
      })
  }

  updateTaskCount(runAs = this.getRunAs() || undefined) {
    return axios
      .post(
        'api/framework/v1/user-manager/userTaskCount-with-trustor',
        {
          todoExpressions: [],
          informExpressions: [
            {
              dataType: 'str',
              name: 'status',
              op: 'ne',
              stringValue: '2',
            },
          ],
          returnTodoNumbers: true,
          returnToReadNumbers: true,
          returnToCommunicateNumbers: true,
          returnToAttentionNumbers: true,
        },
        {
          headers: this.getRunAsHeader(runAs),
        }
      )
      .then((res) => {
        setUserInfo({ ...res.data, ...getUserInfo() }, runAs)
      })
  }

  /**
   * 获取用户权限列表
   * @param {string} runAs 兼职身份
   */
  getUserPerms(runAs = this.getRunAs() || undefined) {
    return axios
      .get('api/framework/v1/user-perm/my-authed-perms', {
        headers: this.getRunAsHeader(runAs),
      })
      .then((res) => {
        const perms = res.data
        setUserPerms(res.data, runAs)
        return perms
      })
  }

  updateRefreshToken() {
    if (
      new Date().getTime() - this.getTokens().time_stamp >
      (this.getTokens().expires_refresh - 10) * 1000
    ) {
      return this.doLoginModal()
    } else {
      return Promise.resolve(true)
    }
  }

  updateAccessToken() {
    if (
      new Date().getTime() - this.getTokens().time_stamp >
      (this.getTokens().expires_in - 10) * 1000
    ) {
      return this.refreshToken().then(() => this.getTokens().access_token)
    } else {
      return Promise.resolve(this.getTokens().access_token)
    }
  }

  // 获取系统配置
  getCommonConfig() {
    return axios.get('api/framework/v1/common-config/get-common-config').then((res) => {
      sdLocalStorage.setItem('commonConfig', JSON.stringify(res.data))
    })
  }

  // 写入加密开关
  getEncryIsOpen() {
    return axios
      .get(
        `api/xcoa-mobile/v1/iam-common/common/dict-key-value?keyId=IS_OPEN_ENCRY&dictType=value&valueId=IS_OPEN`
      )
      .then((res) => {
        sdLocalStorage.setItem('IS_OPEN_ENCRY', res.data[0]?.param0)
      })
  }
}
export default new LoginService()
