<template>
  <div class="users-view">
    <a-page-header
      title="用户与会话管理"
      sub-title="管理员可查看和撤销任意用户的会话，并管理用户账号"
      class="users-view__header"
    />

    <a-tabs v-model:activeKey="activeTab" class="users-view__tabs">
      <!-- Tab 1: 按用户查询会话 -->
      <a-tab-pane key="by-user" tab="按用户查询">
        <a-card class="users-view__card">
          <a-space direction="vertical" :size="16" style="width: 100%">
            <a-form layout="inline">
              <a-form-item label="用户 ID">
                <a-input
                  v-model:value="userIdInput"
                  placeholder="输入用户 ID（UUID）"
                  style="width: 360px"
                  allow-clear
                  @press-enter="loadUserSessions"
                />
              </a-form-item>
              <a-form-item>
                <a-button
                  type="primary"
                  :loading="loadingUser"
                  :disabled="!userIdInput.trim()"
                  @click="loadUserSessions"
                >
                  查询会话
                </a-button>
              </a-form-item>
            </a-form>

            <a-alert
              v-if="userQueryError"
              type="error"
              :message="userQueryError"
              show-icon
              closable
              @close="userQueryError = ''"
            />

            <div v-if="selectedUserId" class="users-view__sessions">
              <a-divider orientation="left">
                用户 <code>{{ selectedUserId }}</code> 的会话
              </a-divider>
              <UserSessionsPanel :user-id="selectedUserId" />
            </div>
            <a-empty
              v-else
              description="输入用户 ID 后点击查询，即可查看该用户的所有会话"
            />
          </a-space>
        </a-card>
      </a-tab-pane>

      <!-- Tab 2: 全局会话概览 -->
      <a-tab-pane key="all-sessions" tab="全局会话概览">
        <a-card class="users-view__card">
          <a-space direction="vertical" :size="16" style="width: 100%">
            <a-space :size="8" align="center">
              <a-button :loading="loadingAll" @click="loadAllSessions">刷新</a-button>
              <span class="users-view__count">共 {{ allSessions.length }} 条会话</span>
            </a-space>

            <a-alert
              v-if="allSessionsError"
              type="error"
              :message="allSessionsError"
              show-icon
              closable
              @close="allSessionsError = ''"
            />

            <ActiveSessionsPanel
              :sessions="allSessions"
              :loading="loadingAll"
              :revoking-id="revokingAllId"
              :admin-mode="true"
              @refresh="loadAllSessions"
              @revoke="handleRevokeAll"
            />
          </a-space>
        </a-card>
      </a-tab-pane>

      <!-- Tab 3: 用户管理 -->
      <a-tab-pane key="user-mgmt" tab="用户管理">
        <a-card class="users-view__card">
          <a-space direction="vertical" :size="16" style="width: 100%">
            <a-space :size="8" align="center">
              <a-button type="primary" @click="openCreateUser">
                <PlusOutlined /> 新建用户
              </a-button>
              <a-select
                v-model:value="userDeptFilter"
                placeholder="按部门筛选"
                allow-clear
                style="width: 220px"
                :options="deptFilterOptions"
                @change="loadUsers"
              />
              <a-button :loading="loadingUsers" @click="loadUsers">刷新</a-button>
            </a-space>

            <a-table
              :columns="userColumns"
              :data-source="users"
              :row-key="(record: IAdminUser) => record.id"
              :loading="loadingUsers"
              :pagination="{ pageSize: 20, showSizeChanger: true }"
              size="middle"
            >
              <template #bodyCell="{ column, record }: { column: TableColumnType<IAdminUser>; record: IAdminUser }">
                <template v-if="column.key === 'role'">
                  <a-tag :color="roleColor(record.role)">{{ record.role }}</a-tag>
                </template>
                <template v-else-if="column.key === 'is_active'">
                  <a-tag :color="record.is_active ? 'green' : 'default'">
                    {{ record.is_active ? '活跃' : '停用' }}
                  </a-tag>
                </template>
                <template v-else-if="column.key === 'departments'">
                  <a-space :size="4" wrap>
                    <a-tag v-for="d in record.departments ?? []" :key="d.id" color="blue">
                      {{ d.name }}
                    </a-tag>
                    <span v-if="!record.departments || record.departments.length === 0">—</span>
                  </a-space>
                </template>
                <template v-else-if="column.key === 'created_at'">
                  {{ formatTime(record.created_at) }}
                </template>
                <template v-else-if="column.key === 'actions'">
                  <a-space :size="4">
                    <a-button type="link" size="small" @click="openEditUser(record)">编辑</a-button>
                    <a-button type="link" size="small" @click="openResetPassword(record)">重置密码</a-button>
                    <a-button type="link" size="small" @click="openUserDepts(record)">部门</a-button>
                    <a-popconfirm
                      title="确认删除该用户？用户将被停用。"
                      ok-text="删除"
                      cancel-text="取消"
                      @confirm="handleDeleteUser(record)"
                    >
                      <a-button type="link" danger size="small">删除</a-button>
                    </a-popconfirm>
                  </a-space>
                </template>
              </template>
            </a-table>
          </a-space>
        </a-card>
      </a-tab-pane>
    </a-tabs>

    <!-- Create user modal -->
    <a-modal
      v-model:open="createFormOpen"
      title="新建用户"
      :confirm-loading="creatingUser"
      ok-text="创建"
      cancel-text="取消"
      @ok="handleCreateUser"
    >
      <a-form layout="vertical">
        <a-form-item label="用户名" required>
          <a-input v-model:value="createForm.username" placeholder="输入用户名" :max-length="64" />
        </a-form-item>
        <a-form-item label="邮箱" required>
          <a-input v-model:value="createForm.email" placeholder="输入邮箱" />
        </a-form-item>
        <a-form-item label="密码" required>
          <a-input-password v-model:value="createForm.password" placeholder="输入初始密码" />
        </a-form-item>
        <a-form-item label="角色">
          <a-select v-model:value="createForm.role" :options="roleOptions" />
        </a-form-item>
        <a-form-item label="所属部门">
          <a-select
            v-model:value="createForm.department_ids"
            mode="multiple"
            placeholder="选择部门（可多选）"
            :options="deptSelectOptions"
            allow-clear
          />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Edit user modal -->
    <a-modal
      v-model:open="editFormOpen"
      title="编辑用户"
      :confirm-loading="editingUser"
      ok-text="保存"
      cancel-text="取消"
      @ok="handleEditUser"
    >
      <a-form layout="vertical">
        <a-form-item label="用户名">
          <a-input :value="editForm.username" disabled />
        </a-form-item>
        <a-form-item label="邮箱">
          <a-input :value="editForm.email" disabled />
        </a-form-item>
        <a-form-item label="角色">
          <a-select v-model:value="editForm.role" :options="roleOptions" />
        </a-form-item>
        <a-form-item label="活跃状态">
          <a-switch v-model:checked="editForm.is_active" />
        </a-form-item>
        <a-form-item label="终端授权">
          <a-switch v-model:checked="editForm.is_terminal_authorized" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Reset password modal -->
    <a-modal
      v-model:open="resetFormOpen"
      title="重置密码"
      :confirm-loading="resettingPassword"
      ok-text="重置"
      cancel-text="取消"
      @ok="handleResetPassword"
    >
      <a-alert
        message="重置密码将撤销该用户的所有会话。"
        type="warning"
        show-icon
        style="margin-bottom: 16px"
      />
      <a-form layout="vertical">
        <a-form-item label="用户">
          <a-input :value="resetTarget ? `${resetTarget.username} (${resetTarget.email})` : ''" disabled />
        </a-form-item>
        <a-form-item label="新密码" required>
          <a-input-password v-model:value="resetForm.newPassword" placeholder="输入新密码" />
        </a-form-item>
      </a-form>
    </a-modal>

    <!-- Department assignment drawer -->
    <a-drawer
      v-model:open="deptsDrawerOpen"
      :title="`部门分配 — ${deptsTarget?.username ?? ''}`"
      width="480"
      placement="right"
    >
      <a-spin :spinning="deptsLoading">
        <div class="users-view__dept-assign">
          <a-card title="已分配部门" size="small" style="margin-bottom: 16px">
            <a-empty v-if="userDepts.length === 0" description="暂未分配部门" :image="simpleImage" />
            <a-list v-else size="small" :data-source="userDepts" :bordered="false">
              <template #renderItem="{ item }">
                <a-list-item>
                  <a-space :size="8" style="width: 100%" justify="space-between">
                    <span><ApartmentOutlined /> {{ item.name }}</span>
                    <a-button type="link" danger size="small" @click="handleRemoveDept(item.id)">移除</a-button>
                  </a-space>
                </a-list-item>
              </template>
            </a-list>
          </a-card>
          <a-card title="添加部门" size="small">
            <a-select
              v-model:value="newDeptId"
              placeholder="选择要添加的部门"
              style="width: 100%"
              :options="availableDeptOptions"
              allow-clear
            />
            <a-button
              type="primary"
              block
              style="margin-top: 12px"
              :disabled="!newDeptId"
              @click="handleAssignDept"
            >
              添加
            </a-button>
          </a-card>
        </div>
      </a-spin>
    </a-drawer>
  </div>
