<template>
  <div class="admin-page">
    <section class="card">
      <div class="filter-row">
        <input v-model="filters.search" class="input" type="text" placeholder="搜索用户名 / 邮箱" />
        <select v-model="filters.roleId" class="input">
          <option value="">全部角色</option>
          <option v-for="role in roles" :key="role.id" :value="role.id">
            {{ role.name }}
          </option>
        </select>
        <button class="btn" type="button" @click="loadUsers">查询</button>
        <button class="btn ghost" type="button" @click="loadUsers" :disabled="loading.users">
          {{ loading.users ? '刷新中...' : '刷新列表' }}
        </button>
        <button class="btn primary" type="button" @click="openCreateDialog">新建用户</button>
      </div>
    </section>

    <section class="card table-card">
      <div v-if="loading.users" class="empty">用户列表加载中...</div>
      <div v-else-if="users.length === 0" class="empty">暂无用户</div>
      <div v-else class="table-wrapper">
        <table class="table">
          <thead>
            <tr>
              <th>用户</th>
              <th>邮箱</th>
              <th>角色</th>
              <th style="width: 180px">操作</th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="user in users" :key="user.id">
              <td>
                <div class="user-name">{{ user.username }}</div>
                <div class="user-meta">创建于：{{ formatDate(user.created_at) }}</div>
              </td>
              <td>{{ user.email }}</td>
              <td>
                <div class="role-tags">
                  <span v-for="role in user.roles" :key="role.id">{{ role.name }}</span>
                  <span v-if="!user.roles.length">--</span>
                </div>
              </td>
              <td class="actions">
                <button class="btn small primary" type="button" @click="openEditDialog(user)">
                  编辑
                </button>
                <button class="btn small danger" type="button" @click="deleteUser(user)">
                  删除
                </button>
              </td>
            </tr>
          </tbody>
        </table>
      </div>
    </section>

    <!-- 创建用户 -->
    <div v-if="showCreate" class="modal-mask">
      <div class="modal">
        <div class="modal-header">
          <h3>新建用户</h3>
          <button class="modal-close" type="button" @click="showCreate = false">×</button>
        </div>
        <form class="form" @submit.prevent="submitCreate">
          <label>用户名</label>
          <input v-model="createForm.username" class="input" type="text" required />

          <label>邮箱</label>
          <input v-model="createForm.email" class="input" type="email" required />

          <label>初始密码</label>
          <input v-model="createForm.password" class="input" type="password" required />

          <label>简介</label>
          <textarea v-model="createForm.bio" class="input" rows="2" />

          <label>分配角色</label>
          <div class="role-checkboxes">
            <label v-for="role in roles" :key="role.id">
              <input v-model="createForm.roleIds" type="checkbox" :value="role.id" />
              {{ role.name }}
            </label>
          </div>

          <div class="modal-footer">
            <button class="btn" type="button" @click="showCreate = false" :disabled="loading.create">
              取消
            </button>
            <button class="btn primary" type="submit" :disabled="loading.create">
              {{ loading.create ? '创建中...' : '创建用户' }}
            </button>
          </div>
        </form>
      </div>
    </div>

    <!-- 编辑用户 -->
    <div v-if="showEdit && editingUser" class="modal-mask">
      <div class="modal">
        <div class="modal-header">
          <h3>编辑用户</h3>
          <button class="modal-close" type="button" @click="closeEdit">×</button>
        </div>
        <form class="form" @submit.prevent="submitEdit">
          <label>用户名</label>
          <input v-model="editingUser.username" class="input" type="text" required />

          <label>邮箱</label>
          <input v-model="editingUser.email" class="input" type="email" required />

          <label>简介</label>
          <textarea v-model="editingUser.bio" class="input" rows="2" />

          <label>角色</label>
          <div class="role-checkboxes">
            <label v-for="role in roles" :key="role.id">
              <input v-model="editingUser.roleIds" type="checkbox" :value="role.id" />
              {{ role.name }}
            </label>
          </div>

          <div class="modal-footer">
            <button class="btn" type="button" @click="closeEdit" :disabled="loading.save">
              取消
            </button>
            <button class="btn primary" type="submit" :disabled="loading.save">
              保存
            </button>
          </div>
        </form>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { onMounted, reactive, ref, watch, computed, type Ref } from 'vue'
