import { ensureOrganizationMembership } from "./authz";
import { env } from "./env";
import { emailTemplate, sendEmail } from "./mailer";
import { prisma } from "./prisma";

export async function inviteByEmail(params: {
  email: string;
  role: string;
  invitedById: string;
  inviterName: string;
  organizationId?: string;
  organizationName?: string;
  workspaceId?: string;
  workspaceName?: string;
  boardId?: string;
  boardName?: string;
}) {
  const invitation = await prisma.invitation.create({
    data: {
      email: params.email,
      organizationId: params.organizationId,
      workspaceId: params.workspaceId,
      boardId: params.boardId,
      role: params.role,
      invitedById: params.invitedById,
    },
  });

  const registerUrl = `${env.CLIENT_URL}/register?invite=${invitation.token}`;
  const target = params.boardName
    ? `the board "${params.boardName}"`
    : params.workspaceName
      ? `the workspace "${params.workspaceName}"`
      : `the organization "${params.organizationName}"`;

  await sendEmail({
    to: params.email,
    subject: `${params.inviterName} invited you to My Assisto`,
    html: emailTemplate({
      title: "You've been invited to My Assisto",
      bodyHtml: `${params.inviterName} invited you to join ${target}. Create your account to get started — it only takes a minute.`,
      ctaLabel: "Create your account",
      ctaUrl: registerUrl,
    }),
  });

  return invitation;
}

export async function acceptPendingInvitationsForEmail(userId: string, email: string) {
  const invitations = await prisma.invitation.findMany({
    where: { email, acceptedAt: null },
  });

  for (const invitation of invitations) {
    if (invitation.organizationId) {
      await prisma.organizationMember.upsert({
        where: { organizationId_userId: { organizationId: invitation.organizationId, userId } },
        update: { role: invitation.role as "OWNER" | "ADMIN" | "MEMBER" },
        create: {
          organizationId: invitation.organizationId,
          userId,
          role: invitation.role as "OWNER" | "ADMIN" | "MEMBER",
        },
      });
    } else if (invitation.workspaceId) {
      const workspace = await prisma.workspace.findUnique({
        where: { id: invitation.workspaceId },
        select: { organizationId: true },
      });
      if (workspace) {
        await ensureOrganizationMembership(userId, workspace.organizationId);
      }

      await prisma.workspaceMember.upsert({
        where: { workspaceId_userId: { workspaceId: invitation.workspaceId, userId } },
        update: {},
        create: {
          workspaceId: invitation.workspaceId,
          userId,
          role: invitation.boardId ? "MEMBER" : (invitation.role as "ADMIN" | "MEMBER"),
        },
      });

      if (invitation.boardId) {
        await prisma.boardMember.upsert({
          where: { boardId_userId: { boardId: invitation.boardId, userId } },
          update: {},
          create: {
            boardId: invitation.boardId,
            userId,
            role: invitation.role as "ADMIN" | "MEMBER" | "VIEWER",
          },
        });
      }
    }

    await prisma.invitation.update({
      where: { id: invitation.id },
      data: { acceptedAt: new Date() },
    });
  }
}