</template>

<script setup lang="ts">
/**
 * Admin: user sessions + user account management view (U9).
 *
 * Three tabs:
 * 1. "按用户查询" — enter a user ID, see that user's sessions via
 *    :class:`UserSessionsPanel` (which wraps the shared
 *    :class:`ActiveSessionsPanel` in admin mode).
 * 2. "全局会话概览" — list all recent sessions across the system,
 *    with the ability to revoke any of them.
 * 3. "用户管理" — user account CRUD, reset password, department
 *    assignment.
 *
 * Access to this view is gated by the router (admin role required).
 */
import { ref, reactive, computed, onMounted } from 'vue'
import { message, Empty } from 'ant-design-vue'
import type { TableColumnType } from 'ant-design-vue'
import {
  PlusOutlined,
  ApartmentOutlined,
} from '@ant-design/icons-vue'
import UserSessionsPanel from '@/components/admin/UserSessionsPanel.vue'
import ActiveSessionsPanel from '@/components/settings/ActiveSessionsPanel.vue'
import { adminApi } from '@/api/admin'
import type { IAdminUser, IDepartment } from '@/api/admin'
import type { ISessionInfo } from '@/api/auth'

/** Select option shape used by a-select ``options`` prop. */
interface ISelectOption {
  label: string
  value: string
}

