import { randomBytes, createHash } from "crypto";
import { g as getAvailabilityFromSchedule, P as ProfileRepository, D as DEFAULT_SCHEDULE } from "./user-LXWvjZHg.js";
import { l as logger, p as prisma, s as slugify, g as getTranslation, M as MembershipRole, v as WEBAPP_URL, a as safeStringify } from "./i18n-VAwx2uzJ.js";
import "./createAProfileForAnExistingUser-G6JzMbyE.js";
import "./bookingtimestatusdenormalized--VR-ufZ1.js";
import "./team-AHxzwFPI.js";
import "./index-browser-AmfhG6O_.js";
import { TRPCError } from "@trpc/server";
import { q as sendTeamInviteEmail, t as sendEmailVerificationCode } from "./email-manager-em79awUz.js";
import { TOTP } from "@otplib/core";
import { createDigest } from "@otplib/plugin-crypto";
import "@otplib/plugin-thirty-two";
import { totp } from "otplib";
import { startSpan } from "@sentry/nextjs";
import { W as WatchlistRepository } from "./watchlist.repository-R1rivcwk.js";
const isEmail = (str) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(str);
logger.getSubLogger({ prefix: ["inviteMember.utils"] });
function checkInputEmailIsValid(email) {
  if (!isEmail(email))
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: `Invite failed because ${email} is not a valid email address`
    });
}
async function createNewUsersConnectToOrgIfExists({
  invitations,
  isOrg,
  teamId,
  parentId,
  autoAcceptEmailDomain,
  orgConnectInfoByUsernameOrEmail,
  isPlatformManaged,
  timeFormat,
  weekStart,
  timeZone,
  language,
  creationSource
}) {
  invitations.forEach((invitation) => checkInputEmailIsValid(invitation.usernameOrEmail));
  const createdUsers = await prisma.$transaction(
    async (tx) => {
      const createdUsers2 = [];
      for (let index = 0; index < invitations.length; index++) {
        const invitation = invitations[index];
        const { orgId, autoAccept } = orgConnectInfoByUsernameOrEmail[invitation.usernameOrEmail];
        const [emailUser, emailDomain] = invitation.usernameOrEmail.split("@");
        const [domainName, TLD] = emailDomain.split(".");
        const orgMemberUsername = emailDomain === autoAcceptEmailDomain ? slugify(emailUser) : slugify(`${emailUser}-${domainName}${isPlatformManaged ? `-${TLD}` : ""}`);
        const regularTeamMemberUsername = null;
        const isBecomingAnOrgMember = parentId || isOrg;
        const defaultAvailability = getAvailabilityFromSchedule(DEFAULT_SCHEDULE);
        const t = await getTranslation(language ?? "en", "common");
        const createdUser = await tx.user.create({
          data: {
            username: isBecomingAnOrgMember ? orgMemberUsername : regularTeamMemberUsername,
            email: invitation.usernameOrEmail,
            verified: true,
            invitedTo: teamId,
            isPlatformManaged: !!isPlatformManaged,
            timeFormat,
            weekStart,
            timeZone,
            creationSource,
            organizationId: orgId || null,
            // If the user is invited to a child team, they are automatically added to the parent org
            ...orgId ? {
              profiles: {
                createMany: {
                  data: [
                    {
                      uid: ProfileRepository.generateProfileUid(),
                      username: orgMemberUsername,
                      organizationId: orgId
                    }
                  ]
                }
              }
            } : null,
            teams: {
              create: {
                teamId,
                role: invitation.role,
                accepted: autoAccept
                // If the user is invited to a child team, they are automatically accepted
              }
            },
            ...!isPlatformManaged ? {
              schedules: {
                create: {
                  name: t("default_schedule_name"),
                  availability: {
                    createMany: {
                      data: defaultAvailability.map((schedule) => ({
                        days: schedule.days,
                        startTime: schedule.startTime,
                        endTime: schedule.endTime
                      }))
                    }
                  }
                }
              }
            } : {}
          }
        });
        if (parentId) {
          await tx.membership.create({
            data: {
              createdAt: /* @__PURE__ */ new Date(),
              teamId: parentId,
              userId: createdUser.id,
              role: MembershipRole.MEMBER,
              accepted: autoAccept
            }
          });
        }
        createdUsers2.push(createdUser);
      }
      return createdUsers2;
    },
    { timeout: 1e4 }
  );
  return createdUsers;
}
async function sendSignupToOrganizationEmail({
  usernameOrEmail,
  team,
  translation,
  inviterName,
  teamId,
  isOrg
}) {
  try {
    const token = randomBytes(32).toString("hex");
    await prisma.verificationToken.create({
      data: {
        identifier: usernameOrEmail,
        token,
        expires: new Date((/* @__PURE__ */ new Date()).setHours(168)),
        // +1 week
        team: {
          connect: {
            id: teamId
          }
        }
      }
    });
    await sendTeamInviteEmail({
      language: translation,
      from: inviterName || `${team.name}'s admin`,
      to: usernameOrEmail,
      teamName: team.name,
      joinLink: `${WEBAPP_URL}/signup?token=${token}&callbackUrl=/getting-started`,
      isCalcomMember: false,
      isOrg,
      parentTeamName: team?.parent?.name,
      isAutoJoin: false,
      isExistingUserMovedToOrg: false,
      // For a new user there is no prev and new links.
      prevLink: null,
      newLink: null
    });
  } catch (error) {
    logger.error(
      "Failed to send signup to organization email",
      safeStringify({
        usernameOrEmail,
        orgId: teamId
      }),
      error
    );
  }
}
const totpRawCheck = (token, secret, opts = {}) => {
  const { window = [1, 0], ...rest } = opts;
  const authenticator = new TOTP({
    createDigest,
    window,
    ...rest
  });
  return authenticator.check(token, secret);
};
function presenter(watchlistedEmail) {
  return startSpan({ name: "checkIfEmailInWatchlist Presenter", op: "serialize" }, () => {
    return !!watchlistedEmail;
  });
}
async function checkIfEmailIsBlockedInWatchlistController(email) {
  return await startSpan({ name: "checkIfEmailInWatchlist Controller" }, async () => {
    const lowercasedEmail = email.toLowerCase();
    const watchlistRepository = new WatchlistRepository();
    const watchlistedEmail = await watchlistRepository.getBlockedEmailInWatchlist(lowercasedEmail);
    return presenter(watchlistedEmail);
  });
}
const log = logger.getSubLogger({ prefix: [`[[Auth] `] });
const sendEmailVerificationByCode = async ({
  email,
  language,
  username,
  isVerifyingEmail
}) => {
  if (await checkIfEmailIsBlockedInWatchlistController(email)) {
    log.warn("Email is blocked - not sending verification email", email);
    return { ok: false, skipped: false };
  }
  const translation = await getTranslation(language ?? "en", "common");
  const secret = createHash("md5").update(email + process.env.CALENDSO_ENCRYPTION_KEY).digest("hex");
  totp.options = { step: 900 };
  const code = totp.generate(secret);
  await sendEmailVerificationCode({
    language: translation,
    verificationEmailCode: code,
    user: {
      email,
      name: username
    },
    isVerifyingEmail
  });
  return { ok: true, skipped: false };
};
export {
  sendEmailVerificationByCode as a,
  createNewUsersConnectToOrgIfExists as c,
  sendSignupToOrganizationEmail as s,
  totpRawCheck as t
};
