<template>
  <a-form
    class="w-full md:w-full mt-3"
    :model="password"
    @submit="modifyPassword"
  >
    <a-form-item
      label="旧密码"
      field="oldPassword"
      label-col-flex="80px"
      :rules="[{ required: true, message: '旧密码必填' }]"
    >
      <a-input-password
        v-model="password.oldPassword"
        allow-clear
        autocomplete="off"
      />
    </a-form-item>
    <a-form-item
      label="新密码"
      field="newPassword"
      label-col-flex="80px"
      :rules="[
        { required: true, message: '新密码必填' },
        { validator: validatePassword },
      ]"
    >
      <a-input-password
        v-model="password.newPassword"
        @input="checkSafe"
        @clear="() => (passwordSafePercent = 0)"
        autocomplete="off"
        allow-clear
      />
    </a-form-item>
    <a-form-item label="密码安全" label-col-flex="80px">
      <a-progress
        :steps="3"
        status="success"
        :percent="passwordSafePercent"
        animation
        :show-text="false"
      />
    </a-form-item>
    <a-form-item
      label="确认密码"
      field="newPassword_confirmation"
      label-col-flex="80px"
      :rules="[{ required: true, message: '确认密码必填' }]"
    >
      <a-input-password
        allow-clear
        v-model="password.newPassword_confirmation"
        autocomplete="off"
      />
    </a-form-item>
    <a-form-item label-col-flex="80px">
      <a-button html-type="submit" type="primary">保存</a-button>
    </a-form-item>
  </a-form>

  <a-modal v-model:visible="visible" @ok="resetLogin">
    <template #title>提示</template>
    密码已经修改成功，需要重新登录系统，点击确定跳转登录页面。
  </a-modal>
</template>

<script setup>
import { ref, reactive } from "vue";
import { Message } from "@arco-design/web-vue";
import user from "@/api/system/user";
import tool from "@/utils/tool";
import { useRouter } from "vue-router";
import zxcvbn from "zxcvbn";

const router = useRouter();
const password = reactive({
  oldPassword: "",
  newPassword: "",
  newPassword_confirmation: "",
});

const visible = ref(false);
const passwordSafePercent = ref(0);

// zxcvbn 警告信息中文映射
const warningTranslations = {
  "Straight rows of keys are easy to guess": "键盘上连续的按键容易被猜到",
  "Short keyboard patterns are easy to guess": "简短的键盘模式容易被猜到",
  "Use a longer keyboard pattern with more turns": "使用更长且更复杂的键盘模式",
  'Repeats like "aaa" are easy to guess': '像 "aaa" 这样的重复字符容易被猜到',
  'Repeats like "abcabcabc" are only slightly harder to guess than "abc"':
    '像 "abcabcabc" 这样的重复模式只比 "abc" 稍难猜一点',
  "Sequences like abc or 6543 are easy to guess":
    "像 abc 或 6543 这样的序列容易被猜到",
  "Recent years are easy to guess": "近期的年份容易被猜到",
  "Dates are often easy to guess": "日期通常容易被猜到",
  "This is a top-10 common password": "这是最常用的10个密码之一",
  "This is a top-100 common password": "这是最常用的100个密码之一",
  "This is a very common password": "这是一个非常常见的密码",
  "This is similar to a commonly used password": "这与常用密码相似",
  "A word by itself is easy to guess": "单个单词容易被猜到",
  "Names and surnames by themselves are easy to guess": "单独的姓名容易被猜到",
  "Common names and surnames are easy to guess": "常见的姓名容易被猜到",
};

// zxcvbn 建议信息中文映射
const suggestionTranslations = {
  "Use a few words, avoid common phrases": "使用几个单词，避免常见短语",
  "No need for symbols, digits, or uppercase letters":
    "不需要符号、数字或大写字母",
  "Add another word or two. Uncommon words are better.":
    "添加一两个单词，不常见的单词更好",
  "Capitalization doesn't help very much": "大写字母帮助不大",
  "All-uppercase is almost as easy to guess as all-lowercase":
    "全大写几乎和全小写一样容易猜到",
  "Reversed words aren't much harder to guess": "颠倒的单词不会更难猜",
  "Predictable substitutions like '@' instead of 'a' don't help very much":
    "像用 '@' 代替 'a' 这样的替换帮助不大",
  "Use a longer keyboard pattern with more turns": "使用更长且更复杂的键盘模式",
  "Avoid repeated words and characters": "避免重复的单词和字符",
  "Avoid sequences": "避免使用序列",
  "Avoid recent years": "避免使用近期年份",
  "Avoid years that are associated with you": "避免使用与你相关的年份",
  "Avoid dates and years that are associated with you":
    "避免使用与你相关的日期和年份",
};

// 翻译函数
const translateText = (text, translations) => {
  return translations[text] || text;
};

// 密码强度验证器
const validatePassword = (value, callback) => {
  if (!value) {
    callback("密码不能为空");
    return;
  }

  // 最小长度检查
  if (value.length < 8) {
    callback("密码长度至少为8位");
    return;
  }

  // 使用 zxcvbn 评估密码强度
  const result = zxcvbn(value);

  // zxcvbn 返回分数 0-4，我们要求至少为 2
  // 0: 太容易被猜到 (如 123456, password)
  // 1: 很容易被猜到
  // 2: 有些容易被猜到 (最低要求)
  // 3: 安全地猜测
  // 4: 非常难以猜测
  if (result.score < 2) {
    // 翻译反馈信息
    const warningText = result.feedback.warning || "密码过于简单，容易被破解";
    const feedback = translateText(warningText, warningTranslations);

    // 翻译建议信息
    let suggestions = "建议使用字母、数字和特殊字符的组合，避免使用常见密码";
    if (result.feedback.suggestions.length > 0) {
      const translatedSuggestions = result.feedback.suggestions.map((s) =>
        translateText(s, suggestionTranslations)
      );
      suggestions = "建议：" + translatedSuggestions.join("；");
    }

    callback(`${feedback}。${suggestions}`);
    return;
  }

  callback();
};

const resetLogin = () => {
  router.push({ name: "login" });
};

const modifyPassword = async (data) => {
  if (!data.errors) {
    if (data.values.newPassword !== data.values.newPassword_confirmation) {
      Message.error("确认密码与新密码不一致");
      return;
    }

    const response = await user.modifyPassword(data.values);
    if (response.code === 200) {
      tool.local.clear();
      visible.value = true;
    } else {
      Message.error(response.message);
    }
  }
};

const checkSafe = (password) => {
  if (password.length < 1) {
    passwordSafePercent.value = 0;
    return;
  }

  // 使用 zxcvbn 评估密码强度
  const result = zxcvbn(password);

  // 将 zxcvbn 的分数 (0-4) 转换为百分比
  // 0: 0%
  // 1: 0.25 (25%)
  // 2: 0.5 (50%)
  // 3: 0.75 (75%)
  // 4: 1.0 (100%)
  passwordSafePercent.value = result.score * 0.25;
};
</script>
