<template>
  <el-form ref="formRef" :rules="rules" :model="form" class="login-form" size="small">
    <el-form-item prop="username">
      <el-input v-model="form.username" placeholder="请输入用户名">
        <template #prefix>
          <el-icon><User /></el-icon>
        </template>
      </el-input>
    </el-form-item>
    <el-form-item prop="password">
      <el-input v-model="form.password" :type="inputType" placeholder="请输入密码">
        <template #prefix>
          <el-icon><Lock /></el-icon>
        </template>
        <template #append>
          <img style="width: 20px; cursor: pointer" :src="pwdIcon" @click="showPass" alt="" />
        </template>
      </el-input>
    </el-form-item>
    <el-form-item prop="multiAccount" v-if="multiAccountShow">
      <el-select v-model="form.multiAccount" placeholder="请选择" style="width: 100%">
        <el-option
          v-for="item in multiAccountList"
          :key="item.accId"
          :label="item.accountSen + '(' + item.tenantName + ')'"
          :value="item.accId"
        />
      </el-select>
    </el-form-item>
    <el-form-item prop="captchaCode">
      <el-input v-model="form.captchaCode" placeholder="图片验证码" maxlength="4" @keyup.enter="toLogin">
        <template #prefix>
          <el-icon><Key /></el-icon>
        </template>
        <template #suffix>
          <img class="imageCode" :src="imageCode" alt="图形验证码" @click="fetchDigitCaptcha" />
        </template>
      </el-input>
    </el-form-item>
    <el-form-item prop="smsCode">
      <el-input v-model="form.smsCode" maxlength="6" placeholder="短信验证码">
        <template #prefix>
          <el-icon><Message /></el-icon>
        </template>
        <template #suffix>
          <el-button class="smsBtn" link :disabled="smsBtn.disable" @click="sendSmsCodeFn">
            {{ smsBtn.btnName }}
          </el-button>
        </template>
      </el-input>
    </el-form-item>
  </el-form>
</template>

<script setup lang="ts">
import { reactive, ref, onMounted } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { fetchDigitCaptcha, sendLoginSmsCode, fetchMultiAccount } from '@/api/login'
import { encryptByAES } from '@/utils/crypto'
import { isUsername, isMobile } from '@/utils/validate'
import { useUserStore } from '@/stores/user'
import type { FormInstance, FormRules } from 'element-plus'

const router = useRouter()
const userStore = useUserStore()

