<script setup lang="ts">
import { onMounted, reactive, ref } from 'vue'
import type { AuthUser, UserRole, UserStatus } from '../auth'
import { currentUser } from '../auth'
import { createUser, fetchUsers, removeUser, updateUser } from '../api/adminUsers'

const users = ref<AuthUser[]>([])
const loading = ref(true)
const busyId = ref<number | null>(null)
const error = ref('')
const notice = ref('')
const resetUserId = ref<number | null>(null)
const resetPassword = ref('')
const form = reactive({
  username: '',
  display_name: '',
  password: '',
  role: 'user' as UserRole,
})

async function load() {
  loading.value = true
  error.value = ''
  try {
    users.value = await fetchUsers()
  } catch (cause) {
    error.value = cause instanceof Error ? cause.message : String(cause)
  } finally {
    loading.value = false
  }
}

async function submit() {
  error.value = ''
  notice.value = ''
  try {
    await createUser(form)
    notice.value = `账号 ${form.username} 已创建`
    Object.assign(form, { username: '', display_name: '', password: '', role: 'user' })
    await load()
  } catch (cause) {
    error.value = cause instanceof Error ? cause.message : String(cause)
  }
}

async function changeUser(user: AuthUser, payload: { role?: UserRole; status?: UserStatus }) {
  busyId.value = user.id
  error.value = ''
  try {
    await updateUser(user.id, payload)
    await load()
  } catch (cause) {
    error.value = cause instanceof Error ? cause.message : String(cause)
  } finally {
    busyId.value = null
  }
}

async function savePassword(user: AuthUser) {
  busyId.value = user.id
  error.value = ''
  try {
    await updateUser(user.id, { password: resetPassword.value })
    resetUserId.value = null
    resetPassword.value = ''
    notice.value = `${user.display_name} 的密码已重置`
  } catch (cause) {
    error.value = cause instanceof Error ? cause.message : String(cause)
  } finally {
    busyId.value = null
  }
}

async function deleteAccount(user: AuthUser) {
  if (!window.confirm(`确认删除账号“${user.username}”吗？此操作不可恢复。`)) return
  busyId.value = user.id
  error.value = ''
  try {
    await removeUser(user.id)
    notice.value = `账号 ${user.username} 已删除`
    await load()
  } catch (cause) {
    error.value = cause instanceof Error ? cause.message : String(cause)
  } finally {
    busyId.value = null
  }
}

function readableTime(value: string | null): string {
  if (!value) return '从未登录'
  return value.replace('T', ' ').slice(0, 16)
}

onMounted(load)
</script>

<template>
  <main class="users-page">
    <header>
      <div>
        <span>ACCESS CONTROL</span>
        <h1>用户管理</h1>
        <p>创建本地账号，并在管理员和普通用户两个固定角色间分配权限。</p>
      </div>
      <div class="role-note">
        <strong>{{ users.length }}</strong>
        <span>系统账号</span>
      </div>
    </header>

    <p v-if="error" class="message error" role="alert">{{ error }}</p>
    <p v-if="notice" class="message success">{{ notice }}</p>

    <section class="create-card">
      <div>
        <span>NEW ACCOUNT</span>
        <h2>创建用户</h2>
      </div>
      <form @submit.prevent="submit">
        <label><span>用户名</span><input v-model.trim="form.username" minlength="3" maxlength="64" pattern="[A-Za-z0-9_.-]+" required /></label>
        <label><span>显示名称</span><input v-model.trim="form.display_name" maxlength="128" required /></label>
        <label><span>初始密码</span><input v-model="form.password" type="password" minlength="8" maxlength="128" autocomplete="new-password" required /></label>
        <label>
          <span>角色</span>
          <select v-model="form.role">
            <option value="user">普通用户</option>
            <option value="admin">管理员</option>
          </select>
        </label>
        <button>创建账号</button>
      </form>
    </section>

    <section class="list-card">
      <div class="list-head">
        <div><span>ACCOUNT DIRECTORY</span><h2>全部用户</h2></div>
        <button type="button" @click="load">刷新</button>
      </div>
      <p v-if="loading" class="empty">正在加载用户…</p>
      <div v-else class="user-list">
        <article v-for="user in users" :key="user.id" class="user-row">
          <span class="avatar">{{ user.display_name.slice(0, 1).toUpperCase() }}</span>
          <div class="identity">
            <strong>{{ user.display_name }}</strong>
            <small>@{{ user.username }} · {{ readableTime(user.last_login_at) }}</small>
          </div>
          <select
            :value="user.role"
            :disabled="busyId === user.id || currentUser?.id === user.id"
            aria-label="用户角色"
            @change="changeUser(user, { role: ($event.target as HTMLSelectElement).value as UserRole })"
          >
            <option value="user">普通用户</option>
            <option value="admin">管理员</option>
          </select>
          <button
            class="status"
            :class="user.status"
            :disabled="busyId === user.id || currentUser?.id === user.id"
            @click="changeUser(user, { status: user.status === 'active' ? 'disabled' : 'active' })"
          >
            {{ user.status === 'active' ? '已启用' : '已禁用' }}
          </button>
          <button
            class="link"
            :disabled="currentUser?.id === user.id"
            @click="resetUserId = resetUserId === user.id ? null : user.id"
          >
            重置密码
          </button>
          <button class="link danger" :disabled="currentUser?.id === user.id" @click="deleteAccount(user)">删除</button>
          <form v-if="resetUserId === user.id" class="reset-form" @submit.prevent="savePassword(user)">
            <input v-model="resetPassword" type="password" minlength="8" maxlength="128" placeholder="输入至少 8 位的新密码" autocomplete="new-password" required />
            <button :disabled="busyId === user.id">保存新密码</button>
          </form>
        </article>
        <p v-if="!users.length" class="empty">暂无用户</p>
      </div>
    </section>
  </main>
