import { query } from '../db/client.js' type AdminUserRow = { id: number username: string password_hash: string role: string status: string session_version: number created_at: string updated_at: string } type AdminUserCreateInput = { username: string passwordHash: string role: string status: string createdAt: string updatedAt: string } type AdminUserPatch = Partial> type AdminUserListInput = { page?: number pageSize?: number username?: string role?: string status?: string } type AdminUserListResult = { items: AdminUserRow[] total: number } const ADMIN_USER_SELECT = ` SELECT au.* FROM admin_users au ` export async function getAdminUserById(userId: number | string): Promise { const result = await query( `${ADMIN_USER_SELECT} WHERE au.id = $1 LIMIT 1`, [Number(userId)], ) return result.rows[0] || null } export async function getAdminUserByUsername(username: string): Promise { const result = await query( `${ADMIN_USER_SELECT} WHERE au.username = $1 LIMIT 1`, [String(username || '').trim().toLowerCase()], ) return result.rows[0] || null } export async function createAdminUser(input: AdminUserCreateInput): Promise { const result = await query<{ [column: string]: unknown, id: number }>( ` INSERT INTO admin_users ( username, password_hash, role, status, session_version, created_at, updated_at ) VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING id `, [ input.username, input.passwordHash, input.role, input.status, 1, input.createdAt, input.updatedAt, ], ) return getAdminUserById(result.rows[0]?.id || 0) } export async function updateAdminUser( userId: number | string, patch: AdminUserPatch, ): Promise { const current = await getAdminUserById(userId) if (!current) { return null } const next = { ...current, ...patch } const result = await query<{ [column: string]: unknown, id: number }>( ` UPDATE admin_users SET username = $1, password_hash = $2, role = $3, status = $4, session_version = $5, updated_at = $6 WHERE id = $7 RETURNING id `, [ next.username, next.password_hash, next.role, next.status, Number(next.session_version || 1), next.updated_at, Number(userId), ], ) return getAdminUserById(result.rows[0]?.id || 0) } export async function listAdminUsers({ page = 1, pageSize = 20, username = '', role = '', status = '', }: AdminUserListInput = {}): Promise { const offset = (page - 1) * pageSize const filters: string[] = [] const params: unknown[] = [] if (username) { params.push(`%${username}%`) filters.push(`username ILIKE $${params.length}`) } if (role) { params.push(role) filters.push(`role = $${params.length}`) } if (status) { params.push(status) filters.push(`status = $${params.length}`) } const whereClause = filters.length > 0 ? `WHERE ${filters.join(' AND ')}` : '' const totalResult = await query<{ [column: string]: unknown, total: number }>( `SELECT COUNT(*)::int AS total FROM admin_users ${whereClause}`, params, ) params.push(pageSize) params.push(offset) const itemsResult = await query( ` ${ADMIN_USER_SELECT} ${whereClause} ORDER BY au.id DESC LIMIT $${params.length - 1} OFFSET $${params.length} `, params, ) return { items: itemsResult.rows, total: Number(totalResult.rows[0]?.total || 0), } } export async function countActiveAdminUsers(): Promise { const result = await query<{ [column: string]: unknown, total: number }>( `SELECT COUNT(*)::int AS total FROM admin_users WHERE role = 'admin' AND status = 'active'`, ) return Number(result.rows[0]?.total || 0) }