<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { fetchUpdateMyPassword } from '@/service/api';
import { useAuthStore } from '@/store/modules/auth';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';

defineOptions({ name: 'ProfilePasswordDialog' });

interface Props {
  username?: string | null;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'submitted'): void;
}

const emit = defineEmits<Emits>();

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

const authStore = useAuthStore();
const { formRef, validate } = useForm();
const { createRequiredRule, createConfirmPwdRule, patternRules } = useFormRules();

const submitting = ref(false);

const model = ref({
  oldPassword: '',
  newPassword: '',
  confirmPassword: ''
});

const confirmDisabled = computed(() => {
  return (
    submitting.value ||
    !model.value.oldPassword.trim() ||
    !model.value.newPassword.trim() ||
    !model.value.confirmPassword.trim()
  );
});

const rules = computed<Record<string, App.Global.FormRule[]>>(() => ({
  oldPassword: [createRequiredRule('请输入旧密码')],
  newPassword: [
    createRequiredRule('请输入新密码'),
    patternRules.pwd,
    {
      asyncValidator: (_rule, value: string) => {
        if (value.trim() !== '' && value === model.value.oldPassword) {
          return Promise.reject(new Error('新密码不能与旧密码相同'));
        }

        return Promise.resolve();
      },
      trigger: 'change'
    }
  ],
  confirmPassword: createConfirmPwdRule(model.value.newPassword)
}));

const displayUsername = computed(() => props.username?.trim() || '--');

function initModel() {
  model.value.oldPassword = '';
  model.value.newPassword = '';
  model.value.confirmPassword = '';
}

function closeDialog() {
  visible.value = false;
}

async function handleSubmit() {
  if (confirmDisabled.value) {
    return;
  }

  await validate();

  submitting.value = true;

  const { error } = await fetchUpdateMyPassword({
    oldPassword: model.value.oldPassword.trim(),
    newPassword: model.value.newPassword.trim()
  });

  submitting.value = false;

  if (error) {
    return;
  }

  window.$message?.success('密码修改成功，请重新登录');
  closeDialog();
  emit('submitted');
  await authStore.resetStore();
}

watch(visible, async value => {
  if (!value) {
    return;
  }

  initModel();
  await nextTick();
  formRef.value?.clearValidate();
});
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    title="修改密码"
    preset="sm"
    :confirm-loading="submitting"
    :confirm-disabled="confirmDisabled"
    @confirm="handleSubmit"
  >
    <ElForm ref="formRef" :model="model" :rules="rules" label-position="top" autocomplete="off">
      <input class="business-form-autofill-guard" type="text" name="fake-username" autocomplete="username" />
      <input class="business-form-autofill-guard" type="password" name="fake-password" autocomplete="new-password" />

      <ElRow :gutter="16">
        <ElCol :span="24">
          <ElFormItem label="用户名">
            <ElInput :model-value="displayUsername" disabled />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElAlert title="密码修改后会退出当前登录态，请使用新密码重新登录。" type="info" :closable="false" show-icon />
        </ElCol>
        <ElCol :span="24">
          <ElFormItem label="旧密码" prop="oldPassword">
            <ElInput
              v-model="model.oldPassword"
              show-password
              autocomplete="current-password"
              placeholder="请输入旧密码"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem label="新密码" prop="newPassword">
            <ElInput v-model="model.newPassword" show-password autocomplete="new-password" placeholder="请输入新密码" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem label="确认新密码" prop="confirmPassword">
            <ElInput
              v-model="model.confirmPassword"
              show-password
              autocomplete="new-password"
              placeholder="请再次输入新密码"
            />
          </ElFormItem>
        </ElCol>
      </ElRow>
    </ElForm>
  </BusinessFormDialog>
</template>

<style scoped>
.business-form-autofill-guard {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
  opacity: 0;
  pointer-events: none;
}
</style>