import { navigateTo } from '#app'
import { useAuth } from '@/composables/useAuth'
import { useAuthToken, useApi } from '@/composables/useApi'

definePageMeta({
  layout: 'admin',
  adminTitle: '用户管理',
  adminSub: '按关键字和角色过滤，支持新增、编辑与删除用户。',
})

interface AdminRole {
  id: number
  name: string
  description?: string | null
  permissions: string[]
}

interface AdminUser {
  id: number
  username: string
  email: string
  bio?: string | null
  roles: AdminRole[]
  created_at?: string
}

interface AdminUsersResponse {
  users?: AdminUser[]
  total?: number
}

interface AdminRolesResponse {
  roles?: AdminRole[]
}

const { token } = useAuthToken()
const { user: authUser, fetchMe } = useAuth() as {
  user: Ref<{ roles?: string[] } | null>
  fetchMe: () => Promise<unknown>
}
const api = useApi()

const hasAccess = ref(false)
const users = ref<AdminUser[]>([])
const roles = ref<AdminRole[]>([])
const loading = reactive({
  users: false,
  create: false,
  save: false,
})

const filters = reactive({
  search: '',
  roleId: '' as string | number,
})

const createForm = reactive({
  username: '',
  email: '',
  password: '',
  bio: '',
  roleIds: [] as number[],
})

const editingUser = ref<{
  id: number
  username: string
  email: string
  bio: string
  roleIds: number[]
} | null>(null)

const showCreate = ref(false)
const showEdit = ref(false)

const isAdmin = computed(() => {
  const rs = authUser.value?.roles
  return Array.isArray(rs) && rs.includes('admin')
})

async function ensureAccess(redirect = true): Promise<boolean> {
  if (!token.value) {
    hasAccess.value = false
    if (redirect) await navigateTo('/login')
    return false
  }
  if (!authUser.value) {
    try {
      await fetchMe()
    } catch (err) {
      console.error('[Admin] fetch user failed', err)
    }
  }
  const ok = isAdmin.value
  hasAccess.value = ok
  if (!ok && redirect) await navigateTo('/')
  return ok
}

function formatDate(value?: string | null): string {
  if (!value) return '--'
  try {
    return new Date(value).toLocaleDateString()
  } catch {
    return '--'
  }
}

async function loadRoles(): Promise<void> {
  if (!hasAccess.value) return
  try {
    const res = (await api.get('/admin/roles')) as AdminRolesResponse
    roles.value = Array.isArray(res.roles) ? res.roles : []
  } catch (err) {
    console.error('[Admin] load roles failed', err)
  }
}

async function loadUsers(): Promise<void> {
  if (!hasAccess.value) return
  loading.users = true
  try {
    const query: Record<string, any> = { limit: 50, offset: 0 }
    const search = filters.search.trim()
    if (search) query.search = search
    const roleId = Number(filters.roleId)
    if (!Number.isNaN(roleId) && roleId > 0) query.role_id = roleId
    const res = (await api.get('/admin/users', query)) as AdminUsersResponse
    users.value = Array.isArray(res.users) ? res.users : []
  } catch (err) {
    console.error('[Admin] load users failed', err)
    alert('加载用户列表失败')
  } finally {
    loading.users = false
  }
}

function resetCreateForm(): void {
  createForm.username = ''
  createForm.email = ''
  createForm.password = ''
  createForm.bio = ''
  createForm.roleIds = []
}

function openCreateDialog(): void {
  resetCreateForm()
  showCreate.value = true
}

function openEditDialog(user: AdminUser): void {
  editingUser.value = {
    id: user.id,
    username: user.username,
    email: user.email,
    bio: user.bio || '',
    roleIds: (user.roles || []).map((r) => r.id),
  }
  showEdit.value = true
}

function closeEdit(): void {
  editingUser.value = null
  showEdit.value = false
}

