"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const utils = require("./utils-PVpkHS-H.cjs");
const z = require("zod");
const _metadata = require("./_metadata-cJJEBrFE.cjs");
const payment_services_generated = require("./payment.services.generated-GxibcY-e.cjs");
const credential = require("./credential-yvBSPLqv.cjs");
const isPrismaObj = require("./isPrismaObj-fQw4PHjD.cjs");
const getUsersCredentials = require("./getUsersCredentials-pRIw8lRu.cjs");
const CalEventParser = require("./CalEventParser-mh8lC_8R.cjs");
const index = require("./i18n-Bs8xJzoY.cjs");
const user = require("./user-7XDeDEMd.cjs");
const index$1 = require("./email-manager-aaSsaN-j.cjs");
const getEnabledAppsFromCredentials = require("./getEnabledAppsFromCredentials-qzc-LlKo.cjs");
const client = require("@prisma/client");
const server = require("@trpc/server");
const cache_js = require("next/cache.js");
const membership = require("./membership-tqAzHYj6.cjs");
const CalendarAppError = require("./CalendarAppError-RC_O0RpM.cjs");
const universalSchema = require("./universalSchema-bsuJA9VF.cjs");
const CalendarService = require("./CalendarService-xOmyTlu5.cjs");
const CalendarService$1 = require("./CalendarService-2NmeX26w.cjs");
const deletePayment = async (paymentId, paymentAppCredentials) => {
  const key = paymentAppCredentials?.app?.dirName;
  const paymentAppImportFn = payment_services_generated.PaymentServiceMap[key];
  if (!paymentAppImportFn) {
    console.warn(`payment app not implemented for key: ${key}`);
    return false;
  }
  const paymentAppModule = await paymentAppImportFn;
  if (!paymentAppModule?.PaymentService) {
    console.warn(`payment App service not found for key: ${key}`);
    return false;
  }
  const PaymentService = paymentAppModule.PaymentService;
  const paymentInstance = new PaymentService(paymentAppCredentials);
  const deleted = await paymentInstance.deletePayment(paymentId);
  return deleted;
};
const isVideoOrConferencingApp = (app) => app?.categories.includes(index.AppCategories.video) || app?.categories.includes(index.AppCategories.conferencing);
const getRemovedIntegrationNameFromAppSlug = (slug) => slug === "msteams" ? "office365_video" : slug.split("-")[0];
const locationsSchema = z.array(z.object({ type: z.string() }));
const handleDeleteCredential = async ({
  userId,
  userMetadata,
  credentialId,
  teamId
}) => {
  const credential2 = await index.prisma.credential.findFirst({
    where: {
      id: credentialId,
      ...teamId ? { teamId } : { userId }
    },
    select: {
      ...index.credentialForCalendarServiceSelect,
      app: {
        select: {
          slug: true,
          categories: true,
          dirName: true
        }
      }
    }
  });
  if (!credential2) {
    throw new Error("Credential not found");
  }
  const eventTypes = await index.prisma.eventType.findMany({
    where: {
      OR: [
        {
          ...teamId ? { teamId } : { userId }
        },
        // for managed events
        {
          parent: {
            teamId
          }
        }
      ]
    },
    select: {
      id: true,
      locations: true,
      destinationCalendar: {
        include: {
          credential: true
        }
      },
      price: true,
      currency: true,
      metadata: true
    }
  });
  for (const eventType of eventTypes) {
    if (eventType.locations && isVideoOrConferencingApp(credential2.app)) {
      const integrationQuery = getRemovedIntegrationNameFromAppSlug(credential2.app?.slug ?? "");
      const locations = locationsSchema.parse(eventType.locations);
      const doesDailyVideoAlreadyExists = locations.some(
        (location) => location.type.includes(CalEventParser.DailyLocationType)
      );
      const updatedLocations = locations.reduce((acc, location) => {
        if (location.type.includes(integrationQuery)) {
          if (!doesDailyVideoAlreadyExists)
            acc.push({ type: CalEventParser.DailyLocationType });
        } else {
          acc.push(location);
        }
        return acc;
      }, []);
      await index.prisma.eventType.update({
        where: {
          id: eventType.id
        },
        data: {
          locations: updatedLocations
        }
      });
    }
    if (credential2.app?.categories.includes(index.AppCategories.calendar) && eventType.destinationCalendar?.credential?.appId === credential2.appId) {
      const destinationCalendar = await index.prisma.destinationCalendar.findUnique({
        where: {
          id: eventType.destinationCalendar?.id
        }
      });
      if (destinationCalendar) {
        await index.prisma.destinationCalendar.delete({
          where: {
            id: destinationCalendar.id
          }
        });
      }
    }
    if (credential2.app?.categories.includes(index.AppCategories.crm)) {
      const metadata2 = index.EventTypeMetaDataSchema.parse(eventType.metadata);
      const appSlugToDelete = credential2.app?.slug;
      const apps = index.eventTypeAppMetadataOptionalSchema.parse(metadata2?.apps);
      if (appSlugToDelete) {
        const appMetadata = removeAppFromEventTypeMetadata(appSlugToDelete, {
          apps
        });
        await index.prisma.$transaction(async () => {
          await index.prisma.eventType.update({
            where: {
              id: eventType.id
            },
            data: {
              hidden: true,
              metadata: {
                ...metadata2,
                apps: {
                  ...appMetadata
                }
              }
            }
          });
        });
      }
    }
    if (credential2.app?.categories.includes(index.AppCategories.payment)) {
      const metadata2 = index.EventTypeMetaDataSchema.parse(eventType.metadata);
      const appSlug = credential2.app?.slug;
      if (appSlug) {
        const apps = index.eventTypeAppMetadataOptionalSchema.parse(metadata2?.apps);
        const appMetadata = removeAppFromEventTypeMetadata(appSlug, {
          apps
        });
        await index.prisma.$transaction(async () => {
          await index.prisma.eventType.update({
            where: {
              id: eventType.id
            },
            data: {
              hidden: true,
              metadata: {
                ...metadata2,
                apps: {
                  ...appMetadata
                }
              }
            }
          });
          const unpaidBookings = await index.prisma.booking.findMany({
            where: {
              userId,
              eventTypeId: eventType.id,
              status: "PENDING",
              paid: false,
              payment: {
                every: {
                  success: false
                }
              }
            },
            select: {
              ...index.bookingMinimalSelect,
              recurringEventId: true,
              userId: true,
              responses: true,
              user: {
                select: {
                  id: true,
                  credentials: true,
                  email: true,
                  timeZone: true,
                  name: true,
                  destinationCalendar: true,
                  locale: true
                }
              },
              location: true,
              references: {
                select: {
                  uid: true,
                  type: true,
                  externalCalendarId: true
                }
              },
              payment: true,
              paid: true,
              eventType: {
                select: {
                  recurringEvent: true,
                  title: true,
                  bookingFields: true,
                  seatsPerTimeSlot: true,
                  seatsShowAttendees: true,
                  eventName: true,
                  hideOrganizerEmail: true,
                  team: {
                    select: {
                      id: true,
                      name: true
                    }
                  },
                  metadata: true
                }
              },
              uid: true,
              eventTypeId: true,
              destinationCalendar: true
            }
          });
          for (const booking of unpaidBookings) {
            await index.prisma.booking.update({
              where: {
                id: booking.id
              },
              data: {
                status: index.BookingStatus.CANCELLED,
                cancellationReason: "Payment method removed"
              }
            });
            for (const payment of booking.payment) {
              try {
                await deletePayment(payment.id, credential2);
              } catch (e) {
                console.error(e);
              }
              await index.prisma.payment.delete({
                where: {
                  id: payment.id
                }
              });
            }
            await index.prisma.attendee.deleteMany({
              where: {
                bookingId: booking.id
              }
            });
            await index.prisma.bookingReference.deleteMany({
              where: {
                bookingId: booking.id
              }
            });
            const attendeesListPromises = booking.attendees.map(async (attendee) => {
              return {
                name: attendee.name,
                email: attendee.email,
                timeZone: attendee.timeZone,
                language: {
                  translate: await index.getTranslation(attendee.locale ?? "en", "common"),
                  locale: attendee.locale ?? "en"
                }
              };
            });
            const attendeesList = await Promise.all(attendeesListPromises);
            const tOrganizer = await index.getTranslation(booking?.user?.locale ?? "en", "common");
            await index$1.sendCancelledEmailsAndSMS(
              {
                type: booking?.eventType?.title,
                title: booking.title,
                description: booking.description,
                customInputs: isPrismaObj.isPrismaObjOrUndefined(booking.customInputs),
                ...payment_services_generated.getCalEventResponses({
                  bookingFields: booking.eventType?.bookingFields ?? null,
                  booking
                }),
                startTime: booking.startTime.toISOString(),
                endTime: booking.endTime.toISOString(),
                organizer: {
                  email: booking?.userPrimaryEmail ?? booking?.user?.email,
                  name: booking?.user?.name ?? "Nameless",
                  timeZone: booking?.user?.timeZone,
                  language: { translate: tOrganizer, locale: booking?.user?.locale ?? "en" }
                },
                attendees: attendeesList,
                uid: booking.uid,
                recurringEvent: getUsersCredentials.parseRecurringEvent(booking.eventType?.recurringEvent),
                location: booking.location,
                destinationCalendar: booking.destinationCalendar ? [booking.destinationCalendar] : booking.user?.destinationCalendar ? [booking.user?.destinationCalendar] : [],
                cancellationReason: "Payment method removed by organizer",
                seatsPerTimeSlot: booking.eventType?.seatsPerTimeSlot,
                seatsShowAttendees: booking.eventType?.seatsShowAttendees,
                hideOrganizerEmail: booking.eventType?.hideOrganizerEmail,
                team: !!booking.eventType?.team ? {
                  name: booking.eventType.team.name,
                  id: booking.eventType.team.id,
                  members: []
                } : void 0
              },
              {
                eventName: booking?.eventType?.eventName
              },
              booking?.eventType?.metadata
            );
          }
        });
      }
    } else if (utils.appStoreMetadata[credential2.app?.slug]?.extendsFeature === "EventType") {
      const metadata2 = index.eventTypeMetaDataSchemaWithTypedApps.parse(eventType.metadata);
      const appSlug = credential2.app?.slug;
      if (appSlug) {
        await index.prisma.eventType.update({
          where: {
            id: eventType.id
          },
          data: {
            hidden: true,
            metadata: {
              ...metadata2,
              apps: {
                ...metadata2?.apps,
                [appSlug]: void 0
              }
            }
          }
        });
      }
    }
  }
  if (credential2.app?.slug === "zapier" || credential2.app?.slug === "make") {
    const ownerFilter = teamId ? { teamId } : { userId };
    await index.prisma.apiKey.deleteMany({
      where: {
        ...ownerFilter,
        appId: credential2.app.slug
      }
    });
    await index.prisma.webhook.deleteMany({
      where: {
        ...ownerFilter,
        appId: credential2.app.slug
      }
    });
    payment_services_generated.deleteWebhookScheduledTriggers({
      appId: credential2.appId,
      userId: teamId ? void 0 : userId,
      teamId
    });
  }
  let metadata = index.userMetadata.parse(userMetadata);
  if (credential2.app?.slug === metadata?.defaultConferencingApp?.appSlug) {
    metadata = {
      ...metadata,
      defaultConferencingApp: void 0
    };
    await index.prisma.user.update({
      where: {
        id: userId
      },
      data: {
        metadata
      }
    });
  }
  if (credential2.app?.categories.includes(index.AppCategories.calendar)) {
    try {
      const calendar = await _metadata.getCalendar(user.buildNonDelegationCredential(credential2));
      const calendars = await calendar?.listCalendars();
      const calendarIds = calendars?.map((cal) => cal.externalId);
      await index.prisma.selectedCalendar.deleteMany({
        where: {
          userId,
          integration: credential2.type,
          externalId: {
            in: calendarIds
          }
        }
      });
    } catch (error) {
      console.warn(
        `Error deleting selected calendars for userId: ${userId} integration: ${credential2.type}`,
        error
      );
    }
  }
  await index.prisma.credential.delete({
    where: {
      id: credentialId
    }
  });
};
const removeAppFromEventTypeMetadata = (appSlugToDelete, eventTypeMetadata) => {
  const appMetadata = eventTypeMetadata?.apps ? Object.entries(eventTypeMetadata.apps).reduce((filteredApps, [appName, appData]) => {
    if (appName !== appSlugToDelete) {
      filteredApps[appName] = appData;
    }
    return filteredApps;
  }, {}) : {};
  return appMetadata;
};
const handleDeleteCredential$1 = handleDeleteCredential;
const safeWorkspacePlatformSelect = {
  id: true,
  name: true,
  enabled: true,
  slug: true,
  description: true
};
const workspacePlatformSelectWithServiceAccountKey = {
  ...safeWorkspacePlatformSelect,
  defaultServiceAccountKey: true
};
class WorkspacePlatformRepository {
  static withParsedServiceAccountKey(data) {
    return {
      ...data,
      defaultServiceAccountKey: index.serviceAccountKeySchema.parse(data.defaultServiceAccountKey)
    };
  }
  static async create(data) {
    const { defaultServiceAccountKey: _defaultServiceAccountKey, ...rest } = data;
    const defaultServiceAccountKey = _defaultServiceAccountKey === void 0 || _defaultServiceAccountKey === null ? client.Prisma.JsonNull : _defaultServiceAccountKey;
    return await index.prisma.workspacePlatform.create({
      data: {
        defaultServiceAccountKey,
        ...rest
      },
      select: safeWorkspacePlatformSelect
    });
  }
  static async findAll() {
    return await index.prisma.workspacePlatform.findMany({
      select: safeWorkspacePlatformSelect
    });
  }
  static async findAllBySlug({ slug }) {
    return await index.prisma.workspacePlatform.findMany({
      where: { slug },
      select: safeWorkspacePlatformSelect
    });
  }
  static async findBySlug({ slug }) {
    return await index.prisma.workspacePlatform.findUnique({
      where: { slug },
      select: safeWorkspacePlatformSelect
    });
  }
  static async findBySlugIncludeSensitiveServiceAccountKey({ slug }) {
    const workspacePlatform = await index.prisma.workspacePlatform.findUnique({
      where: { slug },
      select: workspacePlatformSelectWithServiceAccountKey
    });
    if (!workspacePlatform) {
      return null;
    }
    return this.withParsedServiceAccountKey(workspacePlatform);
  }
  static async updateById({
    id,
    data
  }) {
    return await index.prisma.workspacePlatform.update({
      where: { id },
      data,
      select: safeWorkspacePlatformSelect
    });
  }
}
const log$2 = index.logger.getSubLogger({ prefix: ["delegationCredential/utils"] });
class InvalidServiceAccountKeyError extends Error {
  constructor(message) {
    super(message);
    this.name = "InvalidServiceAccountKeyError";
  }
}
async function ensureDelegationCredentialNotAlreadyConfigured({
  domain,
  currentOrganizationId,
  delegationCredentialBeingUpdatedId
}) {
  const allDelegationsForDomain = await credential.DelegationCredentialRepository.findAllByDomain({
    domain
  });
  const conflictingDelegationInCurrentOrg = allDelegationsForDomain.find(
    (delegation) => delegation.organizationId === currentOrganizationId && delegation.id !== delegationCredentialBeingUpdatedId
  );
  if (conflictingDelegationInCurrentOrg) {
    throw new server.TRPCError({
      code: "BAD_REQUEST",
      message: `Your organization already has delegation credential for ${conflictingDelegationInCurrentOrg.domain}`
    });
  }
  const differentOrgEnabledDelegations = allDelegationsForDomain.filter(
    (delegation) => delegation.organizationId !== currentOrganizationId && delegation.enabled
  );
  if (differentOrgEnabledDelegations.length > 0) {
    throw new server.TRPCError({
      code: "BAD_REQUEST",
      message: `Domain ${domain} already has delegation credential enabled in another organization`
    });
  }
}
const handleDelegationCredentialError = (error) => {
  if (error instanceof InvalidServiceAccountKeyError) {
    throw new server.TRPCError({
      code: "BAD_REQUEST",
      message: error.message
    });
  }
  if (error instanceof server.TRPCError) {
    throw error;
  }
  log$2.error("Error handling delegation credential:", index.safeStringify(error));
  throw new server.TRPCError({
    code: "INTERNAL_SERVER_ERROR",
    message: "An error occurred while handling delegation credential settings."
  });
};
const ensureNoServiceAccountKey = (delegationCredential) => {
  if (!delegationCredential) {
    return null;
  }
  const { serviceAccountKey: _1, ...rest } = delegationCredential;
  return {
    ...rest,
    serviceAccountKey: void 0
  };
};
async function handler({
  input,
  ctx
}) {
  const { workspacePlatformSlug, domain, serviceAccountKey } = input;
  const { user: user2 } = ctx;
  const { organizationId } = user2;
  if (!organizationId) {
    throw new server.TRPCError({
      code: "UNAUTHORIZED",
      message: "You must be part of an organization to add a delegation credential"
    });
  }
  try {
    const workspacePlatform = await WorkspacePlatformRepository.findBySlug({
      slug: workspacePlatformSlug
    });
    if (!workspacePlatform) {
      throw new server.TRPCError({
        code: "NOT_FOUND",
        message: `Workspace platform ${workspacePlatformSlug} not found`
      });
    }
    await ensureDelegationCredentialNotAlreadyConfigured({
      domain,
      currentOrganizationId: organizationId,
      delegationCredentialBeingUpdatedId: null
    });
    const createdDelegation = await credential.DelegationCredentialRepository.create({
      workspacePlatformId: workspacePlatform.id,
      domain,
      // We don't want to enable by default because enabling requires some checks to be completed and it has a separate flow.
      enabled: false,
      organizationId,
      serviceAccountKey
    });
    return ensureNoServiceAccountKey(createdDelegation);
  } catch (error) {
    handleDelegationCredentialError(error);
  }
}
const computeInstallCountsFromDB = async () => {
  const mostPopularApps = z.z.array(z.z.object({ appId: z.z.string(), installCount: z.z.number() })).parse(
    await index.prisma.$queryRaw`
    SELECT
      c."appId",
      COUNT(*)::integer AS "installCount"
    FROM
      "Credential" c
    WHERE
      c."appId" IS NOT NULL
    GROUP BY
      c."appId"
    ORDER BY
      "installCount" DESC
    `
  );
  return mostPopularApps.reduce((acc, { appId, installCount }) => {
    acc[appId] = installCount;
    return acc;
  }, {});
};
const getInstallCountPerApp = async () => {
  return cache_js.unstable_cache(async () => computeInstallCountsFromDB(), ["app-install-counts"], {
    revalidate: 300,
    tags: ["app-install-counts"]
  })();
};
async function getConnectedApps({
  user: user$1,
  prisma,
  input
}) {
  const {
    variant,
    exclude,
    onlyInstalled,
    includeTeamInstalledApps,
    extendsFeature,
    teamId,
    sortByMostPopular,
    sortByInstalledFirst,
    appId
  } = input;
  let credentials = await getUsersCredentials.getUsersCredentialsIncludeServiceAccountKey(user$1);
  let userTeams = [];
  if (includeTeamInstalledApps || teamId) {
    const teamsQuery = await prisma.team.findMany({
      where: {
        ...teamId ? { id: teamId } : {},
        members: {
          some: {
            userId: user$1.id,
            accepted: true
          }
        }
      },
      select: {
        id: true,
        credentials: {
          select: index.credentialForCalendarServiceSelect
        },
        name: true,
        logoUrl: true,
        members: {
          where: {
            userId: user$1.id
          },
          select: {
            role: true
          }
        },
        parent: {
          select: {
            id: true,
            credentials: {
              select: index.credentialForCalendarServiceSelect
            },
            name: true,
            logoUrl: true,
            members: {
              where: {
                userId: user$1.id
              },
              select: {
                role: true
              }
            }
          }
        }
      }
    });
    const parentTeams = [];
    if (teamId) {
      teamsQuery.forEach((team) => {
        if (team?.parent) {
          const { parent, ...filteredTeam } = team;
          if (!teamsQuery.some((t) => t.id === parent.id)) {
            parentTeams.push(parent);
          }
        }
      });
    }
    userTeams = [...teamsQuery, ...parentTeams];
    const teamAppCredentials = userTeams.flatMap((teamApp) => {
      return teamApp.credentials ? user.buildNonDelegationCredentials(teamApp.credentials.flat()) : [];
    });
    if (!includeTeamInstalledApps || teamId) {
      credentials = teamAppCredentials;
    } else {
      credentials = credentials.concat(teamAppCredentials);
    }
  }
  const enabledApps = await getEnabledAppsFromCredentials.getEnabledAppsFromCredentials(credentials, {
    filterOnCredentials: onlyInstalled,
    ...appId ? { where: { slug: appId } } : {}
  });
  let apps = await Promise.all(
    enabledApps.map(async ({ credentials: _, credential: credential2, key: _2, ...app }) => {
      const userCredentialIds = credentials.filter((c) => c.appId === app.slug && !c.teamId).map((c) => c.id);
      const invalidCredentialIds = credentials.filter((c) => c.appId === app.slug && c.invalid).map((c) => c.id);
      const teams = await Promise.all(
        credentials.filter((c) => c.appId === app.slug && c.teamId).map(async (c) => {
          const team = userTeams.find((team2) => team2.id === c.teamId);
          if (!team) {
            return null;
          }
          return {
            teamId: team.id,
            name: team.name,
            logoUrl: team.logoUrl,
            credentialId: c.id,
            isAdmin: getUsersCredentials.checkAdminOrOwner(team.members[0].role)
          };
        })
      );
      const credentialOwner = {
        name: user$1.name,
        avatar: user$1?.avatar ?? user$1?.avatarUrl
      };
      let isSetupAlready = void 0;
      if (credential2 && app.categories.includes("payment")) {
        const paymentAppImportFn = payment_services_generated.PaymentServiceMap[app.dirName];
        if (paymentAppImportFn) {
          const paymentApp = await paymentAppImportFn;
          if (paymentApp && "PaymentService" in paymentApp && paymentApp?.PaymentService) {
            const PaymentService = paymentApp.PaymentService;
            const paymentInstance = new PaymentService(credential2);
            isSetupAlready = paymentInstance.isSetupAlready();
          }
        }
      }
      let dependencyData = [];
      if (app.dependencies?.length) {
        dependencyData = app.dependencies.map((dependency) => {
          const dependencyInstalled = enabledApps.some(
            (dbAppIterator) => dbAppIterator.credentials.length && dbAppIterator.slug === dependency
          );
          const dependencyName = utils.getAppFromSlug(dependency)?.name;
          return { name: dependencyName, installed: dependencyInstalled };
        });
      }
      return {
        ...app,
        ...teams.length && {
          credentialOwner
        },
        userCredentialIds,
        invalidCredentialIds,
        teams,
        isInstalled: !!userCredentialIds.length || !!teams.length || app.isGlobal,
        isSetupAlready,
        ...app.dependencies && { dependencyData }
      };
    })
  );
  if (variant) {
    apps = apps.flatMap((item) => item.variant.startsWith(variant) ? [item] : []);
  }
  if (exclude) {
    apps = apps.filter((item) => exclude ? !exclude.includes(item.variant) : true);
  }
  if (onlyInstalled) {
    apps = apps.flatMap(
      (item) => item.userCredentialIds.length > 0 || item.teams.length || item.isGlobal ? [item] : []
    );
  }
  if (extendsFeature) {
    apps = apps.filter((app) => app.extendsFeature?.includes(extendsFeature)).map((app) => ({
      ...app,
      isInstalled: !!app.userCredentialIds?.length || !!app.teams?.length || app.isGlobal
    }));
  }
  if (sortByMostPopular) {
    const installCountPerApp = await getInstallCountPerApp();
    apps.sort((a, b) => {
      const aCount = installCountPerApp[a.slug] || 0;
      const bCount = installCountPerApp[b.slug] || 0;
      return bCount - aCount;
    });
  }
  if (sortByInstalledFirst) {
    apps.sort((a, b) => {
      return (a.isInstalled ? 0 : 1) - (b.isInstalled ? 0 : 1);
    });
  }
  return {
    items: apps
  };
}
const log$1 = index.logger.getSubLogger({ prefix: ["[DelegationCredential]"] });
async function getAffectedMembersForDisable({
  delegationCredentialId
}) {
  const delegationCredential = await credential.DelegationCredentialRepository.findById({ id: delegationCredentialId });
  if (!delegationCredential) {
    return [];
  }
  const lastEnabledAt = delegationCredential.lastEnabledAt;
  if (!lastEnabledAt) {
    log$1.info(
      `Delegation credential ${delegationCredentialId} has no lastEnabledAt, so assuming no members were affected`
    );
    return [];
  }
  const membershipsThatCouldPotentiallyBeAffected = await membership.MembershipRepository.findMembershipsCreatedAfterTimeIncludeUser({
    organizationId: delegationCredential.organizationId,
    time: lastEnabledAt
  });
  return membershipsThatCouldPotentiallyBeAffected.map((membership2) => ({
    email: membership2.user.email,
    name: membership2.user.name,
    id: membership2.user.id
  }));
}
const log = index.logger.getSubLogger({ prefix: ["viewer", "delegationCredential", "toggleEnabled"] });
async function toggleDelegationCredentialEnabled(loggedInUser, input) {
  const currentDelegationCredential = await credential.DelegationCredentialRepository.findById({
    id: input.id
  });
  if (!currentDelegationCredential) {
    throw new Error("Delegation credential not found");
  }
  const shouldBeEnabled = input.enabled;
  if (shouldBeEnabled === currentDelegationCredential.enabled) {
    return currentDelegationCredential;
  }
  if (shouldBeEnabled) {
    await assertWorkspaceConfigured({
      delegationCredentialId: input.id,
      user: loggedInUser
    });
  }
  if (!shouldBeEnabled) {
    const affectedMemberships = await getAffectedMembersForDisable({ delegationCredentialId: input.id });
    const slug = currentDelegationCredential.workspacePlatform?.slug;
    if (!slug) {
      log.error(`Delegation credential ${input.id} has no workspace platform slug`);
    }
    let calendarAppName;
    let conferencingAppName;
    if (slug === "google") {
      calendarAppName = "Google Calendar";
      conferencingAppName = "Google Meet";
    } else if (slug === "office365") {
      calendarAppName = "Microsoft 365";
      conferencingAppName = "Microsoft Teams";
    } else {
      throw new Error(`Unsupported workspace platform slug: ${slug}`);
    }
    for (const membership2 of affectedMemberships) {
      if (membership2.email) {
        await index$1.sendDelegationCredentialDisabledEmail({
          recipientEmail: membership2.email,
          recipientName: membership2.name || void 0,
          calendarAppName,
          conferencingAppName
        });
      }
    }
  }
  const updatedDelegationCredential = await credential.DelegationCredentialRepository.updateById({
    id: input.id,
    data: {
      enabled: shouldBeEnabled,
      // Don't touch lastEnabledAt if we are disabling
      lastEnabledAt: shouldBeEnabled ? /* @__PURE__ */ new Date() : void 0,
      // Don't touch lastDisabledAt if we are enabling
      lastDisabledAt: shouldBeEnabled ? void 0 : /* @__PURE__ */ new Date()
    }
  });
  return ensureNoServiceAccountKey(updatedDelegationCredential);
}
const assertWorkspaceConfigured = async ({
  delegationCredentialId,
  user: user2
}) => {
  const delegationCredential = await credential.DelegationCredentialRepository.findByIdIncludeSensitiveServiceAccountKey(
    {
      id: delegationCredentialId
    }
  );
  if (!delegationCredential) {
    throw new Error("Domain wide delegation not found");
  }
  if (!hasServiceAccountKey(delegationCredential)) {
    throw new Error("Domain wide delegation doesn't have service account key");
  }
  const isSuccessfullyConfigured = await credential.checkIfSuccessfullyConfiguredInWorkspace({
    delegationCredential,
    user: user2
  });
  if (!isSuccessfullyConfigured) {
    throw new Error("Workspace not successfully configured");
  }
};
function hasServiceAccountKey(delegationCredential) {
  return delegationCredential.serviceAccountKey !== null;
}
exports.getAppFromSlug = utils.getAppFromSlug;
exports.getApps = utils.getApps;
exports.DelegationCredentialRepository = credential.DelegationCredentialRepository;
exports.enrichUserWithDelegationConferencingCredentialsWithoutOrgId = credential.enrichUserWithDelegationConferencingCredentialsWithoutOrgId;
exports.getUsersCredentialsIncludeServiceAccountKey = getUsersCredentials.getUsersCredentialsIncludeServiceAccountKey;
exports.getEnabledAppsFromCredentials = getEnabledAppsFromCredentials.getEnabledAppsFromCredentials;
exports.CalendarAppDelegationCredentialClientIdNotAuthorizedError = CalendarAppError.CalendarAppDelegationCredentialClientIdNotAuthorizedError;
exports.CalendarAppDelegationCredentialConfigurationError = CalendarAppError.CalendarAppDelegationCredentialConfigurationError;
exports.CalendarAppDelegationCredentialError = CalendarAppError.CalendarAppDelegationCredentialError;
exports.CalendarAppDelegationCredentialInvalidGrantError = CalendarAppError.CalendarAppDelegationCredentialInvalidGrantError;
exports.CalendarAppDelegationCredentialNotSetupError = CalendarAppError.CalendarAppDelegationCredentialNotSetupError;
exports.CalendarAppError = CalendarAppError.CalendarAppError;
exports.OAuth2UniversalSchema = universalSchema.OAuth2UniversalSchema;
exports.IcsFeedCalendarService = CalendarService.default;
exports.CalendarService = CalendarService$1.default;
exports.addDelegationCredential = handler;
exports.getConnectedApps = getConnectedApps;
exports.handleDeleteCredential = handleDeleteCredential$1;
exports.toggleDelegationCredentialEnabled = toggleDelegationCredentialEnabled;
