<script setup lang="ts">
import { fetchEmailCode, fetchSMSCode, fetchUserPasswordUpdate, fetchVerifyCode } from '@/apis/user'
import { useUserStore } from '@/store/modules/user'
import { ss } from '@/utils/storage'
import type { CountdownInst, FormInst, FormItemRule } from 'naive-ui'
import SparkMD5 from 'spark-md5'
import { onMounted, ref, shallowReadonly, useTemplateRef, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'

const { t } = useI18n()
const passwordInfoFormRef = useTemplateRef<FormInst>('passwordInfoFormRef')
const countdownRef = useTemplateRef<CountdownInst>('countdownRef')
const userStore = useUserStore()

const isShowPasswordChangeModal = defineModel<boolean>('isShowPasswordChangeModal', { default: false })

const passwordChangeSubmitBtnLoading = ref(false)
const passwordInfoForm = ref<{
  verificationMethod: 'email' | 'sms'
  verifyCode: string
  password: string
  confirmPassword: string
}>({
  verificationMethod: 'email',
  verifyCode: '',
  password: '',
  confirmPassword: '',
})

const isShowCountdown = ref(false)
const countdownDuration = ref<number>(60000)
const countdownActive = ref(true)

const passwordFormRules = shallowReadonly({
  verifyCode: {
    required: true,
    trigger: 'blur',
    validator: (_rule: FormItemRule, value: string) => {
      if (!value) {
        return new Error(t('login_module.please_enter_the_verification_code'))
      } else if (value.length < 6) {
        return new Error(t('personal_settings_module.please_enter_the_correct_verification_code'))
      }

      return
    },
  },
  password: {
    required: true,
    trigger: 'blur',
    validator: (_rule: FormItemRule, value: string) => {
      if (!value) {
        return new Error(t('personal_settings_module.please_enter_your_new_password'))
      } else if (value.length <= 6) {
        return new Error(t('personal_settings_module.the_password_contains_a_maximum_of_6_characters'))
      }

      return
    },
  },
  confirmPassword: {
    required: true,
    trigger: 'blur',
    validator: (_rule: FormItemRule, value: string) => {
      if (!value) {
        return new Error(t('personal_settings_module.please_enter_confirm_new_password'))
      } else if (value !== passwordInfoForm.value.password) {
        return new Error(
          t('personal_settings_module.verify_that_the_new_password_is_inconsistent_with_the_new_password'),
        )
      }

      return
    },
  },
})

const verificationMethodDisable = ref({
  email: false,
  sms: false,
})

watchEffect(() => {
  if (userStore.userInfo) {
    !userStore.userInfo.email
      ? (verificationMethodDisable.value.email = true)
      : (verificationMethodDisable.value.email = false)

    !userStore.userInfo.mobilePhone
      ? (verificationMethodDisable.value.sms = true)
      : (verificationMethodDisable.value.sms = false)

    if (userStore.userInfo.email) {
      passwordInfoForm.value.verificationMethod = 'email'
    } else if (userStore.userInfo.mobilePhone) {
      passwordInfoForm.value.verificationMethod = 'sms'
    }
  }
})

onMounted(() => {
  let timeStringDraft = ss.get('PASSWORD_CHANGE_CODE')

  if (timeStringDraft) {
    const time = Math.floor(Date.now() - parseInt(timeStringDraft))

    if (time < 60000) {
      countdownDuration.value = 60000 - time
      countdownRef.value?.reset()
      isShowCountdown.value = true
    }
  }
})

function countdownRender({ seconds, minutes }: { seconds: number; minutes: number }) {
  if (minutes && minutes === 1) {
    return '60 s'
  }

  return `${seconds} s`
}

function onModalAfterLeave() {
  passwordInfoForm.value = {
    password: '',
    confirmPassword: '',
    verificationMethod: 'email',
    verifyCode: '',
  }
}

function handlePasswordChangeSubmit() {
  passwordInfoFormRef.value?.validate((errors) => {
    if (errors) return ''

    passwordChangeSubmitBtnLoading.value = true

    fetchVerifyCode<string>(
      passwordInfoForm.value.verificationMethod === 'email' ? userStore.userInfo.email : userStore.userInfo.mobilePhone,
      passwordInfoForm.value.verifyCode,
    )
      .then((res) => {
        if (res.code !== 0) return ''

        fetchUserPasswordUpdate(res.data, SparkMD5.hash(passwordInfoForm.value.confirmPassword)).then(() => {
          window.$message.success(t('common_module.successful_update'))

          isShowPasswordChangeModal.value = false

          passwordChangeSubmitBtnLoading.value = false
          isShowCountdown.value = false
        })
      })
      .catch(() => {
        passwordChangeSubmitBtnLoading.value = false
      })
  })
}

function onCountdownFinish() {
  isShowCountdown.value = false
}

function handleSMSCodeGain() {
  countdownDuration.value = 60000
  ss.set('PASSWORD_CHANGE_CODE', Date.now())
  countdownRef.value?.reset()
  isShowCountdown.value = true

  if (passwordInfoForm.value.verificationMethod === 'sms') {
    fetchSMSCode(userStore.userInfo.mobilePhone).then((res) => {
      if (res.code !== 0) return ''

      window.$message.success(t('login_module.successful'))
    })
  } else if (passwordInfoForm.value.verificationMethod === 'email') {
    fetchEmailCode(encodeURIComponent(userStore.userInfo.email)).then((res) => {
      if (res.code !== 0) return ''

      window.$message.success(t('login_module.successful'))
    })
  }
}
</script>

<template>
  <n-modal v-model:show="isShowPasswordChangeModal" :mask-closable="false" :on-after-leave="onModalAfterLeave">
    <n-card
      class="!w-[600px]"
      :title="t('personal_settings_module.password_change')"
      :bordered="false"
      size="medium"
      closable
      @close="() => (isShowPasswordChangeModal = false)"
    >
      <n-form
        ref="passwordInfoFormRef"
        label-placement="left"
        label-width="auto"
        :model="passwordInfoForm"
        :rules="passwordFormRules"
      >
        <n-form-item :label="t('personal_settings_module.obtaining_the_verification_code')">
          <div>
            <n-radio-group v-model:value="passwordInfoForm.verificationMethod" name="verificationMethod" size="small">
              <n-radio-button :disabled="verificationMethodDisable.email" value="email">
                {{ t('common_module.email') }}
              </n-radio-button>
              <n-radio-button :disabled="verificationMethodDisable.sms" value="sms">
                {{ t('common_module.sms') }}
              </n-radio-button>
            </n-radio-group>
          </div>
        </n-form-item>

        <n-form-item :label="t('common_module.verificationCode')" path="verifyCode">
          <n-input
            v-model:value="passwordInfoForm.verifyCode"
            :placeholder="t('login_module.please_enter_the_verification_code')"
            :maxlength="6"
          >
            <template #suffix>
              <span class="mx-[10px] inline-block h-[50%] w-[2px] bg-[#e0e0e6]"></span>
              <span
                v-show="!isShowCountdown"
                class="text-theme-color cursor-pointer text-[12px]"
                @click="handleSMSCodeGain"
              >
                {{ t('login_module.get_verification_code') }}
              </span>

              <div v-show="isShowCountdown" class="inline-block w-[50px] text-center">
                <n-countdown
                  ref="countdownRef"
                  :duration="countdownDuration"
                  :active="countdownActive"
                  :render="countdownRender"
                  :on-finish="onCountdownFinish"
                />
              </div>
            </template>
          </n-input>
        </n-form-item>

        <n-form-item :label="t('personal_settings_module.new_password')" path="password">
          <n-input
            v-model:value="passwordInfoForm.password"
            type="password"
            show-password-on="click"
            class="font-sans"
            :placeholder="t('personal_settings_module.please_enter_your_new_password')"
          />
        </n-form-item>
        <n-form-item :label="t('personal_settings_module.confirm_new_password')" path="confirmPassword">
          <n-input
            v-model:value="passwordInfoForm.confirmPassword"
            type="password"
            show-password-on="click"
            class="font-sans"
            :placeholder="t('personal_settings_module.please_enter_confirm_new_password')"
          />
        </n-form-item>
      </n-form>

      <template #footer>
        <div class="text-end">
          <n-space justify="end">
            <n-button @click="() => (isShowPasswordChangeModal = false)">
              {{ t('common_module.cancel_btn_text') }}
            </n-button>
            <n-button type="primary" :loading="passwordChangeSubmitBtnLoading" @click="handlePasswordChangeSubmit">
              {{ t('common_module.confirm_btn_text') }}
            </n-button>
          </n-space>
        </div>
      </template>
    </n-card>
  </n-modal>
</template>
