<template>
  <el-dropdown size="small" class="d2-mr">
    <span class="btn-text">
      {{ info.name ? $t('page.layout.user.greeting', { name: info.name }) : $t('page.layout.user.not_logged_in') }}
    </span>
    <el-dropdown-menu slot="dropdown">
      <el-dropdown-item v-if="isAdmin" icon="el-icon-setting" @click.native="openApiDebug">
        {{ $t('page.layout.user.api_debug') }}
      </el-dropdown-item>
      <el-dropdown-item icon="el-icon-key" @click.native="openPasswordDialog">
        {{ $t('page.layout.user.change_password') }}
      </el-dropdown-item>
      <el-dropdown-item icon="el-icon-refresh" @click.native="reloadMenu">
        {{ $t('page.layout.user.reload_menu') }}
      </el-dropdown-item>
      <el-dropdown-item icon="el-icon-document-checked" @click.native="openAuthDialog">
        {{ $t('page.layout.user.product_authorization') }}
      </el-dropdown-item>
      <el-dropdown-item divided @click.native="logOff">
        <d2-icon name="power-off" class="d2-mr-5" />
        {{ $t('page.layout.user.logout') }}
      </el-dropdown-item>
    </el-dropdown-menu>

    <el-dialog
      :title="$t('page.layout.user.change_password')"
      width="600px"
      :visible.sync="passwordDialogVisible"
      :append-to-body="true"
      :close-on-click-modal="false"
      @close="resetPasswordForm"
    >
      <el-form ref="passwordForm" :model="passwordForm" :rules="passwordRules" label-width="110px" size="small">
        <el-form-item :label="$t('page.layout.user.original_password')" prop="password_old">
          <el-input v-model.trim="passwordForm.password_old" type="password" :placeholder="$t('page.layout.user.placeholder_original_password')" clearable show-password />
        </el-form-item>
        <el-form-item :label="$t('page.layout.user.new_password')" prop="password">
          <el-input v-model.trim="passwordForm.password" type="password" :placeholder="$t('page.layout.user.placeholder_new_password')" clearable show-password />
        </el-form-item>
        <el-form-item :label="$t('page.layout.user.confirm_password')" prop="password_confirm">
          <el-input v-model.trim="passwordForm.password_confirm" type="password" :placeholder="$t('page.layout.user.placeholder_confirm_password')" clearable show-password />
        </el-form-item>
      </el-form>
      <div slot="footer">
        <el-button size="small" @click="passwordDialogVisible = false">{{ $t('page.layout.user.cancel') }}</el-button>
        <el-button size="small" type="primary" :loading="passwordSubmitting" @click="submitPassword">
          {{ $t('page.layout.user.confirm') }}
        </el-button>
      </div>
    </el-dialog>

    <el-dialog
      :title="$t('page.layout.user.product_authorization')"
      width="600px"
      :visible.sync="authDialogVisible"
      :append-to-body="true"
      :close-on-click-modal="false"
      @opened="clearAuthFiles"
    >
      <el-descriptions :column="1" border>
        <el-descriptions-item :label="$t('page.layout.user.authorization_validity_period')">
          {{ authTime || '-' }}
        </el-descriptions-item>
      </el-descriptions>
      <el-upload
        ref="authUpload"
        class="auth-upload"
        drag
        action=""
        :limit="1"
        :show-file-list="true"
        :before-upload="beforeAuthUpload"
        :http-request="uploadAuthFile"
      >
        <i class="el-icon-upload" />
        <div class="el-upload__text">
          {{ $t('page.layout.user.drag_upload_hint') }}<em>{{ $t('page.layout.user.click_upload') }}</em>
        </div>
        <div slot="tip" class="el-upload__tip">{{ $t('page.layout.user.upload_file_tip') }}</div>
      </el-upload>
    </el-dialog>
  </el-dropdown>
</template>

<script>
import util from '@/libs/util'
import { mapActions, mapState } from 'vuex'
import { updateUserPwd } from '@/api/system-administration/user'
import { getAuthNearTime, getAuthTime, getAuthTimeByUpload } from '@/api/auth'

