<script setup>
import { reactive, ref } from 'vue';
import { api } from '@/lib/api';
import { sessionStore } from '@/stores/session';
import { uiStore } from '@/stores/ui';
import StatusBadge from './StatusBadge.vue';

const props = defineProps({ status: { type: Object, default: () => ({}) } });
const emit = defineEmits(['updated']);
const busy = ref(false);
const error = ref('');
const setup = ref(null);
const recoveryCodes = ref([]);
const password = reactive({ currentPassword: '', newPassword: '', confirmPassword: '' });
const setupPassword = ref('');
const enableCode = ref('');
const protectedAction = reactive({ currentPassword: '', code: '' });

async function run(action) {
  busy.value = true;
  error.value = '';
  try { await action(); }
  catch (requestError) { error.value = requestError.message; }
  finally { busy.value = false; }
}

function changePassword() {
  return run(async () => {
    if (password.newPassword !== password.confirmPassword) throw new Error('两次输入的新密码不一致');
    await api('/api/auth/change-password', { method: 'POST', body: password });
    Object.assign(password, { currentPassword: '', newPassword: '', confirmPassword: '' });
    uiStore.notify('密码修改成功', '下次登录请使用新密码');
  });
}

function beginSetup() {
  return run(async () => {
    setup.value = await api('/api/auth/totp/setup', { method: 'POST', body: { currentPassword: setupPassword.value } });
    setupPassword.value = '';
  });
}

function enableTotp() {
  return run(async () => {
    const response = await api('/api/auth/totp/enable', { method: 'POST', body: { code: enableCode.value } });
    recoveryCodes.value = response.recoveryCodes || [];
    setup.value = null;
    enableCode.value = '';
    await sessionStore.refreshSession();
    emit('updated');
    uiStore.notify('二次验证已开启', '请立即保存恢复码');
  });
}

function regenerateCodes() {
  return run(async () => {
    const response = await api('/api/auth/totp/recovery-codes', { method: 'POST', body: protectedAction });
    recoveryCodes.value = response.recoveryCodes || [];
    Object.assign(protectedAction, { currentPassword: '', code: '' });
    emit('updated');
  });
}

function disableTotp() {
  return run(async () => {
    await api('/api/auth/totp/disable', { method: 'POST', body: protectedAction });
    Object.assign(protectedAction, { currentPassword: '', code: '' });
    recoveryCodes.value = [];
    await sessionStore.refreshSession();
    emit('updated');
    uiStore.notify('二次验证已关闭', '账户现在仅使用密码登录');
  });
}

async function copyCodes() {
  await navigator.clipboard.writeText(recoveryCodes.value.join('\n'));
  uiStore.notify('恢复码已复制', '请保存到安全的位置');
}
</script>

<template>
  <div class="security-stack">
    <div v-if="error" class="form-error">{{ error }}</div>
    <section v-if="recoveryCodes.length" class="recovery-code-panel">
      <div><p>账户恢复</p><h2>立即保存恢复码</h2><span>每个恢复码只能使用一次，关闭页面后系统不会再次展示本组代码。</span></div>
      <div class="recovery-code-grid"><code v-for="code in recoveryCodes" :key="code">{{ code }}</code></div>
      <button class="app-button app-button--primary" type="button" @click="copyCodes">复制全部恢复码</button>
    </section>

    <form class="business-form security-card" @submit.prevent="changePassword">
      <header><div><p>登录安全</p><h2>修改登录密码</h2></div><StatusBadge value="active" /></header>
      <span>账号：{{ sessionStore.state.user?.username || sessionStore.state.user?.candidateNumber }}。新密码至少 8 位，并应与当前密码不同。</span>
      <label><span>当前密码</span><input v-model="password.currentPassword" type="password" autocomplete="current-password" required></label>
      <label><span>新密码</span><input v-model="password.newPassword" type="password" autocomplete="new-password" minlength="8" required></label>
      <label><span>再次输入新密码</span><input v-model="password.confirmPassword" type="password" autocomplete="new-password" minlength="8" required></label>
      <button class="app-button app-button--primary" :disabled="busy">保存新密码</button>
    </form>

    <section class="business-form security-card">
      <header><div><p>二次验证</p><h2>动态验证码（TOTP）</h2></div><StatusBadge :value="status.enabled ? 'active' : 'disabled'" /></header>
      <template v-if="!status.enabled && !setup">
        <span>使用验证器应用生成的动态验证码，为账号增加独立于密码的第二层保护。</span>
        <form class="inline-security-form" @submit.prevent="beginSetup"><label><span>确认当前密码</span><input v-model="setupPassword" type="password" autocomplete="current-password" required></label><button class="app-button app-button--primary" :disabled="busy">开始绑定验证器</button></form>
      </template>
      <template v-else-if="setup">
        <div class="totp-setup-grid"><img :src="setup.qrCode" alt="TOTP 绑定二维码" width="220" height="220"><div><span>无法扫码时手动输入密钥</span><code>{{ setup.secret?.match(/.{1,4}/g)?.join(' ') || setup.secret }}</code><small>基于时间 · 6 位 · 每 30 秒更新</small></div></div>
        <form class="inline-security-form" @submit.prevent="enableTotp"><label><span>验证器中的 6 位验证码</span><input v-model="enableCode" inputmode="numeric" autocomplete="one-time-code" pattern="[0-9]{6}" maxlength="6" required></label><button class="app-button app-button--primary" :disabled="busy">验证并启用</button></form>
      </template>
      <template v-else>
        <span>二次验证正在保护此账号，当前剩余 {{ status.recoveryCodesRemaining }} 个恢复码。</span>
        <div class="security-protected-actions">
          <label><span>当前密码</span><input v-model="protectedAction.currentPassword" type="password" autocomplete="current-password"></label>
          <label><span>动态验证码或恢复码</span><input v-model="protectedAction.code" autocomplete="one-time-code"></label>
          <div><button class="app-button" type="button" :disabled="busy" @click="regenerateCodes">重新生成恢复码</button><button class="app-button app-button--danger" type="button" :disabled="busy" @click="disableTotp">关闭二次验证</button></div>
        </div>
      </template>
    </section>
  </div>
</template>