const simpleImage = Empty.PRESENTED_IMAGE_SIMPLE

const activeTab = ref<'by-user' | 'all-sessions' | 'user-mgmt'>('by-user')

// --- Tab 1: by user ---
const userIdInput = ref('')
const selectedUserId = ref('')
const loadingUser = ref(false)
const userQueryError = ref('')

async function loadUserSessions(): Promise<void> {
  const uid = userIdInput.value.trim()
  if (!uid) return
  loadingUser.value = true
  userQueryError.value = ''
  try {
    // Just verify the user exists by listing their sessions; the panel
    // does its own data loading once we set selectedUserId.
    await adminApi.listUserSessions(uid, false)
    selectedUserId.value = uid
  } catch (err) {
    userQueryError.value = _extractMessage(err, '查询用户会话失败（请检查用户 ID 是否正确）')
    selectedUserId.value = ''
  } finally {
    loadingUser.value = false
  }
}

// --- Tab 2: all sessions ---
const allSessions = ref<ISessionInfo[]>([])
const loadingAll = ref(false)
const allSessionsError = ref('')
const revokingAllId = ref<string | null>(null)

async function loadAllSessions(): Promise<void> {
  loadingAll.value = true
  allSessionsError.value = ''
  try {
    allSessions.value = await adminApi.listAllSessions(200)
  } catch (err) {
    allSessionsError.value = _extractMessage(err, '加载全局会话列表失败')
  } finally {
    loadingAll.value = false
  }
}

async function handleRevokeAll(sid: string): Promise<void> {
  // The global overview doesn't have a userId per row in the current
  // ISessionInfo shape — but the server's DELETE /admin/sessions/{sid}
  // endpoint doesn't require a userId. We use the per-user endpoint
  // only when we know the userId. For the global list, find the row.
  const row = allSessions.value.find((s) => s.id === sid)
  if (!row || !row.user_id) {
    message.error('无法撤销：缺少用户 ID 信息')
    return
  }
  revokingAllId.value = sid
  try {
    const result = await adminApi.revokeUserSession(row.user_id, sid)
    if (result.revoked) {
      message.success('已撤销该会话')
    } else {
      message.info('该会话已是撤销状态')
    }
    allSessions.value = allSessions.value.filter((s) => s.id !== sid)
  } catch (err) {
    message.error(_extractMessage(err, '撤销会话失败'))
  } finally {
    revokingAllId.value = null
  }
}

