<script setup>
import { onMounted, ref } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'

import {
  createAdminPasskeyOptions,
  createAdminPasskeyVerify,
  deleteAdminPasskey,
  fetchAdminPasskeys,
  logout,
  reportAdminPasskeyClientError,
  updateAdminPassword,
  updateAdminUsername,
} from '../api/admin'
import { createPasskey, getPasskeyClientErrorMessage, isPasskeyAvailable } from '../utils/passkey'

const username = ref('')
const currentPassword = ref('')
const password = ref('')
const confirmPassword = ref('')
const submitting = ref(false)
const passkeyLoading = ref(false)
const passkeyAddLoading = ref(false)
const passkeyDeviceName = ref('')
const passkeyItems = ref([])
const passkeyRegisterOptions = ref(null)
const passkeyRegisterOptionsAt = ref(0)
const PASSKEY_OPTIONS_PREFETCH_MAX_AGE_MS = 240000

function validateStrongPassword(value) {
  const text = String(value || '')
  if (text.length < 8) return { ok: false, message: '密码长度至少8位' }
  if (text.length > 128) return { ok: false, message: '密码长度不能超过128个字符' }
  if (!/[a-zA-Z]/.test(text) || !/\d/.test(text)) return { ok: false, message: '密码必须包含字母和数字' }
  return { ok: true, message: '' }
}

async function relogin() {
  try {
    await logout()
  } catch {
    // ignore
  } finally {
    window.location.href = '/yuyx'
  }
}

async function saveUsername() {
  const value = username.value.trim()
  if (!value) {
    ElMessage.error('请输入新用户名')
    return
  }

  try {
    await ElMessageBox.confirm(`确定将管理员用户名修改为「${value}」吗？修改后需要重新登录。`, '修改用户名', {
      confirmButtonText: '确认修改',
      cancelButtonText: '取消',
      type: 'warning',
    })
  } catch {
    return
  }

  submitting.value = true
  try {
    await updateAdminUsername(value)
    ElMessage.success('用户名修改成功，请重新登录')
    username.value = ''
    setTimeout(relogin, 1200)
  } catch {
    // handled by interceptor
  } finally {
    submitting.value = false
  }
}

async function savePassword() {
  const currentValue = currentPassword.value
  const value = password.value
  const confirmValue = confirmPassword.value

  if (!currentValue) {
    ElMessage.error('请输入当前密码')
    return
  }

  if (!value) {
    ElMessage.error('请输入新密码')
    return
  }

  const check = validateStrongPassword(value)
  if (!check.ok) {
    ElMessage.error(check.message)
    return
  }

  if (value !== confirmValue) {
    ElMessage.error('两次输入的新密码不一致')
    return
  }

  try {
    await ElMessageBox.confirm('确定修改管理员密码吗？修改后需要重新登录。', '修改密码', {
      confirmButtonText: '确认修改',
      cancelButtonText: '取消',
      type: 'warning',
    })
  } catch {
    return
  }

  submitting.value = true
  try {
    await updateAdminPassword({ currentPassword: currentValue, newPassword: value })
    ElMessage.success('密码修改成功，请重新登录')
    currentPassword.value = ''
    password.value = ''
    confirmPassword.value = ''
    setTimeout(relogin, 1200)
  } catch {
    // handled by interceptor
  } finally {
    submitting.value = false
  }
}

async function loadPasskeys() {
  passkeyLoading.value = true
  try {
    const data = await fetchAdminPasskeys()
    passkeyItems.value = Array.isArray(data?.items) ? data.items : []
    if (passkeyItems.value.length < 3) {
      await prefetchPasskeyRegisterOptions()
    } else {
      passkeyRegisterOptions.value = null
      passkeyRegisterOptionsAt.value = 0
    }
  } catch {
    passkeyItems.value = []
    passkeyRegisterOptions.value = null
    passkeyRegisterOptionsAt.value = 0
  } finally {
    passkeyLoading.value = false
  }
}

function getCachedPasskeyRegisterOptions() {
  if (!passkeyRegisterOptions.value) return null
  if (Date.now() - Number(passkeyRegisterOptionsAt.value || 0) > PASSKEY_OPTIONS_PREFETCH_MAX_AGE_MS) return null
  return passkeyRegisterOptions.value
}

async function prefetchPasskeyRegisterOptions() {
  try {
    const res = await createAdminPasskeyOptions({})
    passkeyRegisterOptions.value = res
    passkeyRegisterOptionsAt.value = Date.now()
  } catch {
    passkeyRegisterOptions.value = null
    passkeyRegisterOptionsAt.value = 0
  }
}

