import { a5 as SERVICE_ACCOUNT_ENCRYPTION_KEY, a6 as symmetricEncrypt, n as symmetricDecrypt, a7 as serviceAccountKeySchema, l as logger, a as safeStringify, p as prisma, M as MembershipRole, t as teamMetadataSchema, a8 as safeCredentialSelect, c as credentialForCalendarServiceSelect } from "./i18n-49-r55rr.js";
import { g as getCalendar, a as metadata$2, b as metadata$3 } from "./_metadata-z9hxrtRQ.js";
import { r as metadata$1 } from "./CalEventParser-gVLQw-Bk.js";
import { a as getOrgUsernameFromEmail, c as getParsedTeam, U as UserRepository, i as isDelegationCredential, h as buildNonDelegationCredentials, j as buildNonDelegationCredential } from "./user-QM9GuUuS.js";
import { z } from "zod";
import { c as createAProfileForAnExistingUser } from "./createAProfileForAnExistingUser-Kn-M-_qx.js";
const name = "@calcom/office365video";
const version = "0.0.0";
const main = "./index.ts";
const description = "Microsoft Teams is a business communication platform and collaborative workspace included in Microsoft 365. It offers workspace chat and video conferencing, file storage, and application integration. Both web versions and desktop/mobile applications are available. NOTE: MUST HAVE A WORK / SCHOOL ACCOUNT";
const dependencies = {
  "@calcom/lib": "*",
  "@calcom/prisma": "*"
};
const devDependencies = {
  "@calcom/types": "*"
};
const _package = {
  "private": true,
  name,
  version,
  main,
  description,
  dependencies,
  devDependencies
};
const metadata = {
  name: "Microsoft 365/Teams (Requires work/school account)",
  description: _package.description,
  appData: {
    location: {
      linkType: "dynamic",
      type: "integrations:office365_video",
      label: "MS Teams (Requires work/school account)"
    }
  },
  type: "office365_video",
  title: "MS Teams (Requires work/school account)",
  variant: "conferencing",
  category: "conferencing",
  categories: ["conferencing"],
  logo: "icon.svg",
  publisher: "Cal.com",
  slug: "msteams",
  dirName: "office365video",
  dependencies: ["office365-calendar"],
  url: "https://www.microsoft.com/en-ca/microsoft-teams/group-chat-software",
  email: "help@cal.com",
  isOAuth: true
};
const encryptedServiceAccountKeySchema = z.object({
  client_email: z.string().optional(),
  client_id: z.string(),
  encrypted_credentials: z.string(),
  tenant_id: z.string().optional()
}).passthrough();
function encryptServiceAccountKey(serviceAccountKey) {
  if (!SERVICE_ACCOUNT_ENCRYPTION_KEY) {
    throw new Error("Service account encryption key is not set");
  }
  const { private_key, ...rest } = serviceAccountKey;
  const sensitiveData = { private_key };
  return {
    ...rest,
    encrypted_credentials: symmetricEncrypt(JSON.stringify(sensitiveData), SERVICE_ACCOUNT_ENCRYPTION_KEY)
  };
}
function decryptServiceAccountKey(encryptedServiceAccountKey) {
  if (!SERVICE_ACCOUNT_ENCRYPTION_KEY) {
    throw new Error("Service account encryption key is not set");
  }
  try {
    const parsedEncrypted = encryptedServiceAccountKeySchema.safeParse(encryptedServiceAccountKey);
    if (!parsedEncrypted.success) {
      throw new Error(`Invalid service account key format: ${JSON.stringify(parsedEncrypted.error)}`);
    }
    const { encrypted_credentials, ...rest } = parsedEncrypted.data;
    const decryptedData = JSON.parse(
      symmetricDecrypt(encrypted_credentials, SERVICE_ACCOUNT_ENCRYPTION_KEY)
    );
    const decrypted = {
      ...rest,
      ...decryptedData
    };
    const parsedDecrypted = serviceAccountKeySchema.safeParse(decrypted);
    if (!parsedDecrypted.success) {
      throw new Error("Invalid decrypted service account key format");
    }
    return parsedDecrypted.data;
  } catch (error) {
    if (error instanceof Error) {
      throw new Error(`Failed to decrypt service account key: ${error.message}`);
    }
    throw new Error("Failed to decrypt service account key");
  }
}
const orgSelect = {
  id: true,
  name: true,
  slug: true,
  logoUrl: true
};
class OrganizationRepository {
  static async createWithExistingUserAsOwner({
    orgData,
    owner
  }) {
    logger.debug("createWithExistingUserAsOwner", safeStringify({ orgData, owner }));
    const organization = await this.create(orgData);
    const ownerProfile = await createAProfileForAnExistingUser({
      user: {
        id: owner.id,
        email: owner.email,
        currentUsername: owner.nonOrgUsername
      },
      organizationId: organization.id
    });
    await prisma.membership.create({
      data: {
        createdAt: /* @__PURE__ */ new Date(),
        userId: owner.id,
        role: MembershipRole.OWNER,
        accepted: true,
        teamId: organization.id
      }
    });
    return { organization, ownerProfile };
  }
  static async createWithNonExistentOwner({
    orgData,
    owner,
    creationSource
  }) {
    logger.debug("createWithNonExistentOwner", safeStringify({ orgData, owner }));
    const organization = await this.create(orgData);
    const ownerUsernameInOrg = getOrgUsernameFromEmail(owner.email, orgData.autoAcceptEmail);
    const userRepo = new UserRepository(prisma);
    const ownerInDb = await userRepo.create({
      email: owner.email,
      username: ownerUsernameInOrg,
      organizationId: organization.id,
      locked: false,
      creationSource
    });
    await prisma.membership.create({
      data: {
        createdAt: /* @__PURE__ */ new Date(),
        userId: ownerInDb.id,
        role: MembershipRole.OWNER,
        accepted: true,
        teamId: organization.id
      }
    });
    return {
      orgOwner: ownerInDb,
      organization,
      ownerProfile: {
        username: ownerUsernameInOrg
      }
    };
  }
  static async create(orgData) {
    return await prisma.team.create({
      data: {
        name: orgData.name,
        isOrganization: true,
        slug: orgData.slug,
        // This is huge and causes issues, we need to have the logic to convert logo to logoUrl and then use that url ehre.
        // logoUrl: orgData.logoUrl,
        bio: orgData.bio,
        organizationSettings: {
          create: {
            isAdminReviewed: orgData.isOrganizationAdminReviewed,
            isOrganizationVerified: true,
            isOrganizationConfigured: orgData.isOrganizationConfigured,
            orgAutoAcceptEmail: orgData.autoAcceptEmail
          }
        },
        metadata: {
          isPlatform: orgData.isPlatform,
          // We still have a case where we don't have slug set directly on organization. The reason is because we want to create an org first(with same slug as another regular team) and then move the team to org.
          // Because in such cases there is a fallback existing at multiple places to use requestedSlug, we set it here still :(
          requestedSlug: orgData.requestedSlug,
          // We set these here still because some parts of code read it from metadata. This data exists in OrganizationOnboarding as well and should be used from there ideally
          // We also need to think about existing Organizations that might not have OrganizationOnboarding, before taking any decision
          orgSeats: orgData.seats,
          orgPricePerSeat: orgData.pricePerSeat,
          billingPeriod: orgData.billingPeriod
        },
        isPlatform: orgData.isPlatform
      }
    });
  }
  static async findById({ id }) {
    return prisma.team.findUnique({
      where: {
        id,
        isOrganization: true
      }
    });
  }
  static async findBySlug({ slug }) {
    return prisma.team.findFirst({
      where: {
        slug,
        isOrganization: true
      }
    });
  }
  static async findBySlugIncludeOnboarding({ slug }) {
    return prisma.team.findFirst({
      where: { slug, isOrganization: true },
      include: {
        organizationOnboarding: {
          select: {
            id: true,
            isDomainConfigured: true,
            isPlatform: true,
            slug: true,
            teams: true,
            invitedMembers: true
          }
        }
      }
    });
  }
  static async findByIdIncludeOrganizationSettings({ id }) {
    return prisma.team.findUnique({
      where: {
        id,
        isOrganization: true
      },
      select: {
        ...orgSelect,
        organizationSettings: true
      }
    });
  }
  static async findUniqueNonPlatformOrgsByMatchingAutoAcceptEmail({ email }) {
    const emailDomain = email.split("@").at(-1);
    const orgs = await prisma.team.findMany({
      where: {
        isOrganization: true,
        isPlatform: false,
        organizationSettings: {
          orgAutoAcceptEmail: emailDomain,
          isOrganizationVerified: true,
          isAdminReviewed: true
        }
      }
    });
    if (orgs.length > 1) {
      logger.error(
        "Multiple organizations found with the same auto accept email domain",
        safeStringify({ orgs, emailDomain })
      );
      throw new Error("Multiple organizations found with the same auto accept email domain");
    }
    const org = orgs[0];
    if (!org) {
      return null;
    }
    return getParsedTeam(org);
  }
  static async findCurrentOrg({ userId, orgId }) {
    const membership = await prisma.membership.findUnique({
      where: {
        userId_teamId: {
          userId,
          teamId: orgId
        }
      },
      include: {
        team: true
      }
    });
    const organizationSettings = await prisma.organizationSettings.findUnique({
      where: {
        organizationId: orgId
      },
      select: {
        lockEventTypeCreationForUsers: true,
        adminGetsNoSlotsNotification: true,
        isAdminReviewed: true,
        allowSEOIndexing: true,
        orgProfileRedirectsToVerifiedDomain: true,
        orgAutoAcceptEmail: true,
        disablePhoneOnlySMSNotifications: true
      }
    });
    if (!membership) {
      throw new Error("You do not have a membership to your organization");
    }
    const metadata2 = teamMetadataSchema.parse(membership?.team.metadata);
    return {
      canAdminImpersonate: !!organizationSettings?.isAdminReviewed,
      organizationSettings: {
        lockEventTypeCreationForUsers: organizationSettings?.lockEventTypeCreationForUsers,
        adminGetsNoSlotsNotification: organizationSettings?.adminGetsNoSlotsNotification,
        allowSEOIndexing: organizationSettings?.allowSEOIndexing,
        orgProfileRedirectsToVerifiedDomain: organizationSettings?.orgProfileRedirectsToVerifiedDomain,
        orgAutoAcceptEmail: organizationSettings?.orgAutoAcceptEmail,
        disablePhoneOnlySMSNotifications: organizationSettings?.disablePhoneOnlySMSNotifications
      },
      user: {
        role: membership?.role,
        accepted: membership?.accepted
      },
      ...membership?.team,
      metadata: metadata2
    };
  }
  static async findTeamsInOrgIamNotPartOf({ userId, parentId }) {
    const teamsInOrgIamNotPartOf = await prisma.team.findMany({
      where: {
        parentId,
        members: {
          none: {
            userId
          }
        }
      },
      select: {
        parentId: true,
        id: true,
        name: true,
        logoUrl: true,
        slug: true
      }
    });
    return teamsInOrgIamNotPartOf;
  }
  static async adminFindById({ id }) {
    const org = await prisma.team.findUnique({
      where: {
        id
      },
      select: {
        id: true,
        name: true,
        slug: true,
        metadata: true,
        isOrganization: true,
        members: {
          where: {
            role: "OWNER"
          },
          select: {
            user: {
              select: {
                id: true,
                name: true,
                email: true
              }
            }
          }
        },
        organizationSettings: {
          select: {
            isOrganizationConfigured: true,
            isOrganizationVerified: true,
            orgAutoAcceptEmail: true
          }
        }
      }
    });
    if (!org) {
      throw new Error("Organization not found");
    }
    const parsedMetadata = teamMetadataSchema.parse(org.metadata);
    if (!org?.isOrganization) {
      throw new Error("Organization not found");
    }
    return { ...org, metadata: parsedMetadata };
  }
  static async findByMemberEmail({ email }) {
    const organization = await prisma.team.findFirst({
      where: {
        isOrganization: true,
        members: {
          some: {
            user: { email }
          }
        }
      }
    });
    return organization ?? null;
  }
  static async findByMemberEmailId({ email }) {
    const log2 = logger.getSubLogger({ prefix: ["findByMemberEmailId"] });
    log2.debug("called with", { email });
    const organization = await prisma.team.findFirst({
      where: {
        isOrganization: true,
        members: {
          some: {
            user: {
              email
            }
          }
        }
      }
    });
    return organization;
  }
  static async findCalVideoLogoByOrgId({ id }) {
    const org = await prisma.team.findUnique({
      where: {
        id
      },
      select: {
        calVideoLogo: true
      }
    });
    return org?.calVideoLogo;
  }
  static async getVerifiedOrganizationByAutoAcceptEmailDomain(domain) {
    return await prisma.team.findFirst({
      where: {
        organizationSettings: {
          isOrganizationVerified: true,
          orgAutoAcceptEmail: domain
        }
      },
      select: {
        id: true,
        organizationSettings: {
          select: {
            orgAutoAcceptEmail: true
          }
        }
      }
    });
  }
  static async setSlug({ id, slug }) {
    return await prisma.team.update({
      where: { id, isOrganization: true },
      data: { slug }
    });
  }
  static async updateStripeSubscriptionDetails({
    id,
    stripeSubscriptionId,
    stripeSubscriptionItemId,
    existingMetadata
  }) {
    return await prisma.team.update({
      where: { id, isOrganization: true },
      data: {
        metadata: {
          ...existingMetadata,
          subscriptionId: stripeSubscriptionId,
          subscriptionItemId: stripeSubscriptionItemId
        }
      }
    });
  }
  static async checkIfPrivate({ orgId }) {
    const team = await prisma.team.findUnique({
      where: {
        id: orgId,
        isOrganization: true
      },
      select: {
        isPrivate: true
      }
    });
    return team?.isPrivate ?? false;
  }
}
const repositoryLogger = logger.getSubLogger({ prefix: ["DelegationCredentialRepository"] });
const delegationCredentialSafeSelect = {
  id: true,
  enabled: true,
  domain: true,
  createdAt: true,
  updatedAt: true,
  organizationId: true,
  lastEnabledAt: true,
  lastDisabledAt: true,
  workspacePlatform: {
    select: {
      name: true,
      slug: true
    }
  }
};
const delegationCredentialSelectIncludesServiceAccountKey = {
  ...delegationCredentialSafeSelect,
  serviceAccountKey: true
};
function doesEmailMatchDelegationCredentialDomain({
  memberEmail,
  delegationCredentialEmailDomain
}) {
  if (!memberEmail)
    return false;
  const memberEmailDomain = memberEmail.split("@")[1];
  return memberEmailDomain === delegationCredentialEmailDomain;
}
class DelegationCredentialRepository {
  static encryptServiceAccountKey(serviceAccountKey) {
    return encryptServiceAccountKey(serviceAccountKey);
  }
  static decryptServiceAccountKey(encryptedServiceAccountKey) {
    return decryptServiceAccountKey(encryptedServiceAccountKey);
  }
  static withParsedServiceAccountKey(delegationCredential) {
    if (!delegationCredential) {
      return null;
    }
    const { serviceAccountKey, ...rest } = delegationCredential;
    const decryptedKey = this.decryptServiceAccountKey(serviceAccountKey);
    const parsedServiceAccountKey = serviceAccountKeySchema.safeParse(decryptedKey);
    return {
      ...rest,
      serviceAccountKey: parsedServiceAccountKey.success ? parsedServiceAccountKey.data : null
    };
  }
  static async create(data) {
    const encryptedKey = this.encryptServiceAccountKey(data.serviceAccountKey);
    return await prisma.delegationCredential.create({
      data: {
        workspacePlatform: {
          connect: {
            id: data.workspacePlatformId
          }
        },
        domain: data.domain,
        enabled: data.enabled,
        organization: {
          connect: {
            id: data.organizationId
          }
        },
        // z.passthrough() is not allowed in Prisma, but we know this is trusted.
        serviceAccountKey: encryptedKey
      },
      select: delegationCredentialSafeSelect
    });
  }
  static async findById({ id }) {
    return await prisma.delegationCredential.findUnique({
      where: { id },
      select: delegationCredentialSafeSelect
    });
  }
  static async findUniqueByOrganizationIdAndDomainIncludeSensitiveServiceAccountKey({
    organizationId,
    domain
  }) {
    const delegationCredential = await prisma.delegationCredential.findUnique({
      where: { organizationId_domain: { organizationId, domain } },
      select: delegationCredentialSelectIncludesServiceAccountKey
    });
    return DelegationCredentialRepository.withParsedServiceAccountKey(delegationCredential);
  }
  static async findByIdIncludeSensitiveServiceAccountKey({ id }) {
    const delegationCredential = await prisma.delegationCredential.findUnique({
      where: { id },
      select: delegationCredentialSelectIncludesServiceAccountKey
    });
    if (!delegationCredential)
      return null;
    return DelegationCredentialRepository.withParsedServiceAccountKey(delegationCredential);
  }
  static async findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey({ email }) {
    const log2 = repositoryLogger.getSubLogger({
      prefix: ["findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey"]
    });
    log2.debug("called with", { email });
    const organization = await OrganizationRepository.findByMemberEmail({ email });
    if (!organization) {
      log2.debug("Email not found in any organization:", email);
      return null;
    }
    const emailDomain = email.split("@")[1];
    const delegationCredential = await prisma.delegationCredential.findUnique({
      where: {
        organizationId_domain: {
          organizationId: organization.id,
          domain: emailDomain
        }
      },
      select: delegationCredentialSelectIncludesServiceAccountKey
    });
    return DelegationCredentialRepository.withParsedServiceAccountKey(delegationCredential);
  }
  static async findAllByDomain({ domain }) {
    return await prisma.delegationCredential.findMany({
      where: { domain },
      select: delegationCredentialSafeSelect
    });
  }
  static async updateById({
    id,
    data
  }) {
    const { workspacePlatformId, organizationId, ...rest } = data;
    return await prisma.delegationCredential.update({
      where: { id },
      data: {
        ...workspacePlatformId && {
          workspacePlatform: {
            connect: {
              id: workspacePlatformId
            }
          }
        },
        ...organizationId && {
          organization: {
            connect: {
              id: organizationId
            }
          }
        },
        ...rest
      },
      select: delegationCredentialSafeSelect
    });
  }
  static async deleteById({ id }) {
    return await prisma.delegationCredential.delete({
      where: { id }
    });
  }
  static async findByOrgIdIncludeSensitiveServiceAccountKey({ organizationId }) {
    return await prisma.delegationCredential.findMany({
      where: { organizationId },
      select: {
        ...delegationCredentialSelectIncludesServiceAccountKey,
        workspacePlatform: {
          select: {
            id: true,
            name: true,
            slug: true
          }
        }
      }
    });
  }
  static async findAllEnabledIncludeDelegatedMembers() {
    const delegationCredentials = await prisma.delegationCredential.findMany({
      where: {
        enabled: true
      },
      include: {
        workspacePlatform: {
          select: {
            slug: true
          }
        },
        organization: {
          include: {
            members: {
              select: {
                id: true,
                userId: true,
                user: {
                  select: {
                    id: true,
                    email: true
                  }
                },
                accepted: true
              },
              where: {
                // Note: We don't maintain anything on Membership that can identify if a Membership has been processed, so we send all and let it be on the caller to filter out
                accepted: true
              }
            }
          }
        }
      }
    });
    return delegationCredentials.map((delegationCredential) => {
      const delegatedMembers = delegationCredential.organization.members.filter((member) => {
        return doesEmailMatchDelegationCredentialDomain({
          memberEmail: member.user.email,
          delegationCredentialEmailDomain: delegationCredential.domain
        });
      });
      return {
        ...delegationCredential,
        organization: {
          ...delegationCredential.organization,
          delegatedMembers
        }
      };
    });
  }
  static async findAllDisabledAndIncludeNextBatchOfMembersToProcess() {
    const delegationCredentials = await prisma.delegationCredential.findMany({
      where: {
        enabled: false
      },
      include: {
        workspacePlatform: {
          select: {
            slug: true
          }
        },
        organization: {
          include: {
            members: {
              select: {
                id: true,
                userId: true,
                user: {
                  select: {
                    id: true,
                    email: true
                  }
                },
                accepted: true
              },
              where: {
                // Note: We don't maintain anything on Membership that can identify if a Membership has been processed, so we send all and let it be on the caller to filter out
                accepted: true
              }
            }
          }
        }
      }
    });
    return delegationCredentials.map((delegationCredential) => {
      const members = delegationCredential.organization.members;
      const membersThatAreActuallyPartOfDelegationCredential = members.filter((member) => {
        return doesEmailMatchDelegationCredentialDomain({
          memberEmail: member.user.email,
          delegationCredentialEmailDomain: delegationCredential.domain
        });
      });
      return {
        ...delegationCredential,
        organization: {
          ...delegationCredential.organization,
          members: membersThatAreActuallyPartOfDelegationCredential
        }
      };
    });
  }
}
const GOOGLE_WORKSPACE_SLUG = "google";
const OFFICE365_WORKSPACE_SLUG = "office365";
const WORKSPACE_PLATFORM_SLUGS = [GOOGLE_WORKSPACE_SLUG, OFFICE365_WORKSPACE_SLUG];
const log$1 = logger.getSubLogger({ prefix: ["lib/delegationCredential/server"] });
const isValidWorkspaceSlug = (slug) => {
  return WORKSPACE_PLATFORM_SLUGS.includes(slug);
};
const getDelegationCredentialAppMetadata = (slug, isConferencing) => {
  switch (slug) {
    case GOOGLE_WORKSPACE_SLUG:
      return isConferencing ? { type: metadata$1.type, appId: metadata$1.slug } : { type: metadata$3.type, appId: metadata$3.slug };
    case OFFICE365_WORKSPACE_SLUG:
      return isConferencing ? { type: metadata.type, appId: metadata.slug } : { type: metadata$2.type, appId: metadata$2.slug };
    default:
      throw new Error("App metadata does not exist");
  }
};
const _isConferencingCredential = (credential) => {
  return credential.type.endsWith("_video") || credential.type.endsWith("_conferencing") || credential.type.endsWith("_messaging");
};
const _buildCommonUserCredential = ({
  delegationCredential,
  user
}) => {
  return {
    id: -1,
    delegatedToId: delegationCredential.id,
    userId: user.id,
    user: {
      email: user.email
    },
    key: {
      access_token: "NOOP_UNUSED_DELEGATION_TOKEN"
    },
    invalid: false,
    teamId: null,
    team: null,
    delegationCredentialId: delegationCredential.id,
    delegatedTo: delegationCredential.serviceAccountKey ? {
      serviceAccountKey: delegationCredential.serviceAccountKey
    } : null
  };
};
const _buildDelegatedCalendarCredential = ({
  delegationCredential,
  user
}) => {
  log$1.debug(
    "buildDelegationCredential",
    safeStringify({
      delegationCredential: {
        id: delegationCredential.id
      },
      user: {
        id: user.id,
        email: user.email
      }
    })
  );
  if (!isValidWorkspaceSlug(delegationCredential.workspacePlatform.slug)) {
    log$1.warn(
      `Only ${WORKSPACE_PLATFORM_SLUGS.toString()} Platforms are supported here, skipping ${delegationCredential.workspacePlatform.slug}`
    );
    return null;
  }
  return {
    ...getDelegationCredentialAppMetadata(
      delegationCredential.workspacePlatform.slug,
      false
    ),
    ..._buildCommonUserCredential({ delegationCredential, user })
  };
};
const _buildDelegatedCalendarCredentialWithServiceAccountKey = ({
  delegationCredential,
  user
}) => {
  const credential = _buildDelegatedCalendarCredential({ delegationCredential, user });
  if (!credential) {
    return null;
  }
  return {
    ...credential,
    delegatedTo: {
      serviceAccountKey: delegationCredential.serviceAccountKey
    }
  };
};
const _buildDelegatedConferencingCredential = ({
  delegationCredential,
  user
}) => {
  if (!isValidWorkspaceSlug(delegationCredential.workspacePlatform.slug)) {
    log$1.warn(
      `Only ${WORKSPACE_PLATFORM_SLUGS.toString()} Platforms are supported here, skipping ${delegationCredential.workspacePlatform.slug}`
    );
    return null;
  }
  return {
    ...getDelegationCredentialAppMetadata(
      delegationCredential.workspacePlatform.slug,
      true
    ),
    ..._buildCommonUserCredential({ delegationCredential, user })
  };
};
async function getAllDelegationCredentialsForUserIncludeServiceAccountKey({
  user
}) {
  log$1.debug("called with", safeStringify({ user }));
  const delegationCredential = await DelegationCredentialRepository.findUniqueByOrgMemberEmailIncludeSensitiveServiceAccountKey({
    email: user.email
  });
  if (!delegationCredential || !delegationCredential.enabled) {
    return [];
  }
  const delegationCredentials = [
    _buildDelegatedCalendarCredential({ delegationCredential, user }),
    _buildDelegatedConferencingCredential({ delegationCredential, user })
  ].filter((credential) => credential !== null);
  log$1.debug("Returned", safeStringify({ delegationCredentials }));
  return delegationCredentials;
}
async function _getDelegationCredentialsMapPerUser({
  organizationId,
  users
}) {
  const emptyMap = /* @__PURE__ */ new Map();
  if (!organizationId) {
    return emptyMap;
  }
  const userThatDeterminesDomain = users[0];
  if (!userThatDeterminesDomain) {
    return emptyMap;
  }
  const domain = userThatDeterminesDomain.email.split("@")[1];
  log$1.debug("called with", safeStringify({ users }));
  const delegationCredential = await DelegationCredentialRepository.findUniqueByOrganizationIdAndDomainIncludeSensitiveServiceAccountKey(
    {
      organizationId,
      domain
    }
  );
  if (!delegationCredential || !delegationCredential.enabled) {
    return emptyMap;
  }
  const credentialsByUserId = /* @__PURE__ */ new Map();
  for (const user of users) {
    const delegationCredentials = [
      _buildDelegatedCalendarCredential({ delegationCredential, user }),
      _buildDelegatedConferencingCredential({ delegationCredential, user })
    ].filter((credential) => credential !== null);
    log$1.debug(
      "Returned for user",
      safeStringify({
        user,
        delegationCredentialIds: delegationCredentials?.map?.((delegationCredential2) => delegationCredential2?.delegatedToId) ?? []
      })
    );
    credentialsByUserId.set(user.id, delegationCredentials);
  }
  return credentialsByUserId;
}
async function checkIfSuccessfullyConfiguredInWorkspace({
  delegationCredential,
  user
}) {
  if (!isValidWorkspaceSlug(delegationCredential.workspacePlatform.slug)) {
    log$1.warn(
      `Only ${WORKSPACE_PLATFORM_SLUGS.toString()} Platforms are supported here, skipping ${delegationCredential.workspacePlatform.slug}`
    );
    return false;
  }
  const credential = _buildDelegatedCalendarCredentialWithServiceAccountKey({
    delegationCredential,
    user
  });
  const calendar = await getCalendar(credential);
  if (!calendar) {
    throw new Error("Google Calendar App not found");
  }
  return await calendar?.testDelegationCredentialSetup?.();
}
const buildAllCredentials = ({
  delegationCredentials,
  existingCredentials
}) => {
  const nonDelegationCredentials = existingCredentials.filter(
    (cred) => !isDelegationCredential({ credentialId: cred.id })
  );
  const allCredentials = [
    ...delegationCredentials,
    ...buildNonDelegationCredentials(nonDelegationCredentials)
  ];
  const uniqueAllCredentials = allCredentials.reduce((acc, credential) => {
    if (!credential.delegatedToId) {
      acc.push(credential);
      return acc;
    }
    const existingDelegationCredential = acc.find(
      (c) => c.delegatedToId === credential.delegatedToId && c.appId === credential.appId
    );
    if (!existingDelegationCredential) {
      acc.push(credential);
    }
    return acc;
  }, []);
  return uniqueAllCredentials;
};
async function enrichUsersWithDelegationCredentials({ orgId, users }) {
  const delegationCredentialsMap = await _getDelegationCredentialsMapPerUser({
    organizationId: orgId,
    users
  });
  const enrichedUsers = users.map((user) => {
    const { credentials, ...rest } = user;
    const enrichedCredentials = buildAllCredentials({
      delegationCredentials: delegationCredentialsMap.get(user.id) ?? [],
      existingCredentials: credentials
    });
    return {
      ...rest,
      credentials: enrichedCredentials
    };
  });
  log$1.debug("enrichUsersWithDelegationCredentials", safeStringify({ enrichedUsers, orgId }));
  return enrichedUsers;
}
const enrichHostsWithDelegationCredentials = async ({
  orgId,
  hosts
}) => {
  const delegationCredentialsMap = await _getDelegationCredentialsMapPerUser({
    organizationId: orgId,
    users: hosts.map((host) => host.user)
  });
  const enrichedHosts = hosts.map((host) => {
    const { credentials, ...restUser } = host.user;
    return {
      ...host,
      user: {
        ...restUser,
        credentials: buildAllCredentials({
          delegationCredentials: delegationCredentialsMap.get(restUser.id) ?? [],
          existingCredentials: credentials
        })
      }
    };
  });
  log$1.debug(
    "enrichHostsWithDelegationCredentials",
    safeStringify({
      enrichedHosts: enrichedHosts.map((host) => {
        return {
          userId: host.user.id
        };
      }),
      orgId
    })
  );
  return enrichedHosts;
};
const enrichUserWithDelegationCredentialsIncludeServiceAccountKey = async ({
  user
}) => {
  const delegationCredentials = await getAllDelegationCredentialsForUserIncludeServiceAccountKey({
    user
  });
  const { credentials, ...restUser } = user;
  return {
    ...restUser,
    credentials: buildAllCredentials({
      delegationCredentials,
      existingCredentials: credentials
    })
  };
};
async function enrichUserWithDelegationConferencingCredentialsWithoutOrgId({ user }) {
  const { credentials, ...restUser } = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
    user
  });
  return {
    ...restUser,
    credentials: credentials.filter(_isConferencingCredential)
  };
}
async function getDelegationCredentialOrFindRegularCredential({
  id,
  delegationCredentials
}) {
  return id.delegationCredentialId ? delegationCredentials.find((cred) => cred.delegatedToId === id.delegationCredentialId) : id.credentialId ? await CredentialRepository.findCredentialForCalendarServiceById({
    id: id.credentialId
  }) : null;
}
function getFirstDelegationConferencingCredential({
  credentials
}) {
  return credentials.find((credential) => _isConferencingCredential(credential));
}
function getFirstDelegationConferencingCredentialAppLocation({
  credentials
}) {
  const delegatedConferencingCredential = getFirstDelegationConferencingCredential({ credentials });
  if (delegatedConferencingCredential?.appId === metadata$1.slug) {
    return metadata$1.appData?.location?.type;
  }
  if (delegatedConferencingCredential?.appId === metadata.slug) {
    return metadata.appData?.location?.type;
  }
  return null;
}
async function findUniqueDelegationCalendarCredential({
  userId,
  delegationCredentialId
}) {
  const [delegationCredential, user] = await Promise.all([
    DelegationCredentialRepository.findByIdIncludeSensitiveServiceAccountKey({ id: delegationCredentialId }),
    new UserRepository(prisma).findById({ id: userId })
  ]);
  if (!delegationCredential) {
    throw new Error("Delegation Credential not found");
  }
  if (!delegationCredential.enabled) {
    return null;
  }
  if (!user) {
    throw new Error("User not found");
  }
  const dwdCredential = _buildDelegatedCalendarCredential({
    delegationCredential,
    user
  });
  return dwdCredential;
}
async function getCredentialForCalendarCache({ credentialId }) {
  const credential = await CredentialRepository.findByIdIncludeDelegationCredential({
    id: credentialId
  });
  let credentialForCalendarService;
  if (credential?.delegationCredential) {
    if (!credential.userId) {
      throw new Error(`Credential ${credentialId} doesn't have a user`);
    }
    const delegationCredential = await findUniqueDelegationCalendarCredential({
      userId: credential.userId,
      delegationCredentialId: credential.delegationCredential.id
    });
    if (!delegationCredential) {
      credentialForCalendarService = null;
    } else {
      credentialForCalendarService = {
        ...delegationCredential,
        id: credential.id
      };
    }
  } else {
    credentialForCalendarService = buildNonDelegationCredential(credential);
  }
  return credentialForCalendarService;
}
const log = logger.getSubLogger({ prefix: ["CredentialRepository"] });
class CredentialRepository {
  static async create(data) {
    const credential = await prisma.credential.create({ data: { ...data } });
    return buildNonDelegationCredential(credential);
  }
  static async findByAppIdAndUserId({ appId, userId }) {
    const credential = await prisma.credential.findFirst({
      where: {
        appId,
        userId
      }
    });
    return buildNonDelegationCredential(credential);
  }
  /**
   * Doesn't retrieve key field as that has credentials
   */
  static async findFirstByIdWithUser({ id }) {
    const credential = await prisma.credential.findUnique({ where: { id }, select: safeCredentialSelect });
    return buildNonDelegationCredential(credential);
  }
  /**
   * Includes 'key' field which is sensitive data.
   */
  static async findFirstByIdWithKeyAndUser({ id }) {
    const credential = await prisma.credential.findUnique({
      where: { id },
      select: { ...safeCredentialSelect, key: true }
    });
    return buildNonDelegationCredential(credential);
  }
  static async findFirstByAppIdAndUserId({ appId, userId }) {
    return await prisma.credential.findFirst({
      where: {
        appId,
        userId
      }
    });
  }
  static async findFirstByUserIdAndType({ userId, type }) {
    const credential = await prisma.credential.findFirst({ where: { userId, type } });
    return buildNonDelegationCredential(credential);
  }
  static async deleteById({ id }) {
    await prisma.credential.delete({ where: { id } });
  }
  static async updateCredentialById({ id, data }) {
    await prisma.credential.update({
      where: { id },
      data
    });
  }
  static async deleteAllByDelegationCredentialId({
    delegationCredentialId
  }) {
    return prisma.credential.deleteMany({ where: { delegationCredentialId } });
  }
  static async findCredentialForCalendarServiceById({ id }) {
    const dbCredential = await prisma.credential.findUnique({
      where: { id },
      select: credentialForCalendarServiceSelect
    });
    if (!dbCredential) {
      return dbCredential;
    }
    return buildNonDelegationCredential(dbCredential);
  }
  static async findByIdIncludeDelegationCredential({ id }) {
    const dbCredential = await prisma.credential.findUnique({
      where: { id },
      select: { ...credentialForCalendarServiceSelect, delegationCredential: true }
    });
    return dbCredential;
  }
  static async findAllDelegationByUserIdsListAndDelegationCredentialIdAndType({
    userIds,
    delegationCredentialId,
    type
  }) {
    return prisma.credential.findMany({
      where: {
        userId: {
          in: userIds
        },
        delegationCredentialId,
        type
      },
      select: {
        userId: true
      }
    });
  }
  static async findAllDelegationByTypeIncludeUserAndTake({ type, take }) {
    const delegationUserCredentials = await prisma.credential.findMany({
      where: {
        delegationCredentialId: { not: null },
        type
      },
      include: {
        user: {
          select: {
            email: true,
            id: true
          }
        }
      },
      take
    });
    return delegationUserCredentials.map(({ delegationCredentialId, ...rest }) => {
      return {
        ...rest,
        // We queried only those where delegationCredentialId is not null
        // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
        delegationCredentialId
      };
    });
  }
  static async findUniqueByUserIdAndDelegationCredentialId({
    userId,
    delegationCredentialId
  }) {
    const delegationUserCredentials = await prisma.credential.findMany({
      where: {
        userId,
        delegationCredentialId
      }
    });
    if (delegationUserCredentials.length > 1) {
      log.error(`DelegationCredential: Multiple delegation user credentials found - this should not happen`, {
        userId,
        delegationCredentialId
      });
    }
    return delegationUserCredentials[0];
  }
  static async updateWhereUserIdAndDelegationCredentialId({
    userId,
    delegationCredentialId,
    data
  }) {
    return prisma.credential.updateMany({
      where: {
        userId,
        delegationCredentialId
      },
      data
    });
  }
  static async createDelegationCredential({
    userId,
    delegationCredentialId,
    type,
    key,
    appId
  }) {
    return prisma.credential.create({ data: { userId, delegationCredentialId, type, key, appId } });
  }
  static async updateWhereId({ id, data }) {
    return prisma.credential.update({ where: { id }, data });
  }
  static async findPaymentCredentialByAppIdAndTeamId({
    appId,
    teamId
  }) {
    return await prisma.credential.findFirst({
      where: {
        teamId,
        appId
      },
      include: {
        app: true
      }
    });
  }
  static async findPaymentCredentialByAppIdAndUserId({
    appId,
    userId
  }) {
    return await prisma.credential.findFirst({
      where: {
        userId,
        appId
      },
      include: {
        app: true
      }
    });
  }
  static async findPaymentCredentialByAppIdAndUserIdOrTeamId({
    appId,
    userId,
    teamId
  }) {
    const idToSearchObject = teamId ? { teamId } : { userId };
    return await prisma.credential.findFirst({
      where: {
        ...idToSearchObject,
        appId
      },
      include: {
        app: true
      }
    });
  }
}
export {
  CredentialRepository as C,
  DelegationCredentialRepository as D,
  enrichUserWithDelegationConferencingCredentialsWithoutOrgId as a,
  enrichHostsWithDelegationCredentials as b,
  checkIfSuccessfullyConfiguredInWorkspace as c,
  getAllDelegationCredentialsForUserIncludeServiceAccountKey as d,
  enrichUserWithDelegationCredentialsIncludeServiceAccountKey as e,
  getDelegationCredentialOrFindRegularCredential as f,
  getCredentialForCalendarCache as g,
  buildAllCredentials as h,
  getFirstDelegationConferencingCredentialAppLocation as i,
  enrichUsersWithDelegationCredentials as j,
  encryptServiceAccountKey as k
};
