import type { NotificationType } from "@prisma/client";
import { emailTemplate, sendEmail } from "./mailer";
import { prisma } from "./prisma";
import { emitToUser } from "./socketBus";
import { env } from "./env";

const PREFERENCE_FIELD: Record<NotificationType, string> = {
  MENTION: "emailOnMention",
  ASSIGNMENT: "emailOnAssignment",
  DUE_DATE: "emailOnDueDate",
  COMMENT: "emailOnComment",
  BOARD_INVITE: "emailOnBoardInvite",
  DRIVE_SHARE: "emailOnDriveShare",
  PORTAL_REQUEST: "emailOnPortalRequest",
};

export async function notifyUser(params: {
  recipientId: string;
  actorId?: string;
  type: NotificationType;
  message: string;
  cardId?: string;
  boardId?: string;
  workspaceId?: string;
  fileId?: string;
}) {
  if (params.actorId === params.recipientId) return;

  const notification = await prisma.notification.create({
    data: {
      recipientId: params.recipientId,
      actorId: params.actorId,
      type: params.type,
      message: params.message,
      cardId: params.cardId,
      boardId: params.boardId,
      workspaceId: params.workspaceId,
      fileId: params.fileId,
    },
    include: { actor: true },
  });

  emitToUser(params.recipientId, "notification:new", { notification });

  const prefs = await prisma.notificationPreference.upsert({
    where: { userId: params.recipientId },
    update: {},
    create: { userId: params.recipientId },
  });

  const field = PREFERENCE_FIELD[params.type] as keyof typeof prefs;
  if (!prefs[field]) return;

  const recipient = await prisma.user.findUnique({ where: { id: params.recipientId } });
  if (!recipient) return;

  let ctaUrl = env.CLIENT_URL;
  if (params.cardId && params.boardId) {
    ctaUrl = `${env.CLIENT_URL}/boards/${params.boardId}?card=${params.cardId}`;
  } else if (params.boardId) {
    ctaUrl = `${env.CLIENT_URL}/boards/${params.boardId}`;
  } else if (params.workspaceId) {
    ctaUrl = `${env.CLIENT_URL}/workspaces/${params.workspaceId}`;
  } else if (params.fileId) {
    ctaUrl = `${env.CLIENT_URL}/drive?file=${params.fileId}`;
  }

  // Fire-and-forget: SMTP delivery (especially Ethereal's test inbox) can take several
  // seconds, and must not block the HTTP response for whatever action triggered it.
  sendEmail({
    to: recipient.email,
    subject: params.message,
    html: emailTemplate({
      title: params.message,
      bodyHtml: notification.actor
        ? `${notification.actor.name} — ${params.message.toLowerCase()}`
        : params.message,
      ctaLabel: "Open in My Assisto",
      ctaUrl,
    }),
  })
    .then(() => prisma.notification.update({ where: { id: notification.id }, data: { emailSent: true } }))
    .catch((err) => console.error("[notifications] Failed to send email:", err));
}