const formRef = ref<FormInstance>()
const multiAccountList = ref<any[]>([])
const multiAccountShow = ref(false)
const imageCode = ref('')
const showPwdFlag = ref(false)
const inputType = ref('password')
const pwdIcon = ref('data:image/svg+xml,' + encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20"><circle cx="10" cy="10" r="5" fill="#999"/></svg>'))

const smsBtn = reactive({
  btnName: '发送验证码',
  disable: false,
  seconds: 60,
  intervalObj: null as number | null
})

const form = reactive({
  username: '',
  password: '',
  captchaKey: '',
  captchaCode: '',
  smsCode: '',
  multiAccount: ''
})

const validateUsername = (_rule: any, value: string, callback: any) => {
  if (!isUsername(value) && !isMobile(value)) {
    return callback(new Error('请输入正确的用户名'))
  }
  callback()
}

const rules: FormRules = {
  username: [{ required: true, validator: validateUsername, trigger: 'blur' }],
  password: [{ required: true, message: '请输入密码', trigger: 'blur' }],
  smsCode: [
    { required: true, message: '请输入短信验证码', trigger: 'blur' },
    { len: 6, message: '长度6个字符', trigger: 'blur' }
  ],
  captchaCode: [
    { required: true, message: '请输入验证码', trigger: 'blur' },
    { max: 4, message: '最长4个字符', trigger: 'blur' }
  ]
}

async function doFetchDigitCaptcha() {
  try {
    const res = await fetchDigitCaptcha()
    console.log(res.data)
    const key = Object.keys(res.data)[0]
    form.captchaKey = key
    imageCode.value = res.data[key]
  } catch (error: any) {
    ElMessage.error(error?.data?.msg || '获取验证码失败')
  }
}

function counter() {
  if (smsBtn.seconds === 0) {
    smsBtn.seconds = 60
    if (smsBtn.intervalObj) window.clearInterval(smsBtn.intervalObj)
    smsBtn.disable = false
    smsBtn.btnName = '重新发送'
  } else {
    smsBtn.seconds--
    smsBtn.btnName = smsBtn.seconds + '秒'
  }
}

const toLogin = async () => {
  if (!formRef.value) return
  const pwd = form.password
  try {
    await formRef.value.validate()
    const loginForm = {
      username: encryptByAES(form.username),
      password: encryptByAES(form.password),
      smsCode: form.smsCode,
      captchaKey: form.captchaKey,
      captchaCode: form.captchaCode,
      ...(multiAccountShow.value ? { multiAccount: form.multiAccount } : {})
    }

    try {
      const res = await userStore.loginByUsername(loginForm)
      if (res.code === 200) {
        ElMessage.success('登陆成功，请稍候...')
        setTimeout(() => {
          router.push({ path: '/' })
        }, 500)
      }
    } catch (error: any) {
      const data = error?.data
      const username = form.username
      if (data?.code === 'C030103') {
        ElMessage.error(`${data.msg}, 请于${data.data}秒后重试`)
      } else if (data?.code === 'C030105') {
        try {
          await ElMessageBox.confirm(data.msg, '密码过期提示', {
            type: 'warning',
            confirmButtonText: '前往修改'
          })
          router.push({ path: '/update-pwd', query: { code: data.data } })
        } catch {
          formRef.value?.resetFields()
          form.username = username
          doFetchDigitCaptcha()
        }
      } else if (data?.code === 'C030111') {
        ElMessage.warning(data.msg)
        setTimeout(async () => {
          try {
            const res = await fetchMultiAccount({ username: form.username })
            multiAccountList.value = res.data
            multiAccountShow.value = true
            form.password = pwd
            form.captchaCode = ''
            form.username = username
            doFetchDigitCaptcha()
          } catch (err: any) {
            ElMessage.error(err?.data?.msg || '查询多账号失败')
          }
        }, 1000)
      } else {
        ElMessage.error(data?.data || '登录失败')
        formRef.value?.resetFields()
        form.username = username
        doFetchDigitCaptcha()
      }
    }
  } catch {
    // validation failed
  }
}

const sendSmsCodeFn = async () => {
  if (!formRef.value) return
  const fieldsToValidate = ['username', 'captchaCode'] as const
  const results = await Promise.all(
    fieldsToValidate.map((item) => {
      return new Promise<string>((resolve) => {
        formRef.value!.validateField(item, (errorMsg) => {
          resolve(typeof errorMsg === 'string' ? errorMsg : (errorMsg ? String(errorMsg) : ''))
        })
      })
    })
  )
  const error = results.find((res) => res !== '')
  if (!error) {
    smsBtn.disable = true
    smsBtn.btnName = '已发送'
    const params = {
      username: encryptByAES(form.username),
      password: encryptByAES(form.password),
      captchaKey: form.captchaKey,
      captchaCode: form.captchaCode
    }
    try {
      const res = await sendLoginSmsCode(params)
      if (res.code === 200) {
        ElMessage.success(res.msg)
      }
      smsBtn.intervalObj = window.setInterval(counter, 1000)
    } catch (err: any) {
      ElMessage.error(err?.data?.msg || '发送失败')
      smsBtn.intervalObj = window.setInterval(counter, 1000)
    }
  }
}

const showPass = () => {
  showPwdFlag.value = !showPwdFlag.value
  inputType.value = showPwdFlag.value ? 'text' : 'password'
}

onMounted(() => {
  doFetchDigitCaptcha()
})

defineExpose({ toLogin })
</script>

<style scoped lang="less">
.login-form {
  .imageCode {
    position: absolute;
    right: -5px;
    top: 0px;
    cursor: pointer;
    height: 100%;
    width: 100px;
  }

  .smsBtn {
    position: absolute;
    cursor: pointer;
    right: 0;
    width: 100px;
    text-align: center;
    height: 100%;
  }
}

:deep(.el-input--small .el-input__inner) {
  height: 40px;
  line-height: 40px;
}

:deep(.el-form-item--small.el-form-item) {
  margin-bottom: 24px;
}
</style>
