import db, { toIso, nowIso } from "../db";
import { auditEvents } from "../db/schema";
import { desc, like, or, count } from "drizzle-orm";

export type AuditEvent = {
  id: number;
  userId: number | null;
  action: string;
  entityType: string;
  entityId: number | null;
  summary: string | null;
  createdAt: string;
};

// Escape LIKE metacharacters so user input is treated as literal text
function escapeLikePattern(input: string): string {
  return input.replace(/[%_\\]/g, (ch) => `\\${ch}`);
}

export async function countAuditEvents(search?: string): Promise<number> {
  const where = search
    ? (() => {
        const escaped = escapeLikePattern(search);
        return or(
          like(auditEvents.summary, `%${escaped}%`),
          like(auditEvents.action, `%${escaped}%`),
          like(auditEvents.entityType, `%${escaped}%`)
        );
      })()
    : undefined;
  const [row] = await db.select({ value: count() }).from(auditEvents).where(where);
  return row?.value ?? 0;
}

export async function listAuditEvents(
  limit = 100,
  offset = 0,
  search?: string
): Promise<AuditEvent[]> {
  const where = search
    ? (() => {
        const escaped = escapeLikePattern(search);
        return or(
          like(auditEvents.summary, `%${escaped}%`),
          like(auditEvents.action, `%${escaped}%`),
          like(auditEvents.entityType, `%${escaped}%`)
        );
      })()
    : undefined;
  const events = await db
    .select()
    .from(auditEvents)
    .where(where)
    .orderBy(desc(auditEvents.createdAt))
    .limit(limit)
    .offset(offset);

  return events.map((event) => ({
    id: event.id,
    userId: event.userId,
    action: event.action,
    entityType: event.entityType,
    entityId: event.entityId,
    summary: event.summary,
    createdAt: toIso(event.createdAt)!,
  }));
}

export async function createAuditEvent(data: {
  userId: number | null;
  action: string;
  entityType: string;
  entityId?: number | null;
  summary?: string | null;
  data?: string | null;
}): Promise<void> {
  await db.insert(auditEvents).values({
    userId: data.userId,
    action: data.action,
    entityType: data.entityType,
    entityId: data.entityId ?? null,
    summary: data.summary ?? null,
    data: data.data ?? null,
    createdAt: nowIso(),
  });
}
