import { emitNotificationCreated } from "../sse/event-bus.js";

export interface CreateNotificationParams {
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  db: { notification: { create: (args: any) => Promise<{ id: string; userId: string }> } };
  userId: string;
  type: string;
  title: string;
  body?: string | undefined;
  link?: string | undefined;
  entityId?: string | undefined;
  entityType?: string | undefined;
  category?: string | undefined;
  priority?: string | undefined;
  senderId?: string | undefined;
  channel?: string | undefined;
  taskStatus?: string | undefined;
  taskAction?: string | undefined;
  assigneeId?: string | undefined;
  dueDate?: Date | undefined;
  sourceId?: string | undefined;
  /** Set to false to suppress the SSE emitNotificationCreated call. Default: true. */
  emit?: boolean | undefined;
}

/**
 * Create a single in-app notification and optionally emit an SSE event.
 *
 * Handles the `exactOptionalPropertyTypes` spread pattern internally so
 * callers do not need to repeat the `...(val !== undefined ? { key: val } : {})` boilerplate.
 *
 * Returns the created notification's ID.
 */
export async function createNotification(
  params: CreateNotificationParams,
): Promise<string> {
  const {
    db,
    userId,
    type,
    title,
    body,
    link,
    entityId,
    entityType,
    category,
    priority,
    senderId,
    channel,
    taskStatus,
    taskAction,
    assigneeId,
    dueDate,
    sourceId,
    emit = true,
  } = params;

  const notification = await db.notification.create({
    data: {
      userId,
      type,
      title,
      ...(body !== undefined ? { body } : {}),
      ...(link !== undefined ? { link } : {}),
      ...(entityId !== undefined ? { entityId } : {}),
      ...(entityType !== undefined ? { entityType } : {}),
      ...(category !== undefined ? { category } : {}),
      ...(priority !== undefined ? { priority } : {}),
      ...(senderId !== undefined ? { senderId } : {}),
      ...(channel !== undefined ? { channel } : {}),
      ...(taskStatus !== undefined ? { taskStatus } : {}),
      ...(taskAction !== undefined ? { taskAction } : {}),
      ...(assigneeId !== undefined ? { assigneeId } : {}),
      ...(dueDate !== undefined ? { dueDate } : {}),
      ...(sourceId !== undefined ? { sourceId } : {}),
    },
  });

  if (emit) {
    emitNotificationCreated(userId, notification.id);
  }

  return notification.id;
}

/**
 * Create one notification per user ID.
 *
 * Useful for fan-out scenarios (e.g. notifying all managers).
 * Returns the count of notifications created.
 */
export async function createNotificationsForUsers(
  params: Omit<CreateNotificationParams, "userId"> & { userIds: string[] },
): Promise<number> {
  const { userIds, ...rest } = params;
  let count = 0;
  for (const userId of userIds) {
    await createNotification({ ...rest, userId });
    count++;
  }
  return count;
}