</template>

<style scoped>
.users-page { max-width: 1180px; margin: 0 auto; padding: 12px 0 60px; color: #303747; }
header { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 24px; }
header > div > span, .create-card > div > span, .list-head span { color: #6869cf; font-size: 10px; font-weight: 800; letter-spacing: .14em; }
h1 { margin: 7px 0; font-size: 30px; letter-spacing: -.035em; }
header p { margin: 0; color: #7b8392; font-size: 13px; }
.role-note { display: flex; min-width: 100px; padding: 13px 16px; flex-direction: column; border: 1px solid #e0e3e9; border-radius: 12px; background: #fff; }
.role-note strong { font-size: 22px; }.role-note span { color: #8a919d; font-size: 10px; }
.message { padding: 11px 14px; border-radius: 9px; font-size: 12px; }
.message.error { border: 1px solid #f0c4cb; background: #fff3f4; color: #b4233b; }
.message.success { border: 1px solid #bce5d3; background: #effbf6; color: #147653; }
.create-card, .list-card { border: 1px solid #e0e3e9; border-radius: 14px; background: #fff; box-shadow: 0 10px 30px rgba(35,42,62,.04); }
.create-card { display: grid; grid-template-columns: 150px 1fr; gap: 26px; padding: 20px; }
h2 { margin: 5px 0 0; font-size: 17px; }
.create-card form { display: grid; grid-template-columns: 1fr 1fr 1fr 150px auto; gap: 10px; align-items: end; }
label { display: grid; gap: 6px; } label span { color: #667080; font-size: 10px; font-weight: 700; }
input, select { height: 39px; padding: 0 11px; border: 1px solid #d8dce5; border-radius: 8px; background: #fff; color: #384050; font: inherit; font-size: 12px; }
button { height: 39px; padding: 0 15px; border: 0; border-radius: 8px; background: #5d5ec9; color: #fff; font-size: 11px; font-weight: 700; cursor: pointer; }
button:disabled { cursor: not-allowed; opacity: .45; }
.list-card { margin-top: 18px; padding: 20px; }
.list-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.list-head button { height: 32px; background: #f0f1f6; color: #596171; }
.user-list { display: grid; gap: 8px; }
.user-row { display: grid; grid-template-columns: 38px minmax(180px, 1fr) 125px 82px auto auto; gap: 10px; align-items: center; padding: 12px; border: 1px solid #e8eaf0; border-radius: 10px; }
.avatar { display: grid; width: 36px; height: 36px; place-items: center; border-radius: 10px; background: #ececff; color: #5b5cc7; font-size: 13px; font-weight: 800; }
.identity strong, .identity small { display: block; }.identity strong { font-size: 12px; }.identity small { margin-top: 4px; color: #8a919d; font-size: 10px; }
.status { height: 32px; padding: 0 10px; }.status.active { background: #eaf8f2; color: #18815e; }.status.disabled { background: #f3f4f6; color: #737b88; }
.link { height: 32px; padding: 0 5px; background: transparent; color: #5d5ec9; }.link.danger { color: #bd4051; }
.reset-form { grid-column: 2 / -1; display: flex; gap: 8px; padding-top: 4px; }.reset-form input { min-width: 260px; }.reset-form button { height: 39px; }
.empty { padding: 30px; color: #8a919d; text-align: center; font-size: 12px; }
@media (max-width: 980px) {
  .create-card { grid-template-columns: 1fr; }
  .create-card form { grid-template-columns: 1fr 1fr; }
  .user-row { grid-template-columns: 38px 1fr 120px; }
  .user-row > button, .user-row > select { grid-column: auto; }
  .reset-form { grid-column: 1 / -1; }
}
</style>
