import { l as logger, K as WebhookTriggerEvents, a as safeStringify, p as prisma, d as bookingMinimalSelect, c as credentialForCalendarServiceSelect, E as EventTypeMetaDataSchema, j as getTranslation, B as BookingStatus, ax as eventTypeAppMetadataOptionalSchema } from "./orgDomains-eTg-cjth.js";
import dayjs from "dayjs";
import { g as getWebhooks, s as sendPayload, a as getAllCredentialsIncludeServiceAccountKey, h as handleConfirmation } from "./handleConfirmation-ca4z0kHJ.js";
import { i as sendOrganizerRequestEmail, j as sendAttendeeRequestEmailAndSMS, as as getOrgIdFromMemberOrTeamId, au as workflowSelect, at as getBookerBaseUrl, av as getTimeFormatStringFromUserTimeFormat, s as sendScheduledEmailsAndSMS } from "./email-manager-mHSBIi6g.js";
import { captureException } from "@sentry/nextjs";
import { E as EventManager, p as placeholderCreatedEvent } from "./allowDisablingStandardEmails-ijNSmDEY.js";
import { H as HttpError } from "./http-error-RJXCPZV2.js";
import { g as getCalEventResponses } from "./getCalEventResponses-Sb7XbRd2.js";
import { a as isPrismaObjOrUndefined } from "./isPrismaObj-NqBB0qe9.js";
import { p as parseRecurringEvent } from "./isRecurringEvent-jPe_vtM6.js";
import { a as enrichUserWithDelegationCredentials } from "./credential-INULiwKH.js";
const doesBookingRequireConfirmation = ({
  booking: { startTime, eventType }
}) => {
  let requiresConfirmation = eventType?.requiresConfirmation;
  const rcThreshold = eventType?.metadata?.requiresConfirmationThreshold;
  if (rcThreshold) {
    const startTimeUTC = dayjs(startTime).utc();
    const currentTime = dayjs();
    const timeDifference = startTimeUTC.diff(currentTime, rcThreshold.unit);
    if (timeDifference > rcThreshold.time) {
      requiresConfirmation = false;
    }
  }
  return requiresConfirmation;
};
const getWebhookPayloadForBooking = ({
  booking,
  evt
}) => {
  const eventTypeInfo = {
    eventTitle: booking.eventType?.title,
    eventDescription: booking.eventType?.description,
    requiresConfirmation: booking.eventType?.requiresConfirmation || null,
    price: booking.eventType?.price,
    currency: booking.eventType?.currency,
    length: booking.eventType?.length
  };
  const payload = {
    ...evt,
    ...eventTypeInfo,
    bookingId: booking.id
  };
  return payload;
};
const log$1 = logger.getSubLogger({ prefix: ["[handleBookingRequested] book:user"] });
async function handleBookingRequested(args) {
  const { evt, booking } = args;
  log$1.debug("Emails: Sending booking requested emails");
  await sendOrganizerRequestEmail({ ...evt }, booking?.eventType?.metadata);
  await sendAttendeeRequestEmailAndSMS(
    { ...evt },
    evt.attendees[0],
    booking?.eventType?.metadata
  );
  const orgId = await getOrgIdFromMemberOrTeamId({
    memberId: booking.userId,
    teamId: booking.eventType?.teamId
  });
  try {
    const subscribersBookingRequested = await getWebhooks({
      userId: booking.userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: WebhookTriggerEvents.BOOKING_REQUESTED,
      teamId: booking.eventType?.teamId,
      orgId
    });
    const webhookPayload = getWebhookPayloadForBooking({
      booking,
      evt
    });
    const promises = subscribersBookingRequested.map(
      (sub) => sendPayload(
        sub.secret,
        WebhookTriggerEvents.BOOKING_REQUESTED,
        (/* @__PURE__ */ new Date()).toISOString(),
        sub,
        webhookPayload
      ).catch((e) => {
        log$1.error(
          `Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_REQUESTED}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
          safeStringify(e)
        );
      })
    );
    await Promise.all(promises);
  } catch (error) {
    log$1.error("Error in handleBookingRequested", safeStringify(error));
  }
}
function getPlatformParams(platformOAuthClient) {
  return {
    platformClientId: platformOAuthClient.id,
    platformCancelUrl: platformOAuthClient.bookingCancelRedirectUri,
    platformRescheduleUrl: platformOAuthClient.bookingRescheduleRedirectUri,
    platformBookingUrl: platformOAuthClient.bookingRedirectUri,
    arePlatformEmailsEnabled: platformOAuthClient.areEmailsEnabled,
    areCalendarEventsEnabled: platformOAuthClient.areCalendarEventsEnabled
  };
}
class PlatformOAuthClientRepository {
  async getByUserId(userId) {
    try {
      return prisma.platformOAuthClient.findFirst({
        where: {
          users: {
            some: {
              id: userId
            }
          }
        }
      });
    } catch (err) {
      captureException(err);
      throw err;
    }
  }
}
async function getEventType(id) {
  return prisma.eventType.findUnique({
    where: {
      id
    },
    select: {
      id: true,
      recurringEvent: true,
      requiresConfirmation: true,
      metadata: true
    }
  });
}
async function getBooking(bookingId) {
  const booking = await prisma.booking.findUnique({
    where: {
      id: bookingId
    },
    select: {
      ...bookingMinimalSelect,
      responses: true,
      eventType: {
        select: {
          currency: true,
          description: true,
          id: true,
          length: true,
          price: true,
          requiresConfirmation: true,
          hideOrganizerEmail: true,
          metadata: true,
          customReplyToEmail: true,
          title: true,
          teamId: true,
          parentId: true,
          parent: {
            select: {
              teamId: true
            }
          },
          slug: true,
          workflows: {
            select: {
              workflow: {
                select: workflowSelect
              }
            }
          },
          bookingFields: true,
          team: {
            select: {
              id: true,
              name: true,
              parentId: true
            }
          }
        }
      },
      metadata: true,
      smsReminderNumber: true,
      location: true,
      eventTypeId: true,
      userId: true,
      uid: true,
      paid: true,
      destinationCalendar: true,
      status: true,
      user: {
        select: {
          id: true,
          username: true,
          timeZone: true,
          credentials: { select: credentialForCalendarServiceSelect },
          timeFormat: true,
          email: true,
          name: true,
          locale: true,
          destinationCalendar: true,
          isPlatformManaged: true
        }
      }
    }
  });
  if (!booking)
    throw new HttpError({ statusCode: 204, message: "No booking found" });
  let eventTypeRaw = null;
  if (booking.eventTypeId) {
    eventTypeRaw = await getEventType(booking.eventTypeId);
  }
  const eventType = { ...eventTypeRaw, metadata: EventTypeMetaDataSchema.parse(eventTypeRaw?.metadata) };
  const { user: userWithoutDelegationCredentials } = booking;
  if (!userWithoutDelegationCredentials)
    throw new HttpError({ statusCode: 204, message: "No user found" });
  const user = await enrichUserWithDelegationCredentials({
    user: userWithoutDelegationCredentials
  });
  const t = await getTranslation(user.locale ?? "en", "common");
  const attendeesListPromises = booking.attendees.map(async (attendee) => {
    return {
      name: attendee.name,
      email: attendee.email,
      timeZone: attendee.timeZone,
      language: {
        translate: await getTranslation(attendee.locale ?? "en", "common"),
        locale: attendee.locale ?? "en"
      }
    };
  });
  const organizerOrganizationProfile = await prisma.profile.findFirst({
    where: {
      userId: booking.userId ?? void 0
    }
  });
  const organizerOrganizationId = organizerOrganizationProfile?.organizationId;
  const bookerUrl = await getBookerBaseUrl(
    booking.eventType?.team?.parentId ?? organizerOrganizationId ?? null
  );
  const attendeesList = await Promise.all(attendeesListPromises);
  const selectedDestinationCalendar = booking.destinationCalendar || user.destinationCalendar;
  const evt = {
    type: booking?.eventType?.slug,
    title: booking.title,
    bookerUrl,
    description: booking.description || void 0,
    startTime: booking.startTime.toISOString(),
    endTime: booking.endTime.toISOString(),
    customInputs: isPrismaObjOrUndefined(booking.customInputs),
    ...getCalEventResponses({
      booking,
      bookingFields: booking.eventType?.bookingFields || null
    }),
    organizer: {
      email: booking?.userPrimaryEmail ?? user.email,
      // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
      name: user.name,
      timeZone: user.timeZone,
      timeFormat: getTimeFormatStringFromUserTimeFormat(user.timeFormat),
      language: { translate: t, locale: user.locale ?? "en" },
      id: user.id
    },
    hideOrganizerEmail: booking.eventType?.hideOrganizerEmail,
    team: !!booking.eventType?.team ? {
      name: booking.eventType.team.name,
      id: booking.eventType.team.id,
      members: []
    } : void 0,
    attendees: attendeesList,
    location: booking.location,
    uid: booking.uid,
    destinationCalendar: selectedDestinationCalendar ? [selectedDestinationCalendar] : [],
    recurringEvent: parseRecurringEvent(eventType?.recurringEvent),
    customReplyToEmail: booking.eventType?.customReplyToEmail
  };
  return {
    booking,
    user,
    evt,
    eventType
  };
}
const log = logger.getSubLogger({ prefix: ["[handlePaymentSuccess]"] });
async function handlePaymentSuccess(paymentId, bookingId) {
  log.debug(`handling payment success for bookingId ${bookingId}`);
  const { booking, user: userWithCredentials, evt, eventType } = await getBooking(bookingId);
  if (booking.location)
    evt.location = booking.location;
  const bookingData = {
    paid: true,
    status: BookingStatus.ACCEPTED
  };
  const allCredentials = await getAllCredentialsIncludeServiceAccountKey(userWithCredentials, {
    ...booking.eventType,
    metadata: booking.eventType?.metadata
  });
  const isConfirmed = booking.status === BookingStatus.ACCEPTED;
  const platformOAuthClientRepository = new PlatformOAuthClientRepository();
  const platformOAuthClient = userWithCredentials.isPlatformManaged ? await platformOAuthClientRepository.getByUserId(userWithCredentials.id) : null;
  const areCalendarEventsEnabled = platformOAuthClient?.areCalendarEventsEnabled ?? true;
  const areEmailsEnabled = platformOAuthClient?.areEmailsEnabled ?? true;
  if (isConfirmed) {
    const apps = eventTypeAppMetadataOptionalSchema.parse(eventType?.metadata?.apps);
    const eventManager = new EventManager({ ...userWithCredentials, credentials: allCredentials }, apps);
    const scheduleResult = areCalendarEventsEnabled ? await eventManager.create(evt) : placeholderCreatedEvent;
    bookingData.references = { create: scheduleResult.referencesToCreate };
  }
  const requiresConfirmation = doesBookingRequireConfirmation({
    booking: {
      ...booking,
      eventType
    }
  });
  if (requiresConfirmation) {
    delete bookingData.status;
  }
  const paymentUpdate = prisma.payment.update({
    where: {
      id: paymentId
    },
    data: {
      success: true
    }
  });
  const bookingUpdate = prisma.booking.update({
    where: {
      id: booking.id
    },
    data: bookingData
  });
  await prisma.$transaction([paymentUpdate, bookingUpdate]);
  if (!isConfirmed) {
    if (!requiresConfirmation) {
      await handleConfirmation({
        user: { ...userWithCredentials, credentials: allCredentials },
        evt,
        prisma,
        bookingId: booking.id,
        booking,
        paid: true,
        platformClientParams: platformOAuthClient ? getPlatformParams(platformOAuthClient) : void 0
      });
    } else {
      await handleBookingRequested({
        evt,
        booking
      });
      log.debug(`handling booking request for eventId ${eventType.id}`);
    }
  } else if (areEmailsEnabled) {
    await sendScheduledEmailsAndSMS({ ...evt }, void 0, void 0, void 0, eventType.metadata);
  }
  throw new HttpError({
    statusCode: 200,
    message: `Booking with id '${booking.id}' was paid and confirmed.`
  });
}
export {
  handlePaymentSuccess as h
};
