import "server-only";
import { db } from "./db";

const ACTION_LABELS: [string, string][] = [
  ["checkin.conference", "checked in an attendee"],
  ["checkin.api", "checked in an attendee (scanner)"],
  ["session.create", "added a session to the agenda"],
  ["session.update", "updated an agenda session"],
  ["session.delete", "removed an agenda session"],
  ["agenda.reorder", "reordered the agenda"],
  ["announcement.create", "posted an announcement"],
  ["speaker.create", "added a speaker"],
  ["speaker.update", "updated a speaker"],
  ["speaker.import", "imported a speaker from LinkedIn"],
  ["registration.confirmed", "confirmed a registration"],
  ["registration.cancelled", "cancelled a registration"],
  ["certificate.generate", "generated certificates"],
  ["sponsor.create", "added a sponsor"],
  ["sponsor.delete", "removed a sponsor"],
  ["ticket.create", "created a ticket type"],
  ["coupon.create", "created a coupon"],
  ["track.delete", "deleted a track"],
  ["venue.create", "added a venue"],
  ["hall.create", "added a hall"],
];

function humanize(action: string): string {
  return ACTION_LABELS.find(([prefix]) => action.startsWith(prefix))?.[1] ?? `performed: ${action}`;
}

/** Volunteer actions fan out as notifications to the conference's organizers. */
async function notifyOrganizersOfVolunteerAction(conferenceId: string, userId: string, action: string) {
  const volunteer = await db.volunteer.findFirst({
    where: { conferenceId, userId },
    select: { name: true, conference: { select: { name: true } } },
  });
  if (!volunteer) return;
  const organizers = await db.confMember.findMany({
    where: { conferenceId, role: { in: ["ORGANIZER", "CO_ORGANIZER"] }, userId: { not: userId } },
    select: { userId: true },
    distinct: ["userId"],
  });
  if (organizers.length === 0) return;
  await db.notification.createMany({
    data: organizers.map((o) => ({
      userId: o.userId,
      title: `🙋 ${volunteer.name} ${humanize(action)}`,
      body: volunteer.conference.name,
      link: `/dashboard/c/${conferenceId}/volunteers`,
    })),
  });
}

export async function audit(opts: {
  userId?: string | null;
  conferenceId?: string | null;
  action: string;
  entity?: string;
  entityId?: string;
  meta?: Record<string, unknown>;
}) {
  try {
    await db.auditLog.create({
      data: {
        userId: opts.userId ?? null,
        conferenceId: opts.conferenceId ?? null,
        action: opts.action,
        entity: opts.entity,
        entityId: opts.entityId,
        meta: opts.meta ? JSON.stringify(opts.meta) : null,
      },
    });
    if (opts.conferenceId && opts.userId) {
      await notifyOrganizersOfVolunteerAction(opts.conferenceId, opts.userId, opts.action);
    }
  } catch {
    // audit failures must never break the main flow
  }
}