async function submitCreate(): Promise<void> {
  if (!hasAccess.value) return
  if (!createForm.username.trim() || !createForm.email.trim() || !createForm.password.trim()) {
    alert('请完整填写用户名、邮箱和密码')
    return
  }
  loading.create = true
  try {
    await api.post('/admin/users', {
      user: {
        username: createForm.username.trim(),
        email: createForm.email.trim(),
        password: createForm.password,
        bio: createForm.bio,
        role_ids: createForm.roleIds,
      },
    })
    resetCreateForm()
    showCreate.value = false
    await loadUsers()
  } catch (err: any) {
    console.error('[Admin] create user failed', err)
    alert(err?.statusMessage || '创建用户失败')
  } finally {
    loading.create = false
  }
}

async function submitEdit(): Promise<void> {
  if (!hasAccess.value || !editingUser.value) return
  loading.save = true
  try {
    await api.put(`/admin/users/${editingUser.value.id}`, {
      user: {
        username: editingUser.value.username,
        email: editingUser.value.email,
        bio: editingUser.value.bio,
        role_ids: editingUser.value.roleIds,
      },
    })
    closeEdit()
    await loadUsers()
  } catch (err: any) {
    console.error('[Admin] save user failed', err)
    alert(err?.statusMessage || '保存用户失败')
  } finally {
    loading.save = false
  }
}

async function deleteUser(user: AdminUser): Promise<void> {
  if (!hasAccess.value || !user?.id) return
  if (!confirm(`确定删除用户 ${user.username} 吗？`)) return
  try {
    await api.del(`/admin/users/${user.id}`)
    await loadUsers()
  } catch (err: any) {
    console.error('[Admin] delete user failed', err)
    alert(err?.statusMessage || '删除用户失败')
  }
}

onMounted(async () => {
  if (await ensureAccess(true)) {
    await Promise.all([loadRoles(), loadUsers()])
  }
})

watch(
  () => authUser.value?.roles,
  async () => {
    if (await ensureAccess(false)) {
      await Promise.all([loadRoles(), loadUsers()])
    }
  },
)
</script>

<style scoped>
.admin-page {
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.card {
  background: #ffffff;
  border-radius: 16px;
  border: 1px solid #e5e7eb;
  padding: 14px 16px;
  box-shadow: 0 12px 32px rgba(15, 23, 42, 0.08);
}

.filter-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}

.input {
  padding: 8px 10px;
  border-radius: 10px;
  border: 1px solid #d1d5db;
  min-width: 180px;
  font-size: 14px;
  background: #fff;
}

.btn {
  padding: 8px 14px;
  border-radius: 999px;
  border: 1px solid #d1d5db;
  background: #fff;
  cursor: pointer;
  transition: all 0.18s ease;
}

.btn.primary {
  background: #111827;
  color: #fff;
  border-color: #111827;
}

.btn.ghost {
  border-color: #e5e7eb;
  background: #fff;
}

.btn.danger {
  color: #b91c1c;
  border-color: #fecdd3;
  background: #fff5f5;
}

.btn.small {
  padding: 6px 10px;
  font-size: 13px;
}

.table-card {
  padding: 10px 12px;
}

.table-wrapper {
  overflow-x: auto;
}

.table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}

.table th,
.table td {
  padding: 9px 10px;
  border-bottom: 1px solid #f3f4f6;
  text-align: left;
}

.table th {
  color: #6b7280;
  font-size: 13px;
  font-weight: 500;
}

.user-name {
  font-weight: 600;
  color: #0f172a;
}

.user-meta {
  margin-top: 2px;
  color: #9ca3af;
  font-size: 12px;
}

.role-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.role-tags span {
  padding: 3px 8px;
  background: #eef2ff;
  color: #4338ca;
  border-radius: 999px;
  font-size: 12px;
}

.actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.empty {
  padding: 18px 6px;
  text-align: center;
  color: #9ca3af;
}

.modal-mask {
  position: fixed;
  inset: 0;
  background: rgba(15, 23, 42, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 30;
}

.modal {
  width: min(520px, 94vw);
  background: #fff;
  border-radius: 16px;
  padding: 16px;
  box-shadow: 0 24px 60px rgba(15, 23, 42, 0.45);
  display: flex;
  flex-direction: column;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 10px;
}

.modal-close {
  background: none;
  border: none;
  font-size: 20px;
  cursor: pointer;
  color: #6b7280;
}

.form {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.form label {
  font-size: 13px;
  color: #6b7280;
}

.role-checkboxes {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 12px;
  font-size: 13px;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}
</style>