// --- Tab 3: user management ---
const users = ref<IAdminUser[]>([])
const loadingUsers = ref(false)
const userDeptFilter = ref<string | undefined>(undefined)
const allDepartments = ref<IDepartment[]>([])

const userColumns: TableColumnType<IAdminUser>[] = [
  { title: '用户名', key: 'username', dataIndex: 'username', width: 140 },
  { title: '邮箱', key: 'email', dataIndex: 'email', width: 220, ellipsis: true },
  { title: '角色', key: 'role', width: 100 },
  { title: '状态', key: 'is_active', width: 90 },
  { title: '部门', key: 'departments', width: 200 },
  { title: '创建时间', key: 'created_at', width: 170 },
  { title: '操作', key: 'actions', width: 260, fixed: 'right' },
]

const roleOptions: ISelectOption[] = [
  { label: 'member', value: 'member' },
  { label: 'operator', value: 'operator' },
  { label: 'admin', value: 'admin' },
]

const deptFilterOptions = computed<ISelectOption[]>(() =>
  allDepartments.value.map((d) => ({ label: d.name, value: d.id })),
)

const deptSelectOptions = computed<ISelectOption[]>(() =>
  allDepartments.value.map((d) => ({ label: d.name, value: d.id })),
)

function roleColor(role: string): string {
  switch (role) {
    case 'admin':
      return 'red'
    case 'operator':
      return 'orange'
    default:
      return 'blue'
  }
}

async function loadUsers(): Promise<void> {
  loadingUsers.value = true
  try {
    users.value = await adminApi.listUsers(userDeptFilter.value)
  } catch (err) {
    message.error(_extractMessage(err, '加载用户列表失败'))
  } finally {
    loadingUsers.value = false
  }
}

// Create user
const createFormOpen = ref(false)
const creatingUser = ref(false)
const createForm = reactive({
  username: '',
  email: '',
  password: '',
  role: 'member' as string,
  department_ids: [] as string[],
})

function openCreateUser(): void {
  createForm.username = ''
  createForm.email = ''
  createForm.password = ''
  createForm.role = 'member'
  createForm.department_ids = []
  createFormOpen.value = true
}

async function handleCreateUser(): Promise<void> {
  if (!createForm.username.trim() || !createForm.email.trim() || !createForm.password) {
    message.warning('请填写用户名、邮箱和密码')
    return
  }
  creatingUser.value = true
  try {
    await adminApi.createUser({
      username: createForm.username.trim(),
      email: createForm.email.trim(),
      password: createForm.password,
      role: createForm.role,
      department_ids: createForm.department_ids.length ? createForm.department_ids : undefined,
    })
    message.success('用户已创建')
    createFormOpen.value = false
    await loadUsers()
  } catch (err) {
    message.error(_extractMessage(err, '创建用户失败'))
  } finally {
    creatingUser.value = false
  }
}

// Edit user
const editFormOpen = ref(false)
const editingUser = ref(false)
const editForm = reactive({
  id: '',
  username: '',
  email: '',
  role: 'member' as string,
  is_active: true,
  is_terminal_authorized: false,
})

function openEditUser(record: IAdminUser): void {
  editForm.id = record.id
  editForm.username = record.username
  editForm.email = record.email
  editForm.role = record.role
  editForm.is_active = record.is_active
  editForm.is_terminal_authorized = record.is_terminal_authorized
  editFormOpen.value = true
}

async function handleEditUser(): Promise<void> {
  editingUser.value = true
  try {
    await adminApi.updateUser(editForm.id, {
      role: editForm.role,
      is_active: editForm.is_active,
      is_terminal_authorized: editForm.is_terminal_authorized,
    })
    message.success('用户已更新')
    editFormOpen.value = false
    await loadUsers()
  } catch (err) {
    message.error(_extractMessage(err, '更新用户失败'))
  } finally {
    editingUser.value = false
  }
}

// Delete user
async function handleDeleteUser(record: IAdminUser): Promise<void> {
  try {
    await adminApi.deleteUser(record.id)
    message.success('用户已删除')
    await loadUsers()
  } catch (err) {
    message.error(_extractMessage(err, '删除用户失败'))
  }
}