async function addPasskey() {
  if (!isPasskeyAvailable()) {
    ElMessage.error('当前浏览器或环境不支持Passkey（需 HTTPS）')
    return
  }
  if (passkeyItems.value.length >= 3) {
    ElMessage.error('最多可绑定3台设备')
    return
  }

  passkeyAddLoading.value = true
  try {
    let optionsRes = getCachedPasskeyRegisterOptions()
    if (!optionsRes) {
      optionsRes = await createAdminPasskeyOptions({})
    }
    const credential = await createPasskey(optionsRes?.publicKey || {})
    await createAdminPasskeyVerify({ credential, device_name: passkeyDeviceName.value.trim() })
    passkeyRegisterOptions.value = null
    passkeyRegisterOptionsAt.value = 0
    passkeyDeviceName.value = ''
    ElMessage.success('Passkey设备添加成功')
    await loadPasskeys()
  } catch (e) {
    try {
      await reportAdminPasskeyClientError({
        stage: 'register',
        source: 'admin-settings',
        name: e?.name || '',
        message: e?.message || '',
        code: e?.code || '',
        user_agent: navigator.userAgent || '',
      })
    } catch {
      // ignore report failure
    }
    passkeyRegisterOptions.value = null
    passkeyRegisterOptionsAt.value = 0
    await prefetchPasskeyRegisterOptions()
    const data = e?.response?.data
    const message =
      data?.error ||
      getPasskeyClientErrorMessage(e, 'Passkey注册')
    ElMessage.error(message)
  } finally {
    passkeyAddLoading.value = false
  }
}

async function removePasskey(item) {
  try {
    await ElMessageBox.confirm(`确定删除设备「${item?.device_name || '未命名设备'}」吗？`, '删除Passkey设备', {
      confirmButtonText: '删除',
      cancelButtonText: '取消',
      type: 'warning',
    })
  } catch {
    return
  }

  try {
    await deleteAdminPasskey(item.id)
    ElMessage.success('设备已删除')
    await loadPasskeys()
  } catch (e) {
    const data = e?.response?.data
    ElMessage.error(data?.error || '删除失败')
  }
}

onMounted(() => {
  loadPasskeys()
})
</script>

<template>
  <div class="page-stack">
    <div class="app-page-title">
      <h2>设置</h2>
      <span class="app-muted">管理员账号设置</span>
    </div>

    <el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
      <h3 class="section-title">修改管理员用户名</h3>
      <el-form label-width="120px">
        <el-form-item label="新用户名">
          <el-input v-model="username" placeholder="输入新用户名" :disabled="submitting" />
        </el-form-item>
      </el-form>
      <el-button type="primary" :loading="submitting" @click="saveUsername">保存用户名</el-button>
    </el-card>

    <el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
      <h3 class="section-title">修改管理员密码</h3>
      <el-form label-width="120px">
        <el-form-item label="当前密码">
          <el-input
            v-model="currentPassword"
            type="password"
            show-password
            placeholder="输入当前密码"
            :disabled="submitting"
          />
        </el-form-item>

        <el-form-item label="新密码">
          <el-input
            v-model="password"
            type="password"
            show-password
            placeholder="输入新密码"
            :disabled="submitting"
          />
        </el-form-item>

        <el-form-item label="确认新密码">
          <el-input
            v-model="confirmPassword"
            type="password"
            show-password
            placeholder="再次输入新密码"
            :disabled="submitting"
          />
        </el-form-item>
      </el-form>
      <el-button type="primary" :loading="submitting" @click="savePassword">保存密码</el-button>
      <div class="help">建议使用更强密码（至少8位且包含字母与数字）。</div>
    </el-card>

    <el-card shadow="never" :body-style="{ padding: '16px' }" class="card">
      <h3 class="section-title">Passkey设备</h3>
      <el-alert
        type="info"
        :closable="false"
        title="最多可绑定3台设备，可用于管理员无密码登录。"
        show-icon
        class="help-alert"
      />

      <el-form inline>
        <el-form-item label="设备备注">
          <el-input
            v-model="passkeyDeviceName"
            placeholder="例如：值班iPhone / 办公Mac"
            maxlength="40"
            show-word-limit
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" :loading="passkeyAddLoading" @click="addPasskey">添加Passkey设备</el-button>
        </el-form-item>
      </el-form>

      <div v-loading="passkeyLoading">
        <el-empty v-if="passkeyItems.length === 0" description="暂无Passkey设备" />
        <el-table v-else :data="passkeyItems" size="small" style="width: 100%">
          <el-table-column prop="device_name" label="设备备注" min-width="160" />
          <el-table-column prop="credential_id_preview" label="凭据ID" min-width="180" />
          <el-table-column prop="last_used_at" label="最近使用" min-width="140" />
          <el-table-column prop="created_at" label="创建时间" min-width="140" />
          <el-table-column label="操作" width="100" fixed="right">
            <template #default="{ row }">
              <el-button type="danger" text @click="removePasskey(row)">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
      </div>
    </el-card>
  </div>
</template>

<style scoped>
.page-stack {
  display: flex;
  flex-direction: column;
  gap: 14px;
  min-width: 0;
}

.card {
  border-radius: var(--app-radius);
  border: 1px solid var(--app-border);
  background: var(--app-card-bg);
  box-shadow: var(--app-shadow-soft);
}

.section-title {
  margin: 0 0 12px;
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 0.2px;
}

.help {
  margin-top: 10px;
  font-size: 12px;
  color: var(--app-muted);
}

.help-alert {
  margin-bottom: 12px;
}
</style>