export default {
  data () {
    return {
      passwordDialogVisible: false,
      passwordSubmitting: false,
      authDialogVisible: false,
      authTime: '',
      authNoticeTimer: null,
      passwordForm: this.emptyPasswordForm(),
      passwordRules: {
        password_old: [
          { required: true, message: this.$t('page.layout.user.old_password_required'), trigger: 'blur' },
          { min: 6, max: 64, message: this.$t('page.layout.user.length_6_to_64'), trigger: 'blur' }
        ],
        password: [
          { required: true, message: this.$t('page.layout.user.new_password_required'), trigger: 'blur' },
          { min: 6, max: 64, message: this.$t('page.layout.user.length_6_to_64'), trigger: 'blur' }
        ],
        password_confirm: [
          { required: true, message: this.$t('page.layout.user.confirm_password_required'), trigger: 'blur' },
          { min: 6, max: 64, message: this.$t('page.layout.user.length_6_to_64'), trigger: 'blur' }
        ]
      }
    }
  },
  computed: {
    ...mapState('d2admin/user', [
      'info'
    ]),
    isAdmin () {
      return String(this.info && this.info.admin && this.info.admin.role_id) === '1'
    }
  },
  mounted () {
    this.loadAuthTime()
  },
  beforeDestroy () {
    this.clearAuthNoticeTimer()
  },
  methods: {
    ...mapActions('d2admin/account', [
      'logout'
    ]),
    emptyPasswordForm () {
      return {
        password_old: '',
        password: '',
        password_confirm: ''
      }
    },
    normalizeAuthResponse (res) {
      const source = res && res.data ? res.data : res
      return {
        status: Number(source && source.status),
        msg: source && source.msg ? source.msg : ''
      }
    },
    openApiDebug () {
      const routeData = this.$router.resolve({
        path: '/api',
        query: { token: this.info && this.info.token }
      })
      window.open(routeData.href, '_blank')
    },
    openPasswordDialog () {
      this.passwordForm = this.emptyPasswordForm()
      this.passwordDialogVisible = true
      this.$nextTick(() => {
        this.$refs.passwordForm && this.$refs.passwordForm.clearValidate()
      })
    },
    resetPasswordForm () {
      this.passwordForm = this.emptyPasswordForm()
      this.$nextTick(() => {
        this.$refs.passwordForm && this.$refs.passwordForm.clearValidate()
      })
    },
    submitPassword () {
      this.$refs.passwordForm.validate(async valid => {
        if (!valid) return
        if (this.passwordForm.password_old === this.passwordForm.password) {
          this.$message.error(this.$t('page.layout.user.password_same_error'))
          return
        }
        if (this.passwordForm.password !== this.passwordForm.password_confirm) {
          this.$message.error(this.$t('page.layout.user.password_not_match'))
          return
        }

        this.passwordSubmitting = true
        try {
          await updateUserPwd({
            user_id: this.info && this.info.admin && this.info.admin.user_id,
            ...this.passwordForm
          })
          this.passwordDialogVisible = false
          this.$message.success(this.$t('page.layout.user.password_change_success'))
          util.cookies.remove('token')
          util.cookies.remove('uuid')
          util.cookies.remove('block')
          localStorage.removeItem('user_id')
          this.logout({ confirm: false })
        } finally {
          this.passwordSubmitting = false
        }
      })
    },
    async reloadMenu () {
      await this.$store.dispatch('d2admin/menu/menuReload')
      this.$store.commit('d2admin/page/keepAliveClean')
      await this.$router.replace('/refresh')
      this.$message.success(this.$t('page.layout.user.menu_permission_reloaded'))
    },
    openAuthDialog () {
      this.authDialogVisible = true
      this.loadAuthTime()
    },
    clearAuthFiles () {
      this.$nextTick(() => {
        this.$refs.authUpload && this.$refs.authUpload.clearFiles()
      })
    },
    beforeAuthUpload (file) {
      const ext = String(file.name || '').replace(/.+\./, '').toLowerCase()
      if (ext !== 'license') {
        this.$message.error(this.$t('page.layout.user.please_upload_license'))
        return false
      }
      return true
    },
    async uploadAuthFile ({ file }) {
      const formData = new FormData()
      formData.append('method', 'get.auth.timeByUpload')
      formData.append('platform', 'admin')
      formData.append('file', file)
      try {
        const res = this.normalizeAuthResponse(await getAuthTimeByUpload(formData))
        if (res.status !== 0) {
          this.$message.error(res.msg)
          return
        }
        this.authTime = res.msg
        this.$message.success(this.$t('page.layout.user.authorization_update_success', { time: res.msg }))
      } finally {
        this.clearAuthFiles()
      }
    },
    notifyAuthExpired (message) {
      if (process.env.NODE_ENV === 'development') return
      this.$notify.error({
        title: this.$t('page.layout.user.prompt'),
        message,
        duration: 4500,
        position: 'bottom-right',
        showClose: false
      })
    },
    notifyAuthNearTime (message) {
      if (process.env.NODE_ENV === 'development') return
      this.$notify.warning({
        title: this.$t('page.layout.user.prompt'),
        message,
        duration: 4500,
        position: 'top-right',
        showClose: false
      })
    },
    clearAuthNoticeTimer () {
      if (this.authNoticeTimer) {
        clearInterval(this.authNoticeTimer)
        this.authNoticeTimer = null
      }
    },
    startAuthNoticeTimer (type, message) {
      if (process.env.NODE_ENV === 'development') return
      this.clearAuthNoticeTimer()
      const notify = type === 'expired' ? this.notifyAuthExpired : this.notifyAuthNearTime
      const interval = type === 'expired' ? 5000 : 30000
      this.authNoticeTimer = setInterval(() => notify(message), interval)
    },
    async loadAuthTime () {
      try {
        const auth = this.normalizeAuthResponse(await getAuthTime())
        if (auth.msg) this.authTime = auth.msg
        if (auth.status === 1) {
          const message = this.$t('page.layout.user.authorization_expired_message', { time: auth.msg })
          this.notifyAuthExpired(message)
          this.startAuthNoticeTimer('expired', message)
        }

        const near = this.normalizeAuthResponse(await getAuthNearTime())
        if (near.status === 1) {
          const message = this.$t('page.layout.user.authorization_near_message', { message: near.msg })
          this.notifyAuthNearTime(message)
          this.startAuthNoticeTimer('near', message)
        }
      } catch (error) {
        this.clearAuthNoticeTimer()
      }
    },
    logOff () {
      localStorage.removeItem('user_id')
      this.logout({
        confirm: true
      })
    }
  }
}
</script>

<style scoped>
.auth-upload {
  margin-top: 16px;
}
</style>