// Reset password
const resetFormOpen = ref(false)
const resettingPassword = ref(false)
const resetTarget = ref<IAdminUser | null>(null)
const resetForm = reactive({ newPassword: '' })

function openResetPassword(record: IAdminUser): void {
  resetTarget.value = record
  resetForm.newPassword = ''
  resetFormOpen.value = true
}

async function handleResetPassword(): Promise<void> {
  if (!resetTarget.value || !resetForm.newPassword) {
    message.warning('请输入新密码')
    return
  }
  resettingPassword.value = true
  try {
    await adminApi.resetPassword(resetTarget.value.id, resetForm.newPassword)
    message.success('密码已重置，该用户的所有会话已撤销')
    resetFormOpen.value = false
  } catch (err) {
    message.error(_extractMessage(err, '重置密码失败'))
  } finally {
    resettingPassword.value = false
  }
}

// Department assignment
const deptsDrawerOpen = ref(false)
const deptsLoading = ref(false)
const deptsTarget = ref<IAdminUser | null>(null)
const userDepts = ref<IDepartment[]>([])
const newDeptId = ref<string | undefined>(undefined)

const availableDeptOptions = computed<ISelectOption[]>(() => {
  const assigned = new Set(userDepts.value.map((d) => d.id))
  return allDepartments.value
    .filter((d) => d.is_active && !assigned.has(d.id))
    .map((d) => ({ label: d.name, value: d.id }))
})

async function openUserDepts(record: IAdminUser): Promise<void> {
  deptsTarget.value = record
  userDepts.value = record.departments ?? []
  newDeptId.value = undefined
  deptsDrawerOpen.value = true
  // Re-fetch the user to get fresh department list
  deptsLoading.value = true
  try {
    const fresh = await adminApi.getUser(record.id)
    userDepts.value = fresh.departments ?? []
  } catch (err) {
    message.error(_extractMessage(err, '加载用户部门信息失败'))
  } finally {
    deptsLoading.value = false
  }
}

async function handleAssignDept(): Promise<void> {
  if (!deptsTarget.value || !newDeptId.value) return
  try {
    await adminApi.assignDepartment(deptsTarget.value.id, newDeptId.value)
    message.success('部门已分配')
    newDeptId.value = undefined
    const fresh = await adminApi.getUser(deptsTarget.value.id)
    userDepts.value = fresh.departments ?? []
    await loadUsers()
  } catch (err) {
    message.error(_extractMessage(err, '分配部门失败'))
  }
}

async function handleRemoveDept(deptId: string): Promise<void> {
  if (!deptsTarget.value) return
  try {
    await adminApi.removeDepartment(deptsTarget.value.id, deptId)
    message.success('部门已移除')
    const fresh = await adminApi.getUser(deptsTarget.value.id)
    userDepts.value = fresh.departments ?? []
    await loadUsers()
  } catch (err) {
    message.error(_extractMessage(err, '移除部门失败'))
  }
}

// --- Helpers ---
function formatTime(iso: string): string {
  if (!iso) return '—'
  try {
    return new Date(iso).toLocaleString('zh-CN', { hour12: false })
  } catch {
    return iso
  }
}

function _extractMessage(err: unknown, fallback: string): string {
  if (err && typeof err === 'object') {
    const obj = err as { detail?: unknown; message?: unknown }
    if (typeof obj.detail === 'string' && obj.detail) return obj.detail
    if (typeof obj.message === 'string' && obj.message) return obj.message
  }
  return fallback
}

async function loadDepartments(): Promise<void> {
  try {
    allDepartments.value = await adminApi.listDepartments()
  } catch (err) {
    message.error(_extractMessage(err, '加载部门列表失败'))
  }
}

onMounted(() => {
  loadAllSessions()
  loadUsers()
  loadDepartments()
})
</script>

<style scoped>
.users-view {
  padding: 24px;
  max-width: 1200px;
  margin: 0 auto;
}

.users-view__header {
  margin-bottom: 16px;
}

.users-view__card {
  margin-top: 8px;
}

.users-view__sessions {
  margin-top: 8px;
}

.users-view__count {
  color: var(--text-secondary, #666);
  font-size: 14px;
}

.users-view__dept-assign {
  display: flex;
  flex-direction: column;
}
</style>
