import { Pool } from "pg";

const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
});

export interface AuditLogEntry {
  userId?: string;
  userEmail?: string;
  action: string;
  resource: string;
  resourceId?: string;
  details?: Record<string, unknown>;
  ipAddress?: string;
  userAgent?: string;
}

/**
 * Log an audit event
 */
export async function log(entry: AuditLogEntry): Promise<void> {
  try {
    const id = crypto.randomUUID();
    await pool.query(
      `INSERT INTO "audit_log" 
       (id, user_id, user_email, action, resource, resource_id, details, ip_address, user_agent)
       VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)`,
      [
        id,
        entry.userId || null,
        entry.userEmail || null,
        entry.action,
        entry.resource,
        entry.resourceId || null,
        entry.details ? JSON.stringify(entry.details) : null,
        entry.ipAddress || null,
        entry.userAgent || null,
      ]
    );
  } catch (error) {
    console.error("Failed to write audit log:", error);
    // Don't throw - audit logging should not break the main flow
  }
}

// Convenience functions for common audit events
export const audit = {
  log,

  // Auth events
  signIn: (userId: string, email: string, ipAddress?: string, userAgent?: string) =>
    log({
      userId,
      userEmail: email,
      action: "sign_in",
      resource: "auth",
      ipAddress,
      userAgent,
    }),

  signOut: (userId: string, email: string, ipAddress?: string) =>
    log({
      userId,
      userEmail: email,
      action: "sign_out",
      resource: "auth",
      ipAddress,
    }),

  signInFailed: (email: string, reason: string, ipAddress?: string) =>
    log({
      userEmail: email,
      action: "sign_in_failed",
      resource: "auth",
      details: { reason },
      ipAddress,
    }),

  // User management events
  userCreated: (actorId: string, actorEmail: string, targetUserId: string, targetEmail: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "create",
      resource: "user",
      resourceId: targetUserId,
      details: { targetEmail },
    }),

  userUpdated: (actorId: string, actorEmail: string, targetUserId: string, changes: Record<string, unknown>) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "update",
      resource: "user",
      resourceId: targetUserId,
      details: { changes },
    }),

  userDeleted: (actorId: string, actorEmail: string, targetUserId: string, targetEmail: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "delete",
      resource: "user",
      resourceId: targetUserId,
      details: { targetEmail },
    }),

  userBanned: (actorId: string, actorEmail: string, targetUserId: string, reason?: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "ban",
      resource: "user",
      resourceId: targetUserId,
      details: { reason },
    }),

  userUnbanned: (actorId: string, actorEmail: string, targetUserId: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "unban",
      resource: "user",
      resourceId: targetUserId,
    }),

  userRoleChanged: (actorId: string, actorEmail: string, targetUserId: string, oldRole: string, newRole: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "role_change",
      resource: "user",
      resourceId: targetUserId,
      details: { oldRole, newRole },
    }),

  // Role management events
  roleCreated: (actorId: string, actorEmail: string, roleId: string, roleName: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "create",
      resource: "role",
      resourceId: roleId,
      details: { roleName },
    }),

  roleUpdated: (actorId: string, actorEmail: string, roleId: string, changes: Record<string, unknown>) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "update",
      resource: "role",
      resourceId: roleId,
      details: { changes },
    }),

  roleDeleted: (actorId: string, actorEmail: string, roleId: string, roleName: string) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "delete",
      resource: "role",
      resourceId: roleId,
      details: { roleName },
    }),

  // Settings events
  settingsUpdated: (actorId: string, actorEmail: string, setting: string, oldValue: unknown, newValue: unknown) =>
    log({
      userId: actorId,
      userEmail: actorEmail,
      action: "update",
      resource: "settings",
      resourceId: setting,
      details: { oldValue, newValue },
    }),
};

/**
 * Purge old audit logs based on retention policy
 */
export async function purgeOldLogs(retentionDays?: number): Promise<number> {
  const days = retentionDays || parseInt(process.env.AUDIT_LOG_RETENTION_DAYS || "90");
  
  try {
    const result = await pool.query(
      `DELETE FROM "audit_log" WHERE timestamp < NOW() - INTERVAL '${days} days'`
    );
    return result.rowCount || 0;
  } catch (error) {
    console.error("Failed to purge audit logs:", error);
    return 0;
  }
}
