import { a as allowDisablingHostConfirmationEmails, b as allowDisablingAttendeeConfirmationEmails } from "./allowDisablingStandardEmails-jEot2g-l.js";
import { E } from "./allowDisablingStandardEmails-jEot2g-l.js";
import { F as privacyFilteredLocations, D as DailyLocationType, G as defaultLocations } from "./CalEventParser-ZzmnrFso.js";
import { b as getAppFromSlug, g as getApps, i as defaultVideoAppCategories } from "./utils-xu1OORoz.js";
import "./index-rbwdGzy0.js";
import { ax as getBookingFieldsWithSystemFields, ay as markdownToSafeHTML, F as sendSlugReplacementEmail, an as tasker, au as getBookerBaseUrl, az as hasFilter } from "./email-manager-RBMYQEU9.js";
import { aA } from "./email-manager-RBMYQEU9.js";
import { v as getOrgFullOrigin, p as prisma, bb as allManagedEventTypeProps, bc as unlockedManagedEventTypeProps, bd as getSlugOrRequestedSlug, U as UserRepository, aD as userMetadata, be as bookerLayoutOptions, bf as BookerLayouts, bg as bookerLayouts, e as eventTypeMetaDataSchemaWithTypedApps, A as teamMetadataSchema, bh as customInputSchema, S as SchedulingType, o as getTranslation, l as logger, a as ProfileRepository, b as safeStringify, J as WEBAPP_URL, P as PeriodType, R as RRTimestampBasis, aO as eventTypeAppMetadataOptionalSchema, k as eventTypeLocations, ao as EventTypeAutoTranslatedField, E as EventTypeMetaDataSchema, c as credentialForCalendarServiceSelect, aL as buildNonDelegationCredentials, H as AppCategories, K as WEBSITE_URL, M as MembershipRole, bi as eventTypeMetaDataSchemaWithUntypedApps } from "./user--mpkKOwW.js";
import { aw } from "./user--mpkKOwW.js";
import { a as getUsernameList, g as getDefaultEvent } from "./defaultEvents-32zfEcYf.js";
import { g as getUserAvatarUrl } from "./getAvatarUrl-TW87R0cL.js";
import { i as isRecurringEvent, p as parseRecurringEvent } from "./isRecurringEvent-INEyXcIi.js";
import dayjs from "dayjs";
import { a, g } from "./getBulkEventTypes-v64v3nMp.js";
import { l as library } from "./library-kkFrLHWb.js";
import { g as getAppKeysFromSlug } from "./getAppKeysFromSlug-IDaQR-Xd.js";
import { g as getUsersCredentialsIncludeServiceAccountKey, c as checkAdminOrOwner } from "./getUsersCredentials-WMvzBTYT.js";
import { E as EventTypeRepository } from "./eventTypeRepository-xClplieB.js";
import { TRPCError, initTRPC } from "@trpc/server";
import { Prisma } from "@prisma/client";
import { _ as _EventTypeModel } from "./bookingtimestatusdenormalized-YAH7koTK.js";
import { a as ascendingLimitKeys, b as parseBookingLimit, p as parseDurationLimit } from "./isBookingLimits-2AKB36r0.js";
import { D as DestinationCalendarRepository, H as HashedLinkRepository, a as HashedLinkService, g as getEventTypeAppData, p as parseEventTypeColor } from "./destinationCalendar-SY4__xoB.js";
import { M as MembershipRepository } from "./membership-OqrlZlYw.js";
import { S as ScheduleRepository } from "./schedule-8CReg_DS.js";
import { i as indexBrowser } from "./index-browser-n4djLmCZ.js";
import { a as getCalendarCredentials, b as getConnectedCalendars } from "./CalendarManager-_TKzfJFU.js";
import { z } from "zod";
import superjson from "superjson";
import { setUser } from "@sentry/nextjs";
import { g as getEnabledAppsFromCredentials } from "./getEnabledAppsFromCredentials-xjA01Qrn.js";
import { b as enrichUserWithDelegationConferencingCredentialsWithoutOrgId } from "./credential-7rcNyyEv.js";
import { orderBy } from "lodash";
import "./team-AQqVMyqH.js";
const getBookerBaseUrlSync = (orgSlug, options) => {
  return getOrgFullOrigin(orgSlug ?? "", options);
};
function generateNewChildEventTypeDataForDB({
  eventType,
  userId,
  includeWorkflow = true,
  includeUserConnect = true
}) {
  const allManagedEventTypePropsZod = _EventTypeModel.pick(allManagedEventTypeProps).extend({
    bookingFields: _EventTypeModel.shape.bookingFields.nullish()
  });
  const managedEventTypeValues = allManagedEventTypePropsZod.omit(unlockedManagedEventTypeProps).parse(eventType);
  const unlockedEventTypeValues = allManagedEventTypePropsZod.pick(unlockedManagedEventTypeProps).parse(eventType);
  const currentWorkflowIds = Array.isArray(eventType.workflows) ? eventType.workflows.map((wf) => wf.workflowId) : [];
  return {
    ...managedEventTypeValues,
    ...unlockedEventTypeValues,
    bookingLimits: managedEventTypeValues.bookingLimits ?? void 0,
    recurringEvent: managedEventTypeValues.recurringEvent ?? void 0,
    metadata: managedEventTypeValues.metadata ?? void 0,
    bookingFields: managedEventTypeValues.bookingFields ?? void 0,
    durationLimits: managedEventTypeValues.durationLimits ?? void 0,
    eventTypeColor: managedEventTypeValues.eventTypeColor ?? void 0,
    rrSegmentQueryValue: managedEventTypeValues.rrSegmentQueryValue ?? void 0,
    onlyShowFirstAvailableSlot: managedEventTypeValues.onlyShowFirstAvailableSlot ?? false,
    userId,
    ...includeUserConnect && {
      users: {
        connect: [{ id: userId }]
      }
    },
    parentId: eventType.id,
    hidden: false,
    ...includeWorkflow && {
      workflows: currentWorkflowIds && {
        create: currentWorkflowIds.map((wfId) => ({ workflowId: wfId }))
      }
    }
  };
}
async function getEventTypesToAddNewMembers(teamId) {
  return await prisma.eventType.findMany({
    where: {
      team: { id: teamId },
      assignAllTeamMembers: true
    },
    select: {
      ...allManagedEventTypeProps,
      id: true,
      schedulingType: true
    }
  });
}
async function updateNewTeamMemberEventTypes(userId, teamId) {
  const eventTypesToAdd = await getEventTypesToAddNewMembers(teamId);
  eventTypesToAdd.length > 0 && await prisma.$transaction(
    eventTypesToAdd.map((eventType) => {
      if (eventType.schedulingType === "MANAGED") {
        return prisma.eventType.create({
          data: generateNewChildEventTypeDataForDB({
            eventType,
            userId
          })
        });
      } else {
        return prisma.eventType.update({
          where: { id: eventType.id },
          data: { hosts: { create: [{ userId, isFixed: eventType.schedulingType === "COLLECTIVE" }] } }
        });
      }
    })
  );
}
function getPlaceholderAvatar(avatar, name) {
  return avatar ? avatar : `https://eu.ui-avatars.com/api/?background=fff&color=f9f9f9&bold=true&background=000000&name=${encodeURIComponent(
    name || ""
  )}`;
}
function getOrgOrTeamAvatar(team) {
  return getPlaceholderAvatar(team.logoUrl || team.parent?.logoUrl, team.name);
}
const userSelect = {
  id: true,
  avatarUrl: true,
  username: true,
  name: true,
  weekStart: true,
  brandColor: true,
  darkBrandColor: true,
  theme: true,
  metadata: true,
  organization: {
    select: {
      id: true,
      name: true,
      slug: true,
      bannerUrl: true
    }
  },
  defaultScheduleId: true
};
const getPublicEventSelect = (fetchAllUsers) => {
  return {
    id: true,
    title: true,
    description: true,
    interfaceLanguage: true,
    eventName: true,
    slug: true,
    isInstantEvent: true,
    instantMeetingParameters: true,
    aiPhoneCallConfig: true,
    schedulingType: true,
    length: true,
    locations: true,
    customInputs: true,
    disableGuests: true,
    metadata: true,
    lockTimeZoneToggleOnBookingPage: true,
    lockedTimeZone: true,
    requiresConfirmation: true,
    autoTranslateDescriptionEnabled: true,
    fieldTranslations: {
      select: {
        translatedText: true,
        targetLocale: true,
        field: true
      }
    },
    requiresBookerEmailVerification: true,
    recurringEvent: true,
    price: true,
    currency: true,
    seatsPerTimeSlot: true,
    disableCancelling: true,
    disableRescheduling: true,
    allowReschedulingCancelledBookings: true,
    seatsShowAvailabilityCount: true,
    bookingFields: true,
    teamId: true,
    team: {
      select: {
        parentId: true,
        metadata: true,
        brandColor: true,
        darkBrandColor: true,
        slug: true,
        name: true,
        logoUrl: true,
        theme: true,
        hideTeamProfileLink: true,
        parent: {
          select: {
            slug: true,
            name: true,
            bannerUrl: true,
            logoUrl: true
          }
        },
        isPrivate: true
      }
    },
    successRedirectUrl: true,
    forwardParamsSuccessRedirect: true,
    workflows: {
      include: {
        workflow: {
          include: {
            steps: true
          }
        }
      }
    },
    hosts: {
      select: {
        user: {
          select: userSelect
        }
      },
      ...fetchAllUsers ? {} : { take: 3 }
    },
    owner: {
      select: userSelect
    },
    schedule: {
      select: {
        id: true,
        timeZone: true
      }
    },
    instantMeetingSchedule: {
      select: {
        id: true,
        timeZone: true
      }
    },
    periodType: true,
    periodDays: true,
    // days if limiting future bookings
    periodEndDate: true,
    //end date limit by range
    periodStartDate: true,
    //start date limit by range
    periodCountCalendarDays: true,
    // count calendar days? Or only business days based on periodDays
    hidden: true,
    assignAllTeamMembers: true,
    rescheduleWithSameRoundRobinHost: true,
    parent: {
      select: {
        team: {
          select: {
            theme: true,
            brandColor: true,
            darkBrandColor: true
          }
        }
      }
    }
  };
};
async function isCurrentlyAvailable({
  prisma: prisma2,
  instantMeetingScheduleId,
  availabilityTimezone,
  length
}) {
  const now = dayjs().tz(availabilityTimezone);
  const currentDay = now.day();
  const meetingEndTime = now.add(length, "minute");
  const res = await prisma2.schedule.findUniqueOrThrow({
    where: {
      id: instantMeetingScheduleId
    },
    select: {
      availability: true
    }
  });
  const dateOverride = res.availability.find((a2) => a2.date && dayjs(a2.date).isSame(now, "day"));
  if (dateOverride) {
    return !isAvailableInTimeSlot(dateOverride, now, meetingEndTime);
  }
  for (const availability of res.availability) {
    if (!availability.date && availability.days.includes(currentDay)) {
      const isAvailable = isAvailableInTimeSlot(availability, now, meetingEndTime);
      if (isAvailable) {
        return true;
      }
    }
  }
  return false;
}
function isAvailableInTimeSlot(availability, now, meetingEndTime) {
  const startTime = dayjs(availability.startTime).utc().format("HH:mm");
  const endTime = dayjs(availability.endTime).utc().format("HH:mm");
  const periodStart = now.startOf("day").hour(parseInt(startTime.split(":")[0])).minute(parseInt(startTime.split(":")[1]));
  const periodEnd = now.startOf("day").hour(parseInt(endTime.split(":")[0])).minute(parseInt(endTime.split(":")[1]));
  const isWithinPeriod = now.isBetween(periodStart, periodEnd, null, "[)") && meetingEndTime.isBetween(periodStart, periodEnd, null, "(]");
  return isWithinPeriod;
}
const getPublicEvent = async (username, eventSlug, isTeamEvent, org, prisma2, fromRedirectOfNonOrgLink, currentUserId, fetchAllUsers = false) => {
  const usernameList = getUsernameList(username);
  const orgQuery = org ? getSlugOrRequestedSlug(org) : null;
  if (usernameList.length > 1) {
    const usersInOrgContext = await new UserRepository(prisma2).findUsersByUsername({
      usernameList,
      orgSlug: org
    });
    const users2 = usersInOrgContext;
    const defaultEvent = getDefaultEvent(eventSlug);
    let locations = defaultEvent.locations ? defaultEvent.locations : [];
    const firstUsersMetadata = userMetadata.parse(users2[0].metadata || {});
    const preferedLocationType = firstUsersMetadata?.defaultConferencingApp;
    if (preferedLocationType?.appSlug) {
      const foundApp = getAppFromSlug(preferedLocationType.appSlug);
      const appType = foundApp?.appData?.location?.type;
      if (appType) {
        locations = [{ type: appType, link: preferedLocationType.appLink }];
      }
    }
    const defaultEventBookerLayouts = {
      enabledLayouts: [...bookerLayoutOptions],
      defaultLayout: BookerLayouts.MONTH_VIEW
    };
    const disableBookingTitle = !defaultEvent.isDynamic;
    const unPublishedOrgUser = users2.find((user) => user.profile?.organization?.slug === null);
    let orgDetails2;
    if (org) {
      orgDetails2 = await prisma2.team.findFirstOrThrow({
        where: {
          slug: org
        },
        select: {
          logoUrl: true,
          name: true
        }
      });
    }
    return {
      ...defaultEvent,
      bookingFields: getBookingFieldsWithSystemFields({ ...defaultEvent, disableBookingTitle }),
      // Clears meta data since we don't want to send this in the public api.
      subsetOfUsers: users2.map((user) => ({
        ...user,
        metadata: void 0,
        bookerUrl: getBookerBaseUrlSync(user.profile?.organization?.slug ?? null)
      })),
      users: fetchAllUsers ? users2.map((user) => ({
        ...user,
        metadata: void 0,
        bookerUrl: getBookerBaseUrlSync(user.profile?.organization?.slug ?? null)
      })) : void 0,
      locations: privacyFilteredLocations(locations),
      profile: {
        weekStart: users2[0].weekStart,
        brandColor: users2[0].brandColor,
        darkBrandColor: users2[0].darkBrandColor,
        theme: null,
        bookerLayouts: bookerLayouts.parse(
          firstUsersMetadata?.defaultBookerLayouts || defaultEventBookerLayouts
        ),
        ...orgDetails2 ? {
          image: getPlaceholderAvatar(orgDetails2?.logoUrl, orgDetails2?.name),
          name: orgDetails2?.name,
          username: org
        } : {}
      },
      entity: {
        considerUnpublished: !fromRedirectOfNonOrgLink && unPublishedOrgUser !== void 0,
        fromRedirectOfNonOrgLink,
        orgSlug: org,
        name: unPublishedOrgUser?.profile?.organization?.name ?? null,
        teamSlug: null,
        logoUrl: null,
        hideProfileLink: false
      },
      isInstantEvent: false,
      instantMeetingParameters: [],
      showInstantEventConnectNowModal: false,
      autoTranslateDescriptionEnabled: false,
      fieldTranslations: []
    };
  }
  const usersOrTeamQuery = isTeamEvent ? {
    team: {
      ...getSlugOrRequestedSlug(username),
      parent: orgQuery
    }
  } : {
    users: {
      some: {
        ...orgQuery ? {
          profiles: {
            some: {
              organization: orgQuery,
              username
            }
          }
        } : {
          username,
          profiles: { none: {} }
        }
      }
    },
    team: null
  };
  let event = await prisma2.eventType.findFirst({
    where: {
      slug: eventSlug,
      ...usersOrTeamQuery
    },
    select: getPublicEventSelect(fetchAllUsers)
  });
  if (!event && !orgQuery) {
    event = await prisma2.eventType.findFirst({
      where: {
        slug: eventSlug,
        users: {
          some: {
            username,
            isPlatformManaged: false,
            profiles: {
              some: {
                organization: {
                  isPlatform: true
                }
              }
            }
          }
        }
      },
      select: getPublicEventSelect(fetchAllUsers)
    });
  }
  if (!event)
    return null;
  const eventMetaData = eventTypeMetaDataSchemaWithTypedApps.parse(event.metadata || {});
  const teamMetadata = teamMetadataSchema.parse(event.team?.metadata || {});
  const usersAsHosts = event.hosts.map((host) => host.user);
  const enrichedUsers = await new UserRepository(prisma2).enrichUsersWithTheirProfiles(usersAsHosts);
  const hosts = event.hosts.map((host, index) => ({
    ...host,
    user: enrichedUsers[index]
  }));
  const eventWithUserProfiles = {
    ...event,
    owner: event.owner ? await new UserRepository(prisma2).enrichUserWithItsProfile({
      user: event.owner
    }) : null,
    subsetOfHosts: hosts,
    hosts: fetchAllUsers ? hosts : void 0
  };
  let users = await getUsersFromEvent(eventWithUserProfiles, prisma2) || await getOwnerFromUsersArray(prisma2, event.id);
  if (users === null) {
    throw new Error(`EventType ${event.id} has no owner or users.`);
  }
  if (!eventWithUserProfiles.schedule && eventWithUserProfiles.owner?.defaultScheduleId) {
    const eventOwnerDefaultSchedule = await prisma2.schedule.findUnique({
      where: {
        id: eventWithUserProfiles.owner?.defaultScheduleId
      },
      select: {
        id: true,
        timeZone: true
      }
    });
    eventWithUserProfiles.schedule = eventOwnerDefaultSchedule;
  }
  let orgDetails;
  if (org) {
    orgDetails = await prisma2.team.findFirst({
      where: {
        slug: org,
        parentId: null
      },
      select: {
        logoUrl: true,
        name: true
      }
    });
  }
  let showInstantEventConnectNowModal = eventWithUserProfiles.isInstantEvent;
  if (eventWithUserProfiles.isInstantEvent && eventWithUserProfiles.instantMeetingSchedule?.id) {
    const { id, timeZone } = eventWithUserProfiles.instantMeetingSchedule;
    showInstantEventConnectNowModal = await isCurrentlyAvailable({
      prisma: prisma2,
      instantMeetingScheduleId: id,
      availabilityTimezone: timeZone ?? "Europe/London",
      length: eventWithUserProfiles.length
    });
  }
  const isTeamAdminOrOwner = await prisma2.membership.findFirst({
    where: {
      userId: currentUserId ?? -1,
      teamId: event.teamId ?? -1,
      accepted: true,
      role: { in: ["ADMIN", "OWNER"] }
    }
  });
  const isOrgAdminOrOwner = await prisma2.membership.findFirst({
    where: {
      userId: currentUserId ?? -1,
      teamId: event.team?.parentId ?? -1,
      accepted: true,
      role: { in: ["ADMIN", "OWNER"] }
    }
  });
  if (event.team?.isPrivate && !isTeamAdminOrOwner && !isOrgAdminOrOwner) {
    users = [];
  }
  return {
    ...eventWithUserProfiles,
    bookerLayouts: bookerLayouts.parse(eventMetaData?.bookerLayouts || null),
    description: markdownToSafeHTML(eventWithUserProfiles.description),
    metadata: eventMetaData,
    customInputs: customInputSchema.array().parse(event.customInputs || []),
    locations: privacyFilteredLocations(eventWithUserProfiles.locations || []),
    bookingFields: getBookingFieldsWithSystemFields(event),
    recurringEvent: isRecurringEvent(eventWithUserProfiles.recurringEvent) ? parseRecurringEvent(event.recurringEvent) : null,
    // Sets user data on profile object for easier access
    profile: getProfileFromEvent(eventWithUserProfiles),
    subsetOfUsers: users,
    users: fetchAllUsers ? users : void 0,
    entity: {
      fromRedirectOfNonOrgLink,
      considerUnpublished: !fromRedirectOfNonOrgLink && (eventWithUserProfiles.team?.slug === null || eventWithUserProfiles.owner?.profile?.organization?.slug === null || eventWithUserProfiles.team?.parent?.slug === null),
      orgSlug: org,
      teamSlug: (eventWithUserProfiles.team?.slug || teamMetadata?.requestedSlug) ?? null,
      name: (eventWithUserProfiles.owner?.profile?.organization?.name || eventWithUserProfiles.team?.parent?.name || eventWithUserProfiles.team?.name) ?? null,
      hideProfileLink: eventWithUserProfiles.team?.hideTeamProfileLink ?? false,
      ...orgDetails ? {
        logoUrl: getPlaceholderAvatar(orgDetails?.logoUrl, orgDetails?.name),
        name: orgDetails?.name
      } : {}
    },
    isDynamic: false,
    isInstantEvent: eventWithUserProfiles.isInstantEvent,
    showInstantEventConnectNowModal,
    instantMeetingParameters: eventWithUserProfiles.instantMeetingParameters,
    aiPhoneCallConfig: eventWithUserProfiles.aiPhoneCallConfig,
    assignAllTeamMembers: event.assignAllTeamMembers,
    disableCancelling: event.disableCancelling,
    disableRescheduling: event.disableRescheduling,
    allowReschedulingCancelledBookings: event.allowReschedulingCancelledBookings,
    interfaceLanguage: event.interfaceLanguage
  };
};
function getProfileFromEvent(event) {
  const { team, subsetOfHosts: hosts, owner } = event;
  const nonTeamProfile = hosts?.[0]?.user || owner;
  const profile = team || nonTeamProfile;
  if (!profile)
    throw new Error("Event has no owner");
  const styleProfile = team || event.parent?.team || nonTeamProfile;
  const username = "username" in profile ? profile.username : team?.slug;
  const weekStart = hosts?.[0]?.user?.weekStart || owner?.weekStart || "Monday";
  const eventMetaData = eventTypeMetaDataSchemaWithTypedApps.parse(event.metadata || {});
  const userMetaData = userMetadata.parse(profile.metadata || {});
  return {
    username,
    name: profile.name,
    weekStart,
    image: team ? getOrgOrTeamAvatar(team) : getUserAvatarUrl({
      avatarUrl: nonTeamProfile?.avatarUrl
    }),
    brandColor: styleProfile.brandColor,
    darkBrandColor: styleProfile.darkBrandColor,
    theme: styleProfile.theme,
    bookerLayouts: bookerLayouts.parse(
      eventMetaData?.bookerLayouts || (userMetaData && "defaultBookerLayouts" in userMetaData ? userMetaData.defaultBookerLayouts : null)
    )
  };
}
async function getUsersFromEvent(event, prisma2) {
  const { team, hosts, subsetOfHosts, owner, id } = event;
  if (team) {
    const eventHosts = !!hosts?.length ? hosts : subsetOfHosts;
    return eventHosts.length ? eventHosts.filter((host) => host.user.username).map(mapHostsToUsers) : await getOwnerFromUsersArray(prisma2, id) ?? [];
  }
  if (!owner) {
    return null;
  }
  const { username, name, weekStart, profile, avatarUrl } = owner;
  const organizationId = profile?.organization?.id ?? null;
  return [
    {
      username,
      name,
      weekStart,
      organizationId,
      avatarUrl,
      profile,
      bookerUrl: getBookerBaseUrlSync(owner.profile?.organization?.slug ?? null)
    }
  ];
}
async function getOwnerFromUsersArray(prisma2, eventTypeId) {
  const { users } = await prisma2.eventType.findUniqueOrThrow({
    where: { id: eventTypeId },
    select: {
      users: {
        select: {
          avatarUrl: true,
          username: true,
          name: true,
          weekStart: true,
          id: true
        }
      }
    }
  });
  if (!users.length)
    return null;
  const enrichedUsers = await new UserRepository(prisma2).enrichUsersWithTheirProfiles(users);
  const usersWithUserProfile = enrichedUsers.map((user) => ({
    ...user,
    organizationId: user.profile?.organization?.id ?? null,
    organization: user.profile?.organization,
    profile: user.profile
  }));
  return [
    {
      ...usersWithUserProfile[0],
      bookerUrl: getBookerBaseUrlSync(usersWithUserProfile[0].organization?.slug ?? null)
    }
  ];
}
function mapHostsToUsers(host) {
  return {
    username: host.user.username,
    name: host.user.name,
    avatarUrl: host.user.avatarUrl,
    weekStart: host.user.weekStart,
    organizationId: host.user.profile?.organizationId ?? null,
    bookerUrl: getBookerBaseUrlSync(host.user.profile?.organization?.slug ?? null),
    profile: host.user.profile
  };
}
async function getDefaultLocations(user) {
  const defaultConferencingData = userMetadata.parse(user.metadata)?.defaultConferencingApp;
  if (defaultConferencingData && defaultConferencingData.appSlug !== "daily-video") {
    const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
    const foundApp = getApps(credentials, true).filter(
      (app) => app.slug === defaultConferencingData.appSlug
    )[0];
    const locationType = foundApp?.locationOption?.value ?? DailyLocationType;
    return [{ type: locationType, link: defaultConferencingData.appLink }];
  }
  const appKeys = await getAppKeysFromSlug("daily-video");
  if (typeof appKeys.api_key === "string") {
    return [{ type: DailyLocationType }];
  }
  return [];
}
const createHandler = async ({ ctx, input }) => {
  const {
    schedulingType,
    teamId,
    metadata,
    locations: inputLocations,
    scheduleId,
    calVideoSettings,
    ...rest
  } = input;
  const userId = ctx.user.id;
  const isManagedEventType = schedulingType === SchedulingType.MANAGED;
  const isOrgAdmin = !!ctx.user?.organization?.isOrgAdmin;
  const locations = inputLocations && inputLocations.length !== 0 ? inputLocations : await getDefaultLocations(ctx.user);
  const isCalVideoLocationActive = locations.some((location) => location.type === DailyLocationType);
  const data = {
    ...rest,
    owner: teamId ? void 0 : { connect: { id: userId } },
    metadata: metadata ?? void 0,
    // Only connecting the current user for non-managed event types and non team event types
    users: isManagedEventType || schedulingType ? void 0 : { connect: { id: userId } },
    locations,
    schedule: scheduleId ? { connect: { id: scheduleId } } : void 0
  };
  if (isCalVideoLocationActive && calVideoSettings) {
    data.calVideoSettings = {
      create: {
        disableRecordingForGuests: calVideoSettings.disableRecordingForGuests ?? false,
        disableRecordingForOrganizer: calVideoSettings.disableRecordingForOrganizer ?? false,
        enableAutomaticTranscription: calVideoSettings.enableAutomaticTranscription ?? false,
        enableAutomaticRecordingForOrganizer: calVideoSettings.enableAutomaticRecordingForOrganizer ?? false,
        disableTranscriptionForGuests: calVideoSettings.disableTranscriptionForGuests ?? false,
        disableTranscriptionForOrganizer: calVideoSettings.disableTranscriptionForOrganizer ?? false,
        redirectUrlOnExit: calVideoSettings.redirectUrlOnExit ?? null
      }
    };
  }
  if (teamId && schedulingType) {
    const hasMembership = await ctx.prisma.membership.findFirst({
      where: {
        userId,
        teamId,
        accepted: true
      }
    });
    const isSystemAdmin = ctx.user.role === "ADMIN";
    if (!isSystemAdmin && !isOrgAdmin && (!hasMembership?.role || !["ADMIN", "OWNER"].includes(hasMembership.role))) {
      console.warn(`User ${userId} does not have permission to create this new event type`);
      throw new TRPCError({ code: "UNAUTHORIZED" });
    }
    data.team = {
      connect: {
        id: teamId
      }
    };
    data.schedulingType = schedulingType;
  }
  if (ctx.user.organizationId && !ctx.user?.organization?.isOrgAdmin && !teamId) {
    const orgSettings = await ctx.prisma.organizationSettings.findUnique({
      where: {
        organizationId: ctx.user.organizationId
      },
      select: {
        lockEventTypeCreationForUsers: true
      }
    });
    const orgHasLockedEventTypes = !!orgSettings?.lockEventTypeCreationForUsers;
    if (orgHasLockedEventTypes) {
      console.warn(
        `User ${userId} does not have permission to create this new event type - Locked status: ${orgHasLockedEventTypes}`
      );
      throw new TRPCError({ code: "UNAUTHORIZED" });
    }
  }
  const profile = ctx.user.profile;
  try {
    const eventTypeRepo = new EventTypeRepository(ctx.prisma);
    const eventType = await eventTypeRepo.create({
      ...data,
      profileId: profile.id
    });
    return { eventType };
  } catch (e) {
    console.warn(e);
    if (e instanceof library.PrismaClientKnownRequestError) {
      if (e.code === "P2002" && Array.isArray(e.meta?.target) && e.meta?.target.includes("slug")) {
        throw new TRPCError({ code: "BAD_REQUEST", message: "URL Slug already exists for given user." });
      }
    }
    throw new TRPCError({ code: "BAD_REQUEST" });
  }
};
const sendAllSlugReplacementEmails = async (persons, slug, teamName) => {
  const t = await getTranslation("en", "common");
  persons.map(
    async (person) => await sendSlugReplacementEmail({ email: person.email, name: person.name, teamName, slug, t })
  );
};
const checkExistentEventTypes = async ({
  updatedEventType,
  children,
  prisma: prisma2,
  userIds,
  teamName
}) => {
  const replaceEventType = children?.filter(
    (ch) => ch.owner.eventTypeSlugs.includes(updatedEventType.slug) && userIds.includes(ch.owner.id)
  );
  if (replaceEventType?.length) {
    const deletedReplacedEventTypes = await prisma2.eventType.deleteMany({
      where: {
        slug: updatedEventType.slug,
        userId: {
          in: replaceEventType.map((evTy) => evTy.owner.id)
        }
      }
    });
    await sendAllSlugReplacementEmails(
      replaceEventType.map((evTy) => evTy.owner),
      updatedEventType.slug,
      teamName
    );
    return deletedReplacedEventTypes;
  }
};
async function handleChildrenEventTypes({
  eventTypeId: parentId,
  oldEventType,
  updatedEventType,
  children,
  prisma: prisma2,
  profileId,
  updatedValues
}) {
  if (updatedEventType?.schedulingType !== SchedulingType.MANAGED)
    return {
      message: "No managed event type"
    };
  const eventType = await prisma2.eventType.findFirst({
    where: { id: parentId },
    select: allManagedEventTypeProps
  });
  if (!oldEventType || !eventType)
    return {
      message: "Missing event type"
    };
  const _ManagedEventTypeModel = _EventTypeModel.extend({
    bookingFields: _EventTypeModel.shape.bookingFields.nullish()
  });
  const allManagedEventTypePropsZod = _ManagedEventTypeModel.pick(allManagedEventTypeProps);
  const managedEventTypeValues = allManagedEventTypePropsZod.omit(unlockedManagedEventTypeProps).parse(eventType);
  if (!managedEventTypeValues.metadata?.managedEventConfig)
    return {
      message: "No managed event metadata"
    };
  const unlockedEventTypeValues = allManagedEventTypePropsZod.pick(unlockedManagedEventTypeProps).parse(eventType);
  const previousUserIds = oldEventType.children?.flatMap((ch) => ch.userId ?? []);
  const currentUserIds = children?.map((ch) => ch.owner.id);
  const deletedUserIds = previousUserIds?.filter((id) => !currentUserIds?.includes(id));
  const newUserIds = currentUserIds?.filter((id) => !previousUserIds?.includes(id));
  const oldUserIds = currentUserIds?.filter((id) => previousUserIds?.includes(id));
  const currentWorkflowIds = eventType.workflows?.map((wf) => wf.workflowId);
  let deletedExistentEventTypes = void 0;
  if (newUserIds?.length) {
    deletedExistentEventTypes = await checkExistentEventTypes({
      updatedEventType,
      children,
      prisma: prisma2,
      userIds: newUserIds,
      teamName: oldEventType.team?.name ?? null
    });
    await prisma2.$transaction(
      newUserIds.map((userId) => {
        return prisma2.eventType.create({
          data: {
            instantMeetingScheduleId: eventType.instantMeetingScheduleId ?? void 0,
            profileId: profileId ?? null,
            ...managedEventTypeValues,
            ...unlockedEventTypeValues,
            bookingLimits: managedEventTypeValues.bookingLimits ?? void 0,
            recurringEvent: managedEventTypeValues.recurringEvent ?? void 0,
            metadata: managedEventTypeValues.metadata ?? void 0,
            bookingFields: managedEventTypeValues.bookingFields ?? void 0,
            durationLimits: managedEventTypeValues.durationLimits ?? void 0,
            eventTypeColor: managedEventTypeValues.eventTypeColor ?? void 0,
            onlyShowFirstAvailableSlot: managedEventTypeValues.onlyShowFirstAvailableSlot ?? false,
            userId,
            users: {
              connect: [{ id: userId }]
            },
            parentId,
            hidden: children?.find((ch) => ch.owner.id === userId)?.hidden ?? false,
            workflows: currentWorkflowIds && {
              create: currentWorkflowIds.map((wfId) => ({ workflowId: wfId }))
            },
            /**
             * RR Segment isn't applicable for managed event types.
             */
            rrSegmentQueryValue: void 0,
            assignRRMembersUsingSegment: false,
            useEventLevelSelectedCalendars: false,
            restrictionScheduleId: null,
            useBookerTimezone: false,
            allowReschedulingCancelledBookings: managedEventTypeValues.allowReschedulingCancelledBookings ?? false
          }
        });
      })
    );
  }
  if (oldUserIds?.length) {
    deletedExistentEventTypes = await checkExistentEventTypes({
      updatedEventType,
      children,
      prisma: prisma2,
      userIds: oldUserIds,
      teamName: oldEventType.team?.name || null
    });
    const { unlockedFields } = managedEventTypeValues.metadata?.managedEventConfig;
    const unlockedFieldProps = !unlockedFields ? {} : Object.keys(unlockedFields).reduce((acc, key) => {
      const filteredKey = key === "afterBufferTime" ? "afterEventBuffer" : key === "beforeBufferTime" ? "beforeEventBuffer" : key;
      acc[filteredKey] = true;
      return acc;
    }, {});
    const updatePayload = allManagedEventTypePropsZod.omit(unlockedFieldProps).parse(eventType);
    const updatePayloadFiltered = Object.entries(updatePayload).filter(([key, _]) => key !== "children").reduce((newObj, [key, value]) => ({ ...newObj, [key]: value }), {});
    const oldEventTypes = await Promise.all(
      oldUserIds.map(async (userId) => {
        const existingEventType = await prisma2.eventType.findUnique({
          where: {
            userId_parentId: {
              userId,
              parentId
            }
          },
          select: {
            metadata: true
          }
        });
        const metadata = eventTypeMetaDataSchemaWithTypedApps.parse(existingEventType?.metadata || {});
        return await prisma2.eventType.update({
          where: {
            userId_parentId: {
              userId,
              parentId
            }
          },
          data: {
            ...updatePayloadFiltered,
            hidden: children?.find((ch) => ch.owner.id === userId)?.hidden ?? false,
            ..."schedule" in unlockedFieldProps ? {} : { scheduleId: eventType.scheduleId || null },
            restrictionScheduleId: null,
            useBookerTimezone: false,
            hashedLink: "multiplePrivateLinks" in unlockedFieldProps ? void 0 : {
              deleteMany: {}
            },
            allowReschedulingCancelledBookings: managedEventTypeValues.allowReschedulingCancelledBookings ?? false,
            metadata: {
              ...eventType.metadata,
              ...metadata?.multipleDuration && "length" in unlockedFieldProps ? { multipleDuration: metadata.multipleDuration } : {},
              ...metadata?.apps && "apps" in unlockedFieldProps ? { apps: metadata.apps } : {}
            }
          }
        });
      })
    );
    if (currentWorkflowIds?.length) {
      await prisma2.$transaction(
        currentWorkflowIds.flatMap((wfId) => {
          return oldEventTypes.map((oEvTy) => {
            return prisma2.workflowsOnEventTypes.upsert({
              create: {
                eventTypeId: oEvTy.id,
                workflowId: wfId
              },
              update: {},
              where: {
                workflowId_eventTypeId: {
                  eventTypeId: oEvTy.id,
                  workflowId: wfId
                }
              }
            });
          });
        })
      );
    }
  }
  if (deletedUserIds?.length) {
    await prisma2.eventType.deleteMany({
      where: {
        userId: {
          in: deletedUserIds
        },
        parentId
      }
    });
  }
  return { newUserIds, oldUserIds, deletedUserIds, deletedExistentEventTypes };
}
const validateIntervalLimitOrder = (input) => {
  const sorted = Object.entries(input).sort(([, value], [, valuetwo]) => {
    return value - valuetwo;
  }).map(([key]) => key);
  const validationOrderWithoutMissing = ascendingLimitKeys.filter((key) => sorted.includes(key));
  return sorted.every((key, index) => validationOrderWithoutMissing[index] === key);
};
class CalVideoSettingsRepository {
  static async deleteCalVideoSettings(eventTypeId) {
    return await prisma.calVideoSettings.delete({
      where: { eventTypeId }
    });
  }
  static async createCalVideoSettings({
    eventTypeId,
    calVideoSettings
  }) {
    return await prisma.calVideoSettings.create({
      data: {
        disableRecordingForGuests: calVideoSettings.disableRecordingForGuests ?? false,
        disableRecordingForOrganizer: calVideoSettings.disableRecordingForOrganizer ?? false,
        enableAutomaticTranscription: calVideoSettings.enableAutomaticTranscription ?? false,
        enableAutomaticRecordingForOrganizer: calVideoSettings.enableAutomaticRecordingForOrganizer ?? false,
        disableTranscriptionForGuests: calVideoSettings.disableTranscriptionForGuests ?? false,
        disableTranscriptionForOrganizer: calVideoSettings.disableTranscriptionForOrganizer ?? false,
        redirectUrlOnExit: calVideoSettings.redirectUrlOnExit ?? null,
        eventTypeId
      }
    });
  }
  static async createOrUpdateCalVideoSettings({
    eventTypeId,
    calVideoSettings
  }) {
    return await prisma.calVideoSettings.upsert({
      where: { eventTypeId },
      update: {
        disableRecordingForGuests: calVideoSettings.disableRecordingForGuests ?? false,
        disableRecordingForOrganizer: calVideoSettings.disableRecordingForOrganizer ?? false,
        enableAutomaticTranscription: calVideoSettings.enableAutomaticTranscription ?? false,
        enableAutomaticRecordingForOrganizer: calVideoSettings.enableAutomaticRecordingForOrganizer ?? false,
        disableTranscriptionForGuests: calVideoSettings.disableTranscriptionForGuests ?? false,
        disableTranscriptionForOrganizer: calVideoSettings.disableTranscriptionForOrganizer ?? false,
        redirectUrlOnExit: calVideoSettings.redirectUrlOnExit ?? null,
        updatedAt: /* @__PURE__ */ new Date()
      },
      create: {
        disableRecordingForGuests: calVideoSettings.disableRecordingForGuests ?? false,
        disableRecordingForOrganizer: calVideoSettings.disableRecordingForOrganizer ?? false,
        enableAutomaticTranscription: calVideoSettings.enableAutomaticTranscription ?? false,
        enableAutomaticRecordingForOrganizer: calVideoSettings.enableAutomaticRecordingForOrganizer ?? false,
        disableTranscriptionForGuests: calVideoSettings.disableTranscriptionForGuests ?? false,
        disableTranscriptionForOrganizer: calVideoSettings.disableTranscriptionForOrganizer ?? false,
        redirectUrlOnExit: calVideoSettings.redirectUrlOnExit ?? null,
        eventTypeId
      }
    });
  }
}
const validateBookerLayouts = (settings) => {
  if (settings === null)
    return;
  const atLeastOneLayoutIsEnabled = settings?.enabledLayouts.length > 0;
  if (!atLeastOneLayoutIsEnabled)
    return "bookerlayout_error_min_one_enabled";
  const defaultLayoutIsInEnabledLayouts = settings?.enabledLayouts.find(
    (layout) => layout === settings.defaultLayout
  );
  if (!defaultLayoutIsInEnabledLayouts)
    return "bookerlayout_error_default_not_enabled";
  const enabledLayoutsDoesntContainUnknownLayout = settings?.enabledLayouts.every(
    (layout) => bookerLayoutOptions.includes(layout)
  );
  const defaultLayoutIsKnown = bookerLayoutOptions.includes(settings.defaultLayout);
  if (!enabledLayoutsDoesntContainUnknownLayout || !defaultLayoutIsKnown) {
    return "bookerlayout_error_unknown_layout";
  }
};
const getFirstConnectedCalendar = ({
  connectedCalendars,
  matcher
}) => {
  const calendars = connectedCalendars.flatMap((c) => c.calendars ?? []);
  const matchingCalendars = calendars.filter(matcher);
  const delegationCredentialCalendar = matchingCalendars.find((cal) => !!cal.delegationCredentialId);
  if (delegationCredentialCalendar) {
    return delegationCredentialCalendar;
  } else {
    return matchingCalendars[0];
  }
};
const setDestinationCalendarHandler = async ({ ctx, input }) => {
  const { user } = ctx;
  const { integration, externalId, eventTypeId } = input;
  const credentials = await getUsersCredentialsIncludeServiceAccountKey(user);
  const calendarCredentials = getCalendarCredentials(credentials);
  const { connectedCalendars } = await getConnectedCalendars(
    calendarCredentials,
    user.userLevelSelectedCalendars
  );
  const allCals = connectedCalendars.map((cal) => cal.calendars ?? []).flat();
  const firstConnectedCalendar = getFirstConnectedCalendar({
    connectedCalendars,
    matcher: (cal) => cal.externalId === externalId && cal.integration === integration && cal.readOnly === false
  });
  const { credentialId, delegationCredentialId } = firstConnectedCalendar || {};
  let where;
  if (!credentialId && !delegationCredentialId) {
    throw new TRPCError({ code: "BAD_REQUEST", message: `Could not find calendar ${input.externalId}` });
  }
  const primaryEmail = allCals.find(
    (cal) => cal.primary && (cal.credentialId === credentialId || !!cal.delegationCredentialId && cal.delegationCredentialId === delegationCredentialId)
  )?.email ?? null;
  if (eventTypeId) {
    if (!await prisma.eventType.findFirst({
      where: {
        id: eventTypeId,
        userId: user.id
      }
    })) {
      throw new TRPCError({
        code: "UNAUTHORIZED",
        message: `You don't have access to event type ${eventTypeId}`
      });
    }
    where = { eventTypeId };
  } else
    where = { userId: user.id };
  await DestinationCalendarRepository.upsert({
    where,
    update: {
      integration,
      externalId,
      primaryEmail,
      credentialId,
      delegationCredentialId
    },
    create: {
      ...where,
      integration,
      externalId,
      primaryEmail,
      credentialId,
      delegationCredentialId
    }
  });
};
function errorFormatter({ shape, error }) {
  if (error.cause instanceof z.ZodError) {
    return {
      message: "Invalid input",
      code: 400,
      data: {
        code: "BAD_REQUEST",
        httpStatus: 400,
        path: shape.data.path,
        zodError: error.cause.flatten()
      }
    };
  }
  return shape;
}
const tRPCContext = initTRPC.context().create({
  transformer: superjson,
  errorFormatter
});
tRPCContext.router;
tRPCContext.mergeRouters;
const middleware = tRPCContext.middleware;
const procedure = tRPCContext.procedure;
tRPCContext.createCallerFactory;
const perfMiddleware = middleware(async ({ path, type, next }) => {
  performance.mark("Start");
  const result = await next();
  performance.mark("End");
  performance.measure(`[${result.ok ? "OK" : "ERROR"}][$1] ${type} '${path}'`, "Start", "End");
  return result;
});
const perfMiddleware$1 = perfMiddleware;
async function getUserFromSession(ctx, session) {
  if (!session) {
    return null;
  }
  if (!session.user?.id) {
    return null;
  }
  const userRepo = new UserRepository(prisma);
  const userFromDb = await userRepo.findUnlockedUserForSession({ userId: session.user.id });
  if (!userFromDb) {
    return null;
  }
  const upId = session.upId;
  const user = await userRepo.enrichUserWithTheProfile({
    user: userFromDb,
    upId
  });
  logger.debug(
    `getUserFromSession: enriched user with profile - ${ctx.req?.url}`,
    safeStringify({ user, userFromDb, upId })
  );
  const { email, username, id } = user;
  if (!email || !id) {
    return null;
  }
  const userMetaData = userMetadata.parse(user.metadata || {});
  const orgMetadata = teamMetadataSchema.parse(user.profile?.organization?.metadata || {});
  const locale = user?.locale ?? ctx.locale;
  const { members = [], ..._organization } = user.profile?.organization || {};
  const isOrgAdmin = members.some((member) => ["OWNER", "ADMIN"].includes(member.role));
  if (isOrgAdmin) {
    logger.debug("User is an org admin", safeStringify({ userId: user.id }));
  } else {
    logger.debug("User is not an org admin", safeStringify({ userId: user.id }));
  }
  const organization = {
    ..._organization,
    id: user.profile?.organization?.id ?? null,
    isOrgAdmin,
    metadata: orgMetadata,
    requestedSlug: orgMetadata?.requestedSlug ?? null
  };
  return {
    ...user,
    avatar: `${WEBAPP_URL}/${user.username}/avatar.png?${organization.id}` && `orgId=${organization.id}`,
    // TODO: OrgNewSchema - later -  We could consolidate the props in user.profile?.organization as organization is a profile thing now.
    organization,
    organizationId: organization.id,
    id,
    email,
    username,
    locale,
    defaultBookerLayouts: userMetaData?.defaultBookerLayouts || null
  };
}
const getSession = async (ctx) => {
  const { req } = ctx;
  const { getServerSession } = await import("./getServerSession-ZkQhIqnA.js");
  return req ? await getServerSession({ req }) : null;
};
const getUserSession = async (ctx) => {
  const session = ctx.session || await getSession(ctx);
  const user = session ? await getUserFromSession(ctx, session) : null;
  let foundProfile = null;
  if (session?.profileId && user?.id) {
    foundProfile = await ProfileRepository.findByUserIdAndProfileId({
      userId: user.id,
      profileId: session.profileId
    });
    if (!foundProfile) {
      logger.error(
        "Profile not found or not authorized",
        safeStringify({ profileId: session.profileId, userId: user?.id })
      );
      throw new TRPCError({ code: "UNAUTHORIZED", message: "Profile not found or not authorized" });
    }
  }
  let sessionWithUpId = null;
  if (session) {
    let upId = session.upId;
    if (!upId) {
      upId = foundProfile?.upId ?? `usr-${user?.id}`;
    }
    if (!upId) {
      throw new TRPCError({ code: "INTERNAL_SERVER_ERROR", message: "No upId found for session" });
    }
    sessionWithUpId = {
      ...session,
      upId
    };
  }
  return { user, session: sessionWithUpId };
};
middleware(async ({ ctx, next }) => {
  const middlewareStart = performance.now();
  const { user, session } = await getUserSession(ctx);
  const middlewareEnd = performance.now();
  logger.debug("Perf:t.sessionMiddleware", middlewareEnd - middlewareStart);
  return next({
    ctx: { user, session }
  });
});
const isAuthed = middleware(async ({ ctx, next }) => {
  const middlewareStart = performance.now();
  const { user, session } = await getUserSession(ctx);
  const middlewareEnd = performance.now();
  logger.debug("Perf:t.isAuthed", middlewareEnd - middlewareStart);
  if (!user || !session) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  setUser({ id: user.id });
  return next({
    ctx: { user, session }
  });
});
const isAdminMiddleware = isAuthed.unstable_pipe(({ ctx, next }) => {
  const { user } = ctx;
  if (user?.role !== "ADMIN") {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({ ctx: { user } });
});
const isOrgAdminMiddleware = isAuthed.unstable_pipe(({ ctx, next }) => {
  const { user } = ctx;
  if (!user?.organization?.isOrgAdmin) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  return next({ ctx: { user } });
});
const publicProcedure = tRPCContext.procedure.use(perfMiddleware$1);
const publicProcedure$1 = publicProcedure;
const authedProcedure = procedure.use(perfMiddleware$1).use(isAuthed);
publicProcedure$1.use(isAdminMiddleware);
publicProcedure$1.use(isOrgAdminMiddleware);
const authedProcedure$1 = authedProcedure;
authedProcedure$1.input(
  z.object({
    id: z.number().optional(),
    eventTypeId: z.number().optional(),
    users: z.array(z.number()).optional().default([])
  }).refine((data) => data.id !== void 0 || data.eventTypeId !== void 0, {
    message: "At least one of 'id' or 'eventTypeId' must be present",
    path: ["id", "eventTypeId"]
  })
).use(async ({ ctx, input, next }) => {
  const id = input.eventTypeId ?? input.id;
  const event = await ctx.prisma.eventType.findUnique({
    where: { id },
    include: {
      users: {
        select: {
          id: true
        }
      },
      team: {
        select: {
          members: {
            select: {
              userId: true,
              role: true
            }
          }
        }
      }
    }
  });
  if (!event) {
    throw new TRPCError({ code: "NOT_FOUND" });
  }
  const isAuthorized = function() {
    if (event.team) {
      const isOrgAdmin = !!ctx.user?.organization?.isOrgAdmin;
      return event.team.members.filter((member) => checkAdminOrOwner(member.role)).map((member) => member.userId).includes(ctx.user.id) || isOrgAdmin;
    }
    return event.userId === ctx.user.id || event.users.find((user) => user.id === ctx.user.id);
  }();
  if (!isAuthorized) {
    throw new TRPCError({ code: "FORBIDDEN" });
  }
  const isAllowed = function() {
    if (event.team) {
      const allTeamMembers = event.team.members.map((member) => member.userId);
      return input.users.every((userId) => allTeamMembers.includes(userId));
    }
    return input.users.every((userId) => userId === ctx.user.id);
  }();
  if (!isAllowed) {
    console.warn(
      `User ${ctx.user.id} attempted to an create an event for users ${input.users.join(", ")}.`
    );
    throw new TRPCError({ code: "FORBIDDEN" });
  }
  return next();
});
function isPeriodType(keyInput) {
  return Object.keys(PeriodType).includes(keyInput);
}
function handlePeriodType(periodType) {
  if (typeof periodType !== "string")
    return void 0;
  const passedPeriodType = periodType.toUpperCase();
  if (!isPeriodType(passedPeriodType))
    return void 0;
  return PeriodType[passedPeriodType];
}
function handleCustomInputs(customInputs, eventTypeId) {
  const cInputsIdsToDeleteOrUpdated = customInputs.filter((input) => !input.hasToBeCreated);
  const cInputsIdsToDelete = cInputsIdsToDeleteOrUpdated.map((e) => e.id);
  const cInputsToCreate = customInputs.filter((input) => input.hasToBeCreated).map((input) => ({
    type: input.type,
    label: input.label,
    required: input.required,
    placeholder: input.placeholder,
    options: input.options || void 0
  }));
  const cInputsToUpdate = cInputsIdsToDeleteOrUpdated.map((input) => ({
    data: {
      type: input.type,
      label: input.label,
      required: input.required,
      placeholder: input.placeholder,
      options: input.options || void 0
    },
    where: {
      id: input.id
    }
  }));
  return {
    deleteMany: {
      eventTypeId,
      NOT: {
        id: { in: cInputsIdsToDelete }
      }
    },
    createMany: {
      data: cInputsToCreate
    },
    update: cInputsToUpdate
  };
}
function ensureUniqueBookingFields(fields) {
  if (!fields) {
    return;
  }
  fields.reduce((discoveredFields, field) => {
    if (discoveredFields[field.name]) {
      throw new TRPCError({
        code: "BAD_REQUEST",
        message: `Duplicate booking field name: ${field.name}`
      });
    }
    discoveredFields[field.name] = true;
    return discoveredFields;
  }, {});
}
function ensureEmailOrPhoneNumberIsPresent(fields) {
  if (!fields || fields.length === 0) {
    return;
  }
  const attendeePhoneNumberField = fields.find((field) => field.name === "attendeePhoneNumber");
  const emailField = fields.find((field) => field.name === "email");
  if (emailField?.hidden && attendeePhoneNumberField?.hidden) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: `Both Email and Attendee Phone Number cannot be hidden`
    });
  }
  if (!emailField?.required && !attendeePhoneNumberField?.required) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: `At least Email or Attendee Phone Number need to be required field.`
    });
  }
}
const updateHandler = async ({ ctx, input }) => {
  const {
    schedule,
    instantMeetingSchedule,
    periodType,
    locations,
    bookingLimits,
    durationLimits,
    maxActiveBookingsPerBooker,
    destinationCalendar,
    customInputs,
    recurringEvent,
    eventTypeColor,
    users,
    children,
    assignAllTeamMembers,
    hosts,
    id,
    multiplePrivateLinks,
    // Extract this from the input so it doesn't get saved in the db
    // eslint-disable-next-line
    userId,
    bookingFields,
    offsetStart,
    secondaryEmailId,
    aiPhoneCallConfig,
    isRRWeightsEnabled,
    autoTranslateDescriptionEnabled,
    description: newDescription,
    title: newTitle,
    seatsPerTimeSlot,
    restrictionScheduleId,
    calVideoSettings,
    hostGroups,
    ...rest
  } = input;
  const eventType = await ctx.prisma.eventType.findUniqueOrThrow({
    where: { id },
    select: {
      title: true,
      locations: true,
      description: true,
      seatsPerTimeSlot: true,
      recurringEvent: true,
      maxActiveBookingsPerBooker: true,
      fieldTranslations: {
        select: {
          field: true
        }
      },
      isRRWeightsEnabled: true,
      hosts: {
        select: {
          userId: true,
          priority: true,
          weight: true,
          isFixed: true
        }
      },
      aiPhoneCallConfig: {
        select: {
          generalPrompt: true,
          beginMessage: true,
          enabled: true,
          llmId: true
        }
      },
      calVideoSettings: {
        select: {
          disableRecordingForOrganizer: true,
          disableRecordingForGuests: true,
          enableAutomaticTranscription: true,
          enableAutomaticRecordingForOrganizer: true,
          disableTranscriptionForGuests: true,
          disableTranscriptionForOrganizer: true,
          redirectUrlOnExit: true
        }
      },
      children: {
        select: {
          userId: true
        }
      },
      workflows: {
        select: {
          workflowId: true
        }
      },
      hostGroups: {
        select: {
          id: true,
          name: true
        }
      },
      team: {
        select: {
          id: true,
          name: true,
          slug: true,
          parentId: true,
          rrTimestampBasis: true,
          parent: {
            select: {
              slug: true
            }
          },
          members: {
            select: {
              role: true,
              accepted: true,
              user: {
                select: {
                  name: true,
                  id: true,
                  email: true,
                  eventTypes: {
                    select: {
                      slug: true
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  });
  if (input.teamId && eventType.team?.id && input.teamId !== eventType.team.id) {
    throw new TRPCError({ code: "UNAUTHORIZED" });
  }
  const finalSeatsPerTimeSlot = seatsPerTimeSlot ?? eventType.seatsPerTimeSlot;
  const finalRecurringEvent = recurringEvent ?? eventType.recurringEvent;
  if (finalSeatsPerTimeSlot && finalRecurringEvent) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: "Recurring Events and Offer Seats cannot be active at the same time."
    });
  }
  const teamId = input.teamId || eventType.team?.id;
  const guestsField = bookingFields?.find((field) => field.name === "guests");
  ensureUniqueBookingFields(bookingFields);
  ensureEmailOrPhoneNumberIsPresent(bookingFields);
  if (autoTranslateDescriptionEnabled && !ctx.user.organizationId) {
    logger.error(
      "Auto-translating description requires an organization. This should not happen - UI controls should prevent this state."
    );
  }
  const isLoadBalancingDisabled = !!(eventType.team?.rrTimestampBasis && eventType.team?.rrTimestampBasis !== RRTimestampBasis.CREATED_AT || hostGroups && hostGroups.length > 1 || !hostGroups && eventType.hostGroups && eventType.hostGroups.length > 1);
  const data = {
    ...rest,
    // autoTranslate feature is allowed for org users only
    autoTranslateDescriptionEnabled: !!(ctx.user.organizationId && autoTranslateDescriptionEnabled),
    description: newDescription,
    title: newTitle,
    bookingFields,
    maxActiveBookingsPerBooker,
    isRRWeightsEnabled,
    rrSegmentQueryValue: rest.rrSegmentQueryValue === null ? Prisma.DbNull : rest.rrSegmentQueryValue,
    metadata: rest.metadata === null ? Prisma.DbNull : rest.metadata,
    eventTypeColor: eventTypeColor === null ? Prisma.DbNull : eventTypeColor,
    disableGuests: guestsField?.hidden ?? false,
    seatsPerTimeSlot,
    maxLeadThreshold: isLoadBalancingDisabled ? null : rest.maxLeadThreshold
  };
  data.locations = locations ?? void 0;
  if (periodType) {
    data.periodType = handlePeriodType(periodType);
  }
  if (recurringEvent) {
    data.recurringEvent = {
      dstart: recurringEvent.dtstart,
      interval: recurringEvent.interval,
      count: recurringEvent.count,
      freq: recurringEvent.freq,
      until: recurringEvent.until,
      tzid: recurringEvent.tzid
    };
  } else if (recurringEvent === null) {
    data.recurringEvent = Prisma.DbNull;
  }
  if (destinationCalendar) {
    await setDestinationCalendarHandler({
      ctx,
      input: {
        ...destinationCalendar,
        eventTypeId: id
      }
    });
  }
  if (customInputs) {
    data.customInputs = handleCustomInputs(customInputs, id);
  }
  if (bookingLimits) {
    const isValid = validateIntervalLimitOrder(bookingLimits);
    if (!isValid)
      throw new TRPCError({ code: "BAD_REQUEST", message: "Booking limits must be in ascending order." });
    data.bookingLimits = bookingLimits;
  }
  if (maxActiveBookingsPerBooker) {
    if (maxActiveBookingsPerBooker && maxActiveBookingsPerBooker < 1) {
      throw new TRPCError({ code: "BAD_REQUEST", message: "Booker booking limit must be greater than 0." });
    }
    if (maxActiveBookingsPerBooker && (recurringEvent || eventType.recurringEvent)) {
      throw new TRPCError({
        code: "BAD_REQUEST",
        message: "Recurring Events and booker active bookings limit cannot be active at the same time."
      });
    }
    if (eventType.maxActiveBookingsPerBooker && recurringEvent) {
      throw new TRPCError({
        code: "BAD_REQUEST",
        message: "Recurring Events and booker active bookings limit cannot be active at the same time."
      });
    }
    data.maxActiveBookingsPerBooker = maxActiveBookingsPerBooker;
  }
  if (durationLimits) {
    const isValid = validateIntervalLimitOrder(durationLimits);
    if (!isValid)
      throw new TRPCError({ code: "BAD_REQUEST", message: "Duration limits must be in ascending order." });
    data.durationLimits = durationLimits;
  }
  if (offsetStart !== void 0) {
    if (offsetStart < 0) {
      throw new TRPCError({ code: "BAD_REQUEST", message: "Offset start time must be zero or greater." });
    }
    data.offsetStart = offsetStart;
  }
  const bookerLayoutsError = validateBookerLayouts(input.metadata?.bookerLayouts || null);
  if (bookerLayoutsError) {
    const t = await getTranslation("en", "common");
    throw new TRPCError({ code: "BAD_REQUEST", message: t(bookerLayoutsError) });
  }
  if (schedule) {
    const userScheduleQuery = await ctx.prisma.schedule.findFirst({
      where: {
        userId: ctx.user.id,
        id: schedule
      }
    });
    if (userScheduleQuery) {
      data.schedule = {
        connect: {
          id: schedule
        }
      };
    }
  } else if (null === schedule || schedule === 0) {
    data.schedule = {
      disconnect: true
    };
  }
  if (instantMeetingSchedule) {
    data.instantMeetingSchedule = {
      connect: {
        id: instantMeetingSchedule
      }
    };
  } else if (schedule === null) {
    data.instantMeetingSchedule = {
      disconnect: true
    };
  }
  const membershipRepo = new MembershipRepository(ctx.prisma);
  if (restrictionScheduleId) {
    const scheduleRepo = new ScheduleRepository(ctx.prisma);
    const restrictionSchedule = await scheduleRepo.findScheduleByIdForOwnershipCheck({
      scheduleId: restrictionScheduleId
    });
    if (restrictionSchedule?.userId !== ctx.user.id) {
      if (!teamId || !restrictionSchedule) {
        throw new TRPCError({
          code: "UNAUTHORIZED",
          message: "The restriction schedule is not owned by you or your team"
        });
      }
      const hasMembership = await membershipRepo.hasMembership({
        teamId,
        userId: restrictionSchedule.userId
      });
      if (!hasMembership) {
        throw new TRPCError({
          code: "UNAUTHORIZED",
          message: "The restriction schedule is not owned by you or your team"
        });
      }
    }
    data.restrictionSchedule = {
      connect: {
        id: restrictionScheduleId
      }
    };
  } else if (restrictionScheduleId === null || restrictionScheduleId === 0) {
    data.restrictionSchedule = {
      disconnect: true
    };
  }
  if (users?.length) {
    data.users = {
      set: [],
      connect: users.map((userId2) => ({ id: userId2 }))
    };
  }
  if (hostGroups !== void 0) {
    const existingHostGroups = await ctx.prisma.hostGroup.findMany({
      where: {
        eventTypeId: id
      },
      select: {
        id: true,
        name: true
      }
    });
    await Promise.all(
      hostGroups.map(async (group) => {
        await ctx.prisma.hostGroup.upsert({
          where: { id: group.id },
          update: { name: group.name },
          create: {
            id: group.id,
            name: group.name,
            eventTypeId: id
          }
        });
      })
    );
    const newGroupsMap = new Map(hostGroups.map((group) => [group.id, group]));
    const groupsToDelete = existingHostGroups.filter((existingGroup) => !newGroupsMap.has(existingGroup.id));
    if (groupsToDelete.length > 0) {
      await ctx.prisma.hostGroup.deleteMany({
        where: {
          id: {
            in: groupsToDelete.map((group) => group.id)
          }
        }
      });
    }
  }
  if (teamId && hosts) {
    const teamMemberIds = await membershipRepo.listAcceptedTeamMemberIds({ teamId });
    if (!hosts.every((host) => teamMemberIds.includes(host.userId)) && !eventType.team?.parentId) {
      throw new TRPCError({
        code: "FORBIDDEN"
      });
    }
    const oldHostsSet = new Set(eventType.hosts.map((oldHost) => oldHost.userId));
    const newHostsSet = new Set(hosts.map((oldHost) => oldHost.userId));
    const existingHosts = hosts.filter((newHost) => oldHostsSet.has(newHost.userId));
    const newHosts = hosts.filter((newHost) => !oldHostsSet.has(newHost.userId));
    const removedHosts = eventType.hosts.filter((oldHost) => !newHostsSet.has(oldHost.userId));
    data.hosts = {
      deleteMany: {
        OR: removedHosts.map((host) => ({
          userId: host.userId,
          eventTypeId: id
        }))
      },
      create: newHosts.map((host) => {
        return {
          ...host,
          isFixed: data.schedulingType === SchedulingType.COLLECTIVE || host.isFixed,
          priority: host.priority ?? 2,
          weight: host.weight ?? 100,
          groupId: host.groupId
        };
      }),
      update: existingHosts.map((host) => ({
        where: {
          userId_eventTypeId: {
            userId: host.userId,
            eventTypeId: id
          }
        },
        data: {
          isFixed: data.schedulingType === SchedulingType.COLLECTIVE || host.isFixed,
          priority: host.priority ?? 2,
          weight: host.weight ?? 100,
          scheduleId: host.scheduleId ?? null,
          groupId: host.groupId
        }
      }))
    };
  }
  if (input.metadata?.disableStandardEmails?.all) {
    if (!eventType?.team?.parentId) {
      input.metadata.disableStandardEmails.all.host = false;
      input.metadata.disableStandardEmails.all.attendee = false;
    }
  }
  if (input.metadata?.disableStandardEmails?.confirmation) {
    const workflows = await ctx.prisma.workflow.findMany({
      where: {
        activeOn: {
          some: {
            eventTypeId: input.id
          }
        },
        trigger: indexBrowser.WorkflowTriggerEvents.NEW_EVENT
      },
      include: {
        steps: true
      }
    });
    if (input.metadata?.disableStandardEmails.confirmation?.host) {
      if (!allowDisablingHostConfirmationEmails(workflows)) {
        input.metadata.disableStandardEmails.confirmation.host = false;
      }
    }
    if (input.metadata?.disableStandardEmails.confirmation?.attendee) {
      if (!allowDisablingAttendeeConfirmationEmails(workflows)) {
        input.metadata.disableStandardEmails.confirmation.attendee = false;
      }
    }
  }
  const apps = eventTypeAppMetadataOptionalSchema.parse(input.metadata?.apps);
  for (const appKey in apps) {
    const app = apps[appKey];
    if (app.enabled && app.price && app.currency) {
      data.price = app.price;
      data.currency = app.currency;
      break;
    }
  }
  console.log("multiplePrivateLinks", multiplePrivateLinks);
  const privateLinksRepo = HashedLinkRepository.create();
  const connectedLinks = await privateLinksRepo.findLinksByEventTypeId(input.id);
  console.log("connectedLinks", connectedLinks);
  const connectedMultiplePrivateLinks = connectedLinks.map((link) => link.link);
  const privateLinksService = new HashedLinkService();
  await privateLinksService.handleMultiplePrivateLinks({
    eventTypeId: input.id,
    multiplePrivateLinks,
    connectedMultiplePrivateLinks
  });
  if (assignAllTeamMembers !== void 0) {
    data.assignAllTeamMembers = assignAllTeamMembers;
  }
  if (secondaryEmailId) {
    const secondaryEmail = await ctx.prisma.secondaryEmail.findUnique({
      where: {
        id: secondaryEmailId,
        userId: ctx.user.id
      }
    });
    if (secondaryEmail && secondaryEmail.emailVerified) {
      data.secondaryEmail = {
        connect: {
          id: secondaryEmailId
        }
      };
    } else if (secondaryEmailId === -1) {
      data.secondaryEmail = {
        disconnect: true
      };
    }
  }
  if (aiPhoneCallConfig) {
    if (aiPhoneCallConfig.enabled) {
      await ctx.prisma.aIPhoneCallConfiguration.upsert({
        where: {
          eventTypeId: id
        },
        update: {
          ...aiPhoneCallConfig,
          guestEmail: !!aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null,
          guestCompany: !!aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null
        },
        create: {
          ...aiPhoneCallConfig,
          guestEmail: !!aiPhoneCallConfig?.guestEmail ? aiPhoneCallConfig.guestEmail : null,
          guestCompany: !!aiPhoneCallConfig?.guestCompany ? aiPhoneCallConfig.guestCompany : null,
          eventTypeId: id
        }
      });
    } else if (!aiPhoneCallConfig.enabled && eventType.aiPhoneCallConfig) {
      await ctx.prisma.aIPhoneCallConfiguration.delete({
        where: {
          eventTypeId: id
        }
      });
    }
  }
  if (calVideoSettings) {
    await CalVideoSettingsRepository.createOrUpdateCalVideoSettings({
      eventTypeId: id,
      calVideoSettings
    });
  }
  const parsedEventTypeLocations = eventTypeLocations.safeParse(eventType.locations ?? []);
  const isCalVideoLocationActive = locations ? locations.some((location) => location.type === DailyLocationType) : parsedEventTypeLocations.success && parsedEventTypeLocations.data?.some((location) => location.type === DailyLocationType);
  if (eventType.calVideoSettings && !isCalVideoLocationActive) {
    await CalVideoSettingsRepository.deleteCalVideoSettings(id);
  }
  const hasNoDescriptionTranslations = eventType.fieldTranslations.filter((trans) => trans.field === EventTypeAutoTranslatedField.DESCRIPTION).length === 0;
  const description = newDescription ?? (hasNoDescriptionTranslations ? eventType.description : void 0);
  const hasNoTitleTranslations = eventType.fieldTranslations.filter((trans) => trans.field === EventTypeAutoTranslatedField.TITLE).length === 0;
  const title = newTitle ?? (hasNoTitleTranslations ? eventType.title : void 0);
  if (ctx.user.organizationId && autoTranslateDescriptionEnabled && (title || description)) {
    await tasker.create("translateEventTypeData", {
      eventTypeId: id,
      description,
      title,
      userLocale: ctx.user.locale,
      userId: ctx.user.id
    });
  }
  const updatedEventTypeSelect = {
    slug: true,
    schedulingType: true
  };
  let updatedEventType;
  try {
    updatedEventType = await ctx.prisma.eventType.update({
      where: { id },
      data,
      select: updatedEventTypeSelect
    });
  } catch (e) {
    if (e instanceof Prisma.PrismaClientKnownRequestError) {
      if (e.code === "P2002") {
        throw new TRPCError({ message: "error_event_type_url_duplicate", code: "BAD_REQUEST" });
      }
    }
    throw e;
  }
  const updatedValues = Object.entries(data).reduce((acc, [key, value]) => {
    if (value !== void 0) {
      acc[key] = value;
    }
    return acc;
  }, {});
  await handleChildrenEventTypes({
    eventTypeId: id,
    currentUserId: ctx.user.id,
    oldEventType: eventType,
    updatedEventType,
    children,
    profileId: ctx.user.profile.id,
    prisma: ctx.prisma,
    updatedValues
  });
  if (hostGroups !== void 0 || hosts) {
    await ctx.prisma.hostGroup.deleteMany({
      where: {
        eventTypeId: id,
        hosts: {
          none: {}
        }
      }
    });
  }
  const res = ctx.res;
  if (typeof res?.revalidate !== "undefined") {
    try {
      await res?.revalidate(`/${ctx.user.username}/${updatedEventType.slug}`);
    } catch (e) {
      logger.debug(e?.message);
    }
  }
  return { eventType };
};
const log$1 = logger.getSubLogger({ prefix: ["getEventTypesPublic"] });
async function getEventTypesPublic(userId) {
  const eventTypesWithHidden = await getEventTypesWithHiddenFromDB(userId);
  const eventTypesRaw = eventTypesWithHidden.filter((evt) => !evt.hidden);
  return eventTypesRaw.map((eventType) => ({
    ...eventType,
    metadata: EventTypeMetaDataSchema.parse(eventType.metadata || {}),
    descriptionAsSafeHTML: markdownToSafeHTML(eventType.description)
  }));
}
const getEventTypesWithHiddenFromDB = async (userId) => {
  const eventTypes = await prisma.$queryRaw`
    SELECT data."id", data."title", data."description", data."length", data."schedulingType"::text,
      data."recurringEvent", data."slug", data."hidden", data."price", data."currency",
      data."lockTimeZoneToggleOnBookingPage", data."lockedTimeZone", data."requiresConfirmation", data."requiresBookerEmailVerification",
      data."metadata", data."canSendCalVideoTranscriptionEmails"
      FROM (
        SELECT "EventType"."id", "EventType"."title", "EventType"."description",
          "EventType"."position", "EventType"."length", "EventType"."schedulingType"::text,
          "EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden",
          "EventType"."price", "EventType"."currency",
          "EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."lockedTimeZone", "EventType"."requiresConfirmation",
          "EventType"."requiresBookerEmailVerification", "EventType"."metadata",
          "EventType"."canSendCalVideoTranscriptionEmails"
        FROM "EventType"
        WHERE "EventType"."teamId" IS NULL AND "EventType"."userId" = ${userId}
        UNION
        SELECT "EventType"."id", "EventType"."title", "EventType"."description",
        "EventType"."position", "EventType"."length", "EventType"."schedulingType"::text,
        "EventType"."recurringEvent", "EventType"."slug", "EventType"."hidden",
        "EventType"."price", "EventType"."currency",
        "EventType"."lockTimeZoneToggleOnBookingPage", "EventType"."lockedTimeZone", "EventType"."requiresConfirmation",
        "EventType"."requiresBookerEmailVerification", "EventType"."metadata",
        "EventType"."canSendCalVideoTranscriptionEmails"
        FROM "EventType"
        WHERE "EventType"."teamId" IS NULL
        AND "EventType"."userId" IS NOT NULL
        AND "EventType"."id" IN (
          SELECT "uet1"."A" FROM "_user_eventtype" AS "uet1"
          INNER JOIN "users" AS "u1" ON "u1"."id" = "uet1"."B"
          WHERE "u1"."id" = ${userId} AND "uet1"."A" IS NOT NULL
      )
    ) data
    ORDER BY data."position" DESC, data."id" ASC`;
  return eventTypes.reduce((eventTypes2, eventType) => {
    const parsedMetadata = EventTypeMetaDataSchema.safeParse(eventType.metadata);
    if (!parsedMetadata.success) {
      log$1.error(parsedMetadata.error);
      return eventTypes2;
    }
    eventTypes2.push({
      ...eventType,
      metadata: parsedMetadata.data
    });
    return eventTypes2;
  }, []);
};
async function getLocationGroupedOptions(userOrTeamId, t) {
  const apps = {};
  let idToSearchObject;
  let user = null;
  if ("teamId" in userOrTeamId) {
    const teamId = userOrTeamId.teamId;
    const org = await prisma.team.findFirst({
      where: {
        children: {
          some: {
            id: teamId
          }
        }
      }
    });
    if (org) {
      idToSearchObject = {
        teamId: {
          in: [teamId, org.id]
        }
      };
    } else {
      idToSearchObject = { teamId };
    }
  } else {
    idToSearchObject = { userId: userOrTeamId.userId };
    user = await prisma.user.findUnique({
      where: {
        id: userOrTeamId.userId
      }
    });
  }
  const nonDelegationCredentials = await prisma.credential.findMany({
    where: {
      ...idToSearchObject,
      app: {
        categories: {
          hasSome: defaultVideoAppCategories
        }
      }
    },
    select: {
      ...credentialForCalendarServiceSelect,
      team: {
        select: {
          name: true
        }
      }
    }
  });
  let credentials;
  if (user) {
    const { credentials: allCredentials } = await enrichUserWithDelegationConferencingCredentialsWithoutOrgId(
      {
        user: {
          ...user,
          credentials: nonDelegationCredentials
        }
      }
    );
    credentials = allCredentials;
  } else {
    credentials = buildNonDelegationCredentials(nonDelegationCredentials);
  }
  const integrations = await getEnabledAppsFromCredentials(credentials, { filterOnCredentials: true });
  integrations.forEach((app) => {
    if (app.locationOption) {
      let groupByCategory = app.categories.length >= 2 ? app.categories.find((groupByCategory2) => !defaultVideoAppCategories.includes(groupByCategory2)) : app.categories[0] || app.category;
      if (!groupByCategory)
        groupByCategory = AppCategories.conferencing;
      for (const { teamName } of app.credentials.map((credential) => ({
        teamName: credential.team?.name
      }))) {
        const label = `${app.locationOption.label} ${teamName ? `(${teamName})` : ""}`;
        const option = {
          ...app.locationOption,
          label,
          icon: app.logo,
          slug: app.slug,
          ...app.credential ? { credentialId: app.credential.id, teamName: app.credential.team?.name ?? null } : {}
        };
        if (apps[groupByCategory]) {
          const existingOption = apps[groupByCategory].find((o) => o.value === option.value);
          if (!existingOption) {
            apps[groupByCategory] = [...apps[groupByCategory], option];
          }
        } else {
          apps[groupByCategory] = [option];
        }
      }
    }
  });
  defaultLocations.forEach((l) => {
    const category = l.category;
    if (apps[category]) {
      apps[category] = [
        ...apps[category],
        {
          label: l.label,
          value: l.type,
          icon: l.iconUrl,
          supportsCustomLabel: l.supportsCustomLabel
        }
      ];
    } else {
      apps[category] = [
        {
          label: l.label,
          value: l.type,
          icon: l.iconUrl,
          supportsCustomLabel: l.supportsCustomLabel
        }
      ];
    }
  });
  const locations = [];
  for (const category in apps) {
    const tmp = {
      label: t(category),
      options: apps[category].map((l) => ({
        ...l,
        label: t(l.label)
      }))
    };
    locations.push(tmp);
  }
  return locations;
}
const getEventTypeById = async ({
  currentOrganizationId,
  eventTypeId,
  userId,
  prisma: prisma2,
  isTrpcCall = false,
  isUserOrganizationAdmin
}) => {
  const userSelect2 = {
    name: true,
    avatarUrl: true,
    username: true,
    id: true,
    email: true,
    locale: true,
    defaultScheduleId: true,
    isPlatformManaged: true,
    timeZone: true
  };
  const rawEventType = await getRawEventType({
    userId,
    eventTypeId,
    isUserOrganizationAdmin,
    currentOrganizationId,
    prisma: prisma2
  });
  if (!rawEventType) {
    if (isTrpcCall) {
      throw new TRPCError({ code: "NOT_FOUND" });
    } else {
      throw new Error("Event type not found");
    }
  }
  const { locations, metadata, ...restEventType } = rawEventType;
  const newMetadata = eventTypeMetaDataSchemaWithTypedApps.parse(metadata || {}) || {};
  const apps = newMetadata?.apps || {};
  const eventTypeWithParsedMetadata = { ...rawEventType, metadata: newMetadata };
  const userRepo = new UserRepository(prisma2);
  const eventTeamMembershipsWithUserProfile = [];
  for (const eventTeamMembership of rawEventType.team?.members || []) {
    eventTeamMembershipsWithUserProfile.push({
      ...eventTeamMembership,
      user: await userRepo.enrichUserWithItsProfile({
        user: eventTeamMembership.user
      })
    });
  }
  const childrenWithUserProfile = [];
  for (const child of rawEventType.children || []) {
    childrenWithUserProfile.push({
      ...child,
      owner: child.owner ? await userRepo.enrichUserWithItsProfile({
        user: child.owner
      }) : null
    });
  }
  const eventTypeUsersWithUserProfile = [];
  for (const eventTypeUser of rawEventType.users) {
    eventTypeUsersWithUserProfile.push(
      await userRepo.enrichUserWithItsProfile({
        user: eventTypeUser
      })
    );
  }
  newMetadata.apps = {
    ...apps,
    giphy: getEventTypeAppData(eventTypeWithParsedMetadata, "giphy", true)
  };
  const parsedMetaData = newMetadata;
  const parsedCustomInputs = (rawEventType.customInputs || []).map((input) => customInputSchema.parse(input));
  const eventType = {
    ...restEventType,
    schedule: rawEventType.schedule?.id || (!rawEventType.team ? rawEventType.users[0]?.defaultScheduleId : null) || null,
    restrictionScheduleId: rawEventType.restrictionScheduleId || null,
    restrictionScheduleName: rawEventType.restrictionSchedule?.name || null,
    useBookerTimezone: rawEventType.useBookerTimezone || false,
    instantMeetingSchedule: rawEventType.instantMeetingSchedule?.id || null,
    scheduleName: rawEventType.schedule?.name || null,
    recurringEvent: parseRecurringEvent(restEventType.recurringEvent),
    bookingLimits: parseBookingLimit(restEventType.bookingLimits),
    durationLimits: parseDurationLimit(restEventType.durationLimits),
    eventTypeColor: parseEventTypeColor(restEventType.eventTypeColor),
    locations,
    metadata: parsedMetaData,
    customInputs: parsedCustomInputs,
    users: rawEventType.users,
    bookerUrl: restEventType.team ? await getBookerBaseUrl(restEventType.team.parentId) : restEventType.owner ? await getBookerBaseUrl(currentOrganizationId) : WEBSITE_URL,
    children: childrenWithUserProfile.flatMap(
      (ch) => ch.owner !== null ? {
        ...ch,
        owner: {
          ...ch.owner,
          avatar: getUserAvatarUrl(ch.owner),
          email: ch.owner.email,
          name: ch.owner.name ?? "",
          username: ch.owner.username ?? "",
          membership: restEventType.team?.members.find((tm) => tm.user.id === ch.owner?.id)?.role || MembershipRole.MEMBER
        },
        created: true
      } : []
    )
  };
  if (eventType.users.length === 0 && !eventType.team) {
    const fallbackUser = await prisma2.user.findUnique({
      where: {
        id: userId
      },
      select: userSelect2
    });
    if (!fallbackUser) {
      if (isTrpcCall) {
        throw new TRPCError({
          code: "NOT_FOUND",
          message: "The event type doesn't have user and no fallback user was found"
        });
      } else {
        throw Error("The event type doesn't have user and no fallback user was found");
      }
    }
    eventType.users.push(fallbackUser);
  }
  const eventTypeUsers = eventTypeUsersWithUserProfile.map((user) => ({
    ...user,
    avatar: getUserAvatarUrl(user)
  }));
  const currentUser = eventType.users.find((u) => u.id === userId);
  const t = await getTranslation(currentUser?.locale ?? "en", "common");
  if (!currentUser?.id && !eventType.teamId) {
    throw new TRPCError({
      code: "NOT_FOUND",
      message: "Could not find user or team"
    });
  }
  const locationOptions = await getLocationGroupedOptions(
    eventType.teamId ? { teamId: eventType.teamId } : { userId },
    t
  );
  if (eventType.schedulingType === SchedulingType.MANAGED) {
    locationOptions.splice(0, 0, {
      label: t("default"),
      options: [
        {
          label: t("members_default_location"),
          value: "",
          icon: "/user-check.svg"
        }
      ]
    });
  }
  const isOrgTeamEvent = !!eventType?.teamId && !!eventType.team?.parentId;
  const eventTypeObject = Object.assign({}, eventType, {
    users: eventTypeUsers,
    periodStartDate: eventType.periodStartDate?.toString() ?? null,
    periodEndDate: eventType.periodEndDate?.toString() ?? null,
    bookingFields: getBookingFieldsWithSystemFields({ ...eventType, isOrgTeamEvent })
  });
  const isOrgEventType = !!eventTypeObject.team?.parentId;
  const teamMembers = eventTypeObject.team ? eventTeamMembershipsWithUserProfile.filter((member) => member.accepted || isOrgEventType).map((member) => {
    const user = {
      ...member.user,
      avatar: getUserAvatarUrl(member.user)
    };
    return {
      ...user,
      profileId: user.profile.id,
      eventTypes: user.eventTypes.map((evTy) => evTy.slug),
      membership: member.role
    };
  }) : [];
  const currentUserMembership = eventTypeObject.team?.members.find((el) => el.user.id === userId) ?? null;
  let destinationCalendar = eventTypeObject.destinationCalendar;
  if (!destinationCalendar) {
    destinationCalendar = await prisma2.destinationCalendar.findFirst({
      where: {
        userId,
        eventTypeId: null
      }
    });
  }
  const finalObj = {
    eventType: eventTypeObject,
    locationOptions,
    destinationCalendar,
    team: eventTypeObject.team || null,
    teamMembers,
    currentUserMembership,
    isUserOrganizationAdmin
  };
  return finalObj;
};
async function getRawEventType({
  userId,
  eventTypeId,
  isUserOrganizationAdmin,
  currentOrganizationId,
  prisma: prisma2
}) {
  const eventTypeRepo = new EventTypeRepository(prisma2);
  if (isUserOrganizationAdmin && currentOrganizationId) {
    return await eventTypeRepo.findByIdForOrgAdmin({
      id: eventTypeId,
      organizationId: currentOrganizationId
    });
  }
  return await eventTypeRepo.findById({
    id: eventTypeId,
    userId
  });
}
const log = logger.getSubLogger({ prefix: ["viewer.eventTypes.getByViewer"] });
const getEventTypesByViewer = async (user, filters, forRoutingForms) => {
  const userProfile = user.profile;
  const profile = await ProfileRepository.findByUpId(userProfile.upId);
  const parentOrgHasLockedEventTypes = profile?.organization?.organizationSettings?.lockEventTypeCreationForUsers;
  const isFilterSet = filters && hasFilter(filters);
  const isUpIdInFilter = filters?.upIds?.includes(userProfile.upId);
  let shouldListUserEvents = !isFilterSet || isUpIdInFilter;
  if (isFilterSet && filters?.upIds && !isUpIdInFilter) {
    shouldListUserEvents = true;
  }
  const eventTypeRepo = new EventTypeRepository(prisma);
  const [profileMemberships, profileEventTypes] = await Promise.all([
    MembershipRepository.findAllByUpIdIncludeTeamWithMembersAndEventTypes(
      {
        upId: userProfile.upId
      },
      {
        where: {
          accepted: true
        }
      }
    ),
    shouldListUserEvents ? eventTypeRepo.findAllByUpId(
      {
        upId: userProfile.upId,
        userId: user.id
      },
      {
        where: {
          teamId: null
        },
        orderBy: [
          {
            position: "desc"
          },
          {
            id: "asc"
          }
        ]
      }
    ) : []
  ]);
  if (!profile) {
    throw new TRPCError({ code: "INTERNAL_SERVER_ERROR" });
  }
  const memberships = profileMemberships.map((membership) => ({
    ...membership,
    team: {
      ...membership.team,
      metadata: teamMetadataSchema.parse(membership.team.metadata)
    }
  }));
  log.debug(
    safeStringify({
      profileMemberships,
      profileEventTypes
    })
  );
  const mapEventType = async (eventType) => {
    const userRepo = new UserRepository(prisma);
    return {
      ...eventType,
      safeDescription: eventType?.description ? markdownToSafeHTML(eventType.description) : void 0,
      users: await Promise.all(
        (!!eventType?.hosts?.length ? eventType?.hosts.map((host) => host.user) : eventType.users).map(
          async (u) => await userRepo.enrichUserWithItsProfile({
            user: u
          })
        )
      ),
      metadata: eventType.metadata ? eventTypeMetaDataSchemaWithUntypedApps.parse(eventType.metadata) : null,
      children: await Promise.all(
        (eventType.children || []).map(async (c) => ({
          ...c,
          users: await Promise.all(
            c.users.map(
              async (u) => await userRepo.enrichUserWithItsProfile({
                user: u
              })
            )
          )
        }))
      )
    };
  };
  const userEventTypes = (await Promise.all(profileEventTypes.map(mapEventType))).filter((eventType) => {
    const isAChildEvent = eventType.parentId;
    if (!isAChildEvent) {
      return true;
    }
    const childEventAssignee = eventType.users[0];
    if (!childEventAssignee || childEventAssignee.id != user.id) {
      return false;
    }
    return true;
  });
  let eventTypeGroups = [];
  const unmanagedEventTypes = userEventTypes.filter(
    (evType) => evType.schedulingType !== SchedulingType.MANAGED
  );
  log.debug(safeStringify({ profileMemberships, profileEventTypes, profile }));
  log.debug(
    "Filter Settings",
    safeStringify({
      isFilterSet,
      isProfileIdInFilter: isUpIdInFilter
    })
  );
  if (shouldListUserEvents) {
    const bookerUrl = await getBookerBaseUrl(profile.organizationId ?? null);
    eventTypeGroups.push({
      teamId: null,
      bookerUrl,
      membershipRole: null,
      profile: {
        slug: profile.username,
        name: profile.name,
        image: getUserAvatarUrl({
          avatarUrl: profile.avatarUrl
        }),
        eventTypesLockedByOrg: parentOrgHasLockedEventTypes
      },
      eventTypes: orderBy(unmanagedEventTypes, ["position", "id"], ["desc", "asc"]),
      metadata: {
        membershipCount: 1,
        readOnly: false
      }
    });
  }
  const teamMemberships = profileMemberships.map((membership) => ({
    teamId: membership.team.id,
    membershipRole: membership.role
  }));
  const filterByTeamIds = async (eventType) => {
    if (!filters || !hasFilter(filters)) {
      return true;
    }
    return filters?.teamIds?.includes(eventType?.teamId || 0) ?? false;
  };
  const filterBySchedulingTypes = (evType) => {
    if (!filters || !hasFilter(filters) || !filters.schedulingTypes) {
      return true;
    }
    if (!evType.schedulingType)
      return false;
    return filters.schedulingTypes.includes(evType.schedulingType);
  };
  eventTypeGroups = [].concat(
    eventTypeGroups,
    await Promise.all(
      memberships.filter((mmship) => {
        if (mmship.team.isOrganization) {
          return false;
        } else {
          if (!filters || !hasFilter(filters)) {
            return true;
          }
          return filters?.teamIds?.includes(mmship?.team?.id || 0) ?? false;
        }
      }).map(async (membership) => {
        const orgMembership = teamMemberships.find(
          (teamM) => teamM.teamId === membership.team.parentId
        )?.membershipRole;
        const team = {
          ...membership.team,
          metadata: teamMetadataSchema.parse(membership.team.metadata)
        };
        let slug;
        if (forRoutingForms) {
          slug = `team/${team.slug}`;
        } else {
          slug = team.slug ? !team.parentId ? `team/${team.slug}` : `${team.slug}` : null;
        }
        const eventTypes = await Promise.all(team.eventTypes.map(mapEventType));
        const teamParentMetadata = team.parent ? teamMetadataSchema.parse(team.parent.metadata) : null;
        return {
          teamId: team.id,
          parentId: team.parentId,
          bookerUrl: getBookerBaseUrlSync(team.parent?.slug ?? teamParentMetadata?.requestedSlug ?? null),
          membershipRole: orgMembership && compareMembership(orgMembership, membership.role) ? orgMembership : membership.role,
          profile: {
            image: team.parent ? getPlaceholderAvatar(team.parent.logoUrl, team.parent.name) : getPlaceholderAvatar(team.logoUrl, team.name),
            name: team.name,
            slug
          },
          metadata: {
            membershipCount: team.members.length,
            readOnly: membership.role === (team.parentId ? orgMembership && compareMembership(orgMembership, membership.role) ? orgMembership : MembershipRole.MEMBER : MembershipRole.MEMBER)
          },
          eventTypes: eventTypes.filter(filterByTeamIds).filter((evType) => {
            const res = evType.userId === null || evType.userId === user.id;
            return res;
          }).filter(
            (evType) => membership.role === MembershipRole.MEMBER ? evType.schedulingType !== SchedulingType.MANAGED : true
          ).filter(filterBySchedulingTypes)
        };
      })
    )
  );
  const denormalizedPayload = {
    eventTypeGroups,
    // so we can show a dropdown when the user has teams
    profiles: eventTypeGroups.map((group) => ({
      ...group.profile,
      ...group.metadata,
      teamId: group.teamId,
      membershipRole: group.membershipRole
    }))
  };
  return normalizePayload(denormalizedPayload);
  function normalizePayload(payload) {
    const allUsersAcrossAllEventTypes = /* @__PURE__ */ new Map();
    const eventTypeGroups2 = payload.eventTypeGroups.map((group) => {
      return {
        ...group,
        eventTypes: group.eventTypes.map((eventType) => {
          const { users, ...rest } = eventType;
          return {
            ...rest,
            // Send userIds per event and keep the actual users object outside
            userIds: users.map((user2) => {
              allUsersAcrossAllEventTypes.set(user2.id, user2);
              return user2.id;
            })
          };
        })
      };
    });
    return {
      ...payload,
      allUsersAcrossAllEventTypes,
      eventTypeGroups: eventTypeGroups2
    };
  }
};
function compareMembership(mship1, mship2) {
  const mshipToNumber = (mship) => Object.keys(MembershipRole).findIndex((mmship) => mmship === mship);
  return mshipToNumber(mship1) > mshipToNumber(mship2);
}
const bulkUpdateEventsToDefaultLocation = async ({
  eventTypeIds,
  user,
  prisma: prisma2
}) => {
  const defaultApp = userMetadata.parse(user.metadata)?.defaultConferencingApp;
  if (!defaultApp) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: "Default conferencing app not set"
    });
  }
  const foundApp = getAppFromSlug(defaultApp.appSlug);
  const appType = foundApp?.appData?.location?.type;
  if (!appType) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: `Default conferencing app '${defaultApp.appSlug}' doesnt exist.`
    });
  }
  const credential = await prisma2.credential.findFirst({
    where: {
      userId: user.id,
      appId: foundApp.slug
    },
    select: {
      id: true
    }
  });
  return await prisma2.eventType.updateMany({
    where: {
      id: {
        in: eventTypeIds
      },
      userId: user.id
    },
    data: {
      locations: [
        { type: appType, link: defaultApp.appLink, credentialId: credential?.id }
      ]
    }
  });
};
const bulkUpdateTeamEventsToDefaultLocation = async ({
  eventTypeIds,
  teamId,
  prisma: prisma2
}) => {
  const team = await prisma2.team.findUnique({
    where: { id: teamId },
    select: { metadata: true }
  });
  const defaultApp = teamMetadataSchema.parse(team?.metadata)?.defaultConferencingApp;
  if (!defaultApp) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: "Default conferencing app not set"
    });
  }
  const foundApp = getAppFromSlug(defaultApp.appSlug);
  const appType = foundApp?.appData?.location?.type;
  if (!appType) {
    throw new TRPCError({
      code: "BAD_REQUEST",
      message: `Default conferencing app '${defaultApp.appSlug}' doesnt exist.`
    });
  }
  const credential = await prisma2.credential.findFirst({
    where: {
      teamId,
      appId: foundApp.slug
    },
    select: {
      id: true
    }
  });
  return await prisma2.eventType.updateMany({
    where: {
      id: {
        in: eventTypeIds
      },
      teamId
    },
    data: {
      locations: [
        { type: appType, link: defaultApp.appLink, credentialId: credential?.id }
      ]
    }
  });
};
export {
  E as EventManager,
  EventTypeMetaDataSchema,
  bulkUpdateEventsToDefaultLocation,
  bulkUpdateTeamEventsToDefaultLocation,
  createHandler as createEventType,
  aw as eventTypeBookingFields,
  eventTypeLocations,
  a as getBulkTeamEventTypes,
  g as getBulkUserEventTypes,
  getEventTypeById,
  getEventTypesByViewer,
  getEventTypesPublic,
  getPublicEvent,
  parseEventTypeColor,
  updateHandler as updateEventType,
  updateNewTeamMemberEventTypes,
  aA as validateCustomEventName
};
