/**
 * 日志系统
 *
 * 表结构:
 * - admin_audit_log: 审计日志表
 *   (id, user_id, username, action, resource, resource_id,
 *    request_params, ip_address, user_agent, result, error_message, created_at)
 */
import { query } from "./db";

export type AuditAction = "create" | "read" | "update" | "delete" | "login" | "logout" | "other";

export interface AuditLogEntry {
  id: number;
  user_id: number;
  username: string;
  action: string;
  resource: string;
  resource_id: string | null;
  request_params: Record<string, unknown> | null;
  ip_address: string | null;
  user_agent: string | null;
  result: "success" | "failure";
  error_message: string | null;
  created_at: Date;
}

export interface CreateAuditLogParams {
  userId: number;
  username: string;
  action: AuditAction;
  resource: string;
  resourceId?: string;
  requestParams?: Record<string, unknown>;
  ipAddress?: string;
  userAgent?: string;
  result?: "success" | "failure";
  errorMessage?: string;
}

export async function createAuditLog(params: CreateAuditLogParams): Promise<void> {
  await query(
    `INSERT INTO admin_audit_log
     (user_id, username, action, resource, resource_id, request_params,
      ip_address, user_agent, result, error_message)
     VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)`,
    [
      params.userId,
      params.username,
      params.action,
      params.resource,
      params.resourceId || null,
      params.requestParams ? JSON.stringify(params.requestParams) : null,
      params.ipAddress || null,
      params.userAgent || null,
      params.result || "success",
      params.errorMessage || null,
    ]
  );
}

export interface ListAuditLogsOptions {
  page?: number;
  pageSize?: number;
  userId?: number;
  action?: string;
  resource?: string;
  startDate?: Date;
  endDate?: Date;
}

export async function listAuditLogs(
  options: ListAuditLogsOptions = {}
): Promise<{ logs: AuditLogEntry[]; total: number }> {
  const page = options.page ?? 1;
  const pageSize = options.pageSize ?? 20;
  const offset = (page - 1) * pageSize;

  const conditions: string[] = [];
  const params: unknown[] = [];
  let paramIdx = 1;

  if (options.userId !== undefined) {
    conditions.push(`user_id = $${paramIdx++}`);
    params.push(options.userId);
  }
  if (options.action) {
    conditions.push(`action = $${paramIdx++}`);
    params.push(options.action);
  }
  if (options.resource) {
    conditions.push(`resource ILIKE $${paramIdx++}`);
    params.push(`%${options.resource}%`);
  }
  if (options.startDate) {
    conditions.push(`created_at >= $${paramIdx++}`);
    params.push(options.startDate);
  }
  if (options.endDate) {
    conditions.push(`created_at <= $${paramIdx++}`);
    params.push(options.endDate);
  }

  const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(" AND ")}` : "";

  const countResult = await query<{ count: string }>(
    `SELECT COUNT(*) FROM admin_audit_log ${whereClause}`,
    params
  );
  const total = parseInt(countResult.rows[0].count, 10);

  const limitParam = paramIdx++;
  const offsetParam = paramIdx++;
  const logsResult = await query<AuditLogEntry>(
    `SELECT id, user_id, username, action, resource, resource_id,
            request_params, ip_address, user_agent, result, error_message, created_at
     FROM admin_audit_log ${whereClause}
     ORDER BY created_at DESC
     LIMIT $${limitParam} OFFSET $${offsetParam}`,
    [...params, pageSize, offset]
  );

  return { logs: logsResult.rows, total };
}
