import { desc, eq } from "drizzle-orm";

import { getDatabase } from "@/modules/core/server/db";
import { auditLogs } from "@/modules/core/server/schema";
import type { AuditLog, AuditResult, PublicAccount } from "@/modules/core/types";

type AuditInput = {
  actor?: PublicAccount;
  organizationId?: string;
  action: string;
  targetType: string;
  targetId?: string;
  result: AuditResult;
  reason: string;
};

function toAuditLog(row: typeof auditLogs.$inferSelect): AuditLog {
  return {
    id: row.id,
    organizationId: row.organizationId ?? undefined,
    timestamp: row.timestamp.toISOString(),
    actorAccountId: row.actorAccountId ?? undefined,
    actorEmail: row.actorEmail ?? undefined,
    action: row.action,
    targetType: row.targetType,
    targetId: row.targetId ?? undefined,
    result: row.result,
    reason: row.reason,
  };
}

export async function recordAuditLog(input: AuditInput): Promise<AuditLog> {
  const database = getDatabase();
  const rows = await database
    .insert(auditLogs)
    .values({
      organizationId: input.organizationId,
      actorAccountId: input.actor?.id,
      actorEmail: input.actor?.email,
      action: input.action,
      targetType: input.targetType,
      targetId: input.targetId,
      result: input.result,
      reason: input.reason,
    })
    .returning();
  const row = rows[0];
  if (!row) {
    throw new Error("审计日志写入失败");
  }

  return toAuditLog(row);
}

export async function listAuditLogs(params: { organizationId?: string; limit?: number }): Promise<AuditLog[]> {
  const database = getDatabase();
  const limit = params.limit ?? 100;
  const rows = params.organizationId
    ? await database
        .select()
        .from(auditLogs)
        .where(eq(auditLogs.organizationId, params.organizationId))
        .orderBy(desc(auditLogs.timestamp))
        .limit(limit)
    : await database.select().from(auditLogs).orderBy(desc(auditLogs.timestamp)).limit(limit);

  return rows.map(toAuditLog);
}
