"use strict";
const credential = require("./credential-9BNiqYc8.cjs");
const user = require("./user-cPqQS_l_.cjs");
const index = require("./orgDomains-W_rFTMBa.cjs");
const index$1 = require("./email-manager-w-Fd9mb6.cjs");
const allowDisablingStandardEmails = require("./allowDisablingStandardEmails-ePazUekp.cjs");
const reminderScheduler = require("./reminderScheduler-ikn0HaU9.cjs");
const scheduleTrigger = require("./scheduleTrigger-_fJQ0gee.cjs");
const sendPayload$1 = require("./sendPayload-vPFBacjS.cjs");
const CalEventParser = require("./CalEventParser-XK6njYFX.cjs");
const getCalEventResponses = require("./getCalEventResponses--KV3bpgK.cjs");
const locations = require("./locations-Dh6t6Iz8.cjs");
const dayjs = require("dayjs");
const webhookSelect = {
  id: true,
  subscriberUrl: true,
  payloadTemplate: true,
  appId: true,
  secret: true,
  time: true,
  timeUnit: true,
  eventTriggers: true
};
const getWebhooks = async (options, prisma = index.prisma) => {
  const teamId = options.teamId;
  const userId = options.userId ?? 0;
  const eventTypeId = options.eventTypeId ?? 0;
  const teamIds = Array.isArray(teamId) ? teamId : [teamId ?? 0];
  const orgId = options.orgId ?? 0;
  const oAuthClientId = options.oAuthClientId ?? "";
  const managedChildEventType = await prisma.eventType.findFirst({
    where: {
      id: eventTypeId,
      parentId: {
        not: null
      }
    },
    select: {
      parentId: true
    }
  });
  const managedParentEventTypeId = managedChildEventType?.parentId ?? 0;
  const allWebhooks = await prisma.webhook.findMany({
    where: {
      OR: [
        {
          platform: true
        },
        {
          userId
        },
        {
          eventTypeId
        },
        {
          eventTypeId: managedParentEventTypeId
        },
        {
          teamId: {
            in: [...teamIds, orgId]
          }
        },
        { platformOAuthClientId: oAuthClientId }
      ],
      AND: {
        eventTriggers: {
          has: options.triggerEvent
        },
        active: {
          equals: true
        }
      }
    },
    select: webhookSelect
  });
  return allWebhooks;
};
const getWebhooks$1 = index.withReporting(getWebhooks, "getWebhooks");
const schedulePayload = async (secretKey, triggerEvent, createdAt, webhook, data) => {
  await index$1.tasker.create("sendWebhook", JSON.stringify({ secretKey, triggerEvent, createdAt, webhook, data }));
  return {
    ok: true,
    status: 200,
    message: "Webhook scheduled successfully"
  };
};
const schedulePayload$1 = schedulePayload;
const sendOrSchedulePayload = async (...args) => {
  if (process.env.TASKER_ENABLE_WEBHOOKS === "1")
    return schedulePayload$1(...args);
  return sendPayload$1.sendPayload(...args);
};
const sendPayload = sendOrSchedulePayload;
const getAllCredentialsIncludeServiceAccountKey = async (user$1, eventType) => {
  let allCredentials = user$1.credentials;
  if (eventType?.team?.id) {
    const teamCredentialsQuery = await index.prisma.credential.findMany({
      where: {
        teamId: eventType.team.id
      },
      select: index.credentialForCalendarServiceSelect
    });
    allCredentials.push(...teamCredentialsQuery);
  }
  if (eventType?.parentId) {
    const teamCredentialsQuery = await index.prisma.team.findFirst({
      where: {
        eventTypes: {
          some: {
            id: eventType.parentId
          }
        }
      },
      select: {
        credentials: {
          select: index.credentialForCalendarServiceSelect
        }
      }
    });
    if (teamCredentialsQuery?.credentials) {
      allCredentials.push(...teamCredentialsQuery?.credentials);
    }
  }
  const { profile } = await new user.UserRepository(index.prisma).enrichUserWithItsProfile({
    user: user$1
  });
  if (profile?.organizationId) {
    const org = await index.prisma.team.findUnique({
      where: {
        id: profile.organizationId
      },
      select: {
        credentials: {
          select: index.credentialForCalendarServiceSelect
        }
      }
    });
    if (org?.credentials) {
      allCredentials.push(...org.credentials);
    }
  }
  const eventTypeAppMetadata = index.eventTypeAppMetadataOptionalSchema.parse(eventType?.metadata?.apps);
  const eventTypeCrmCredentials = {};
  for (const appKey in eventTypeAppMetadata) {
    const app = eventTypeAppMetadata[appKey];
    if (app.appCategories && app.appCategories.some((category) => category === "crm")) {
      eventTypeCrmCredentials[app.credentialId] = {
        enabled: app.enabled
      };
    }
  }
  allCredentials = allCredentials.filter((credential2) => {
    if (!credential2.type.includes("_crm") && !credential2.type.includes("_other_calendar")) {
      return credential2;
    }
    if (eventTypeCrmCredentials[credential2.id]) {
      if (eventTypeCrmCredentials[credential2.id].enabled) {
        return credential2;
      }
    } else {
      if (credential2.type.includes("_other_calendar") && (credential2.userId === eventType?.userId || credential2.teamId === eventType?.team?.id || credential2.teamId === eventType?.team?.parentId || credential2.teamId === profile?.organizationId)) {
        return credential2;
      }
    }
  });
  const userWithDelegationCredentials = await credential.enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
    user: { ...user$1, credentials: allCredentials }
  });
  return userWithDelegationCredentials.credentials;
};
const log$1 = index.logger.getSubLogger({ prefix: ["[scheduleMandatoryReminder]"] });
async function _scheduleMandatoryReminder({
  evt,
  workflows,
  requiresConfirmation,
  hideBranding,
  seatReferenceUid,
  isPlatformNoEmail = false,
  isDryRun = false
}) {
  if (isDryRun)
    return;
  if (isPlatformNoEmail)
    return;
  try {
    const hasExistingWorkflow = workflows.some((workflow) => {
      return workflow.trigger === index.WorkflowTriggerEvents.BEFORE_EVENT && (workflow.time !== null && workflow.time <= 12 && workflow.timeUnit === index.TimeUnit.HOUR || workflow.time !== null && workflow.time <= 720 && workflow.timeUnit === index.TimeUnit.MINUTE) && workflow.steps.some((step) => step?.action === index.WorkflowActions.EMAIL_ATTENDEE);
    });
    if (!hasExistingWorkflow && evt.attendees.some((attendee) => attendee.email.includes("@gmail.com")) && !requiresConfirmation) {
      try {
        const filteredAttendees = evt.attendees?.filter((attendee) => attendee.email.includes("@gmail.com")) || [];
        await index$1.scheduleEmailReminder({
          evt,
          triggerEvent: index.WorkflowTriggerEvents.BEFORE_EVENT,
          action: index.WorkflowActions.EMAIL_ATTENDEE,
          timeSpan: {
            time: 1,
            timeUnit: index.TimeUnit.HOUR
          },
          sendTo: filteredAttendees.map((attendee) => attendee.email),
          template: index.WorkflowTemplates.REMINDER,
          hideBranding,
          seatReferenceUid,
          includeCalendarEvent: false,
          isMandatoryReminder: true,
          // Template is fixed so we don't have to verify
          verifiedAt: /* @__PURE__ */ new Date(),
          userId: evt.organizer.id
        });
      } catch (error) {
        log$1.error("Error while scheduling mandatory reminders", JSON.stringify({ error }));
      }
    }
  } catch (error) {
    log$1.error("Error while scheduling mandatory reminders", JSON.stringify({ error }));
  }
}
const scheduleMandatoryReminder = index.withReporting(
  _scheduleMandatoryReminder,
  "scheduleMandatoryReminder"
);
const _scheduleNoShowTriggers = async (args) => {
  const {
    booking,
    triggerForUser,
    organizerUser,
    eventTypeId,
    teamId,
    orgId,
    oAuthClientId,
    isDryRun = false
  } = args;
  const isCalVideoLocation = booking.location === locations.DailyLocationType || booking.location?.trim() === "";
  if (isDryRun || !isCalVideoLocation)
    return;
  const noShowPromises = [];
  const subscribersHostsNoShowStarted = await getWebhooks$1({
    userId: triggerForUser ? organizerUser.id : null,
    eventTypeId,
    triggerEvent: index.WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW,
    teamId,
    orgId,
    oAuthClientId
  });
  noShowPromises.push(
    ...subscribersHostsNoShowStarted.map((webhook) => {
      if (booking?.startTime && webhook.time && webhook.timeUnit) {
        const scheduledAt = dayjs(booking.startTime).add(webhook.time, webhook.timeUnit.toLowerCase()).toDate();
        return index$1.tasker.create(
          "triggerHostNoShowWebhook",
          {
            triggerEvent: index.WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW,
            bookingId: booking.id,
            // Prevents null values from being serialized
            webhook: { ...webhook, time: webhook.time, timeUnit: webhook.timeUnit }
          },
          { scheduledAt }
        );
      }
      return Promise.resolve();
    })
  );
  const subscribersGuestsNoShowStarted = await getWebhooks$1({
    userId: triggerForUser ? organizerUser.id : null,
    eventTypeId,
    triggerEvent: index.WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW,
    teamId,
    orgId,
    oAuthClientId
  });
  noShowPromises.push(
    ...subscribersGuestsNoShowStarted.map((webhook) => {
      if (booking?.startTime && webhook.time && webhook.timeUnit) {
        const scheduledAt = dayjs(booking.startTime).add(webhook.time, webhook.timeUnit.toLowerCase()).toDate();
        return index$1.tasker.create(
          "triggerGuestNoShowWebhook",
          {
            triggerEvent: index.WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW,
            bookingId: booking.id,
            // Prevents null values from being serialized
            webhook: { ...webhook, time: webhook.time, timeUnit: webhook.timeUnit }
          },
          { scheduledAt }
        );
      }
      return Promise.resolve();
    })
  );
  await Promise.all(noShowPromises);
};
const scheduleNoShowTriggers = index.withReporting(_scheduleNoShowTriggers, "scheduleNoShowTriggers");
const log = index.logger.getSubLogger({ prefix: ["[handleConfirmation] book:user"] });
async function handleConfirmation(args) {
  const {
    user: user2,
    evt,
    recurringEventId,
    prisma,
    bookingId,
    booking,
    paid,
    emailsEnabled = true,
    platformClientParams
  } = args;
  const eventType = booking.eventType;
  const eventTypeMetadata = index.EventTypeMetaDataSchema.parse(eventType?.metadata || {});
  const apps = index.eventTypeAppMetadataOptionalSchema.parse(eventTypeMetadata?.apps);
  const eventManager = new allowDisablingStandardEmails.EventManager(user2, apps);
  const areCalendarEventsEnabled = platformClientParams?.areCalendarEventsEnabled ?? true;
  const scheduleResult = areCalendarEventsEnabled ? await eventManager.create(evt) : allowDisablingStandardEmails.placeholderCreatedEvent;
  const results = scheduleResult.results;
  const metadata = {};
  const workflows = await index$1.getAllWorkflowsFromEventType(eventType, booking.userId);
  if (results.length > 0 && results.every((res) => !res.success)) {
    const error = {
      errorCode: "BookingCreatingMeetingFailed",
      message: "Booking failed"
    };
    log.error(`Booking ${user2.username} failed`, index.safeStringify({ error, results }));
  } else {
    if (results.length) {
      metadata.hangoutLink = results[0].createdEvent?.hangoutLink;
      metadata.conferenceData = results[0].createdEvent?.conferenceData;
      metadata.entryPoints = results[0].createdEvent?.entryPoints;
    }
    try {
      const eventType2 = booking.eventType;
      let isHostConfirmationEmailsDisabled = false;
      let isAttendeeConfirmationEmailDisabled = false;
      if (workflows) {
        isHostConfirmationEmailsDisabled = eventTypeMetadata?.disableStandardEmails?.confirmation?.host || false;
        isAttendeeConfirmationEmailDisabled = eventTypeMetadata?.disableStandardEmails?.confirmation?.attendee || false;
        if (isHostConfirmationEmailsDisabled) {
          isHostConfirmationEmailsDisabled = allowDisablingStandardEmails.allowDisablingHostConfirmationEmails(workflows);
        }
        if (isAttendeeConfirmationEmailDisabled) {
          isAttendeeConfirmationEmailDisabled = allowDisablingStandardEmails.allowDisablingAttendeeConfirmationEmails(workflows);
        }
      }
      if (emailsEnabled) {
        await index$1.sendScheduledEmailsAndSMS(
          { ...evt, additionalInformation: metadata },
          void 0,
          isHostConfirmationEmailsDisabled,
          isAttendeeConfirmationEmailDisabled,
          eventTypeMetadata
        );
      }
    } catch (error) {
      log.error(error);
    }
  }
  let updatedBookings = [];
  const videoCallUrl = metadata.hangoutLink ? metadata.hangoutLink : evt.videoCallData?.url || "";
  const meetingUrl = CalEventParser.getVideoCallUrlFromCalEvent(evt) || videoCallUrl;
  if (recurringEventId) {
    const unconfirmedRecurringBookings = await prisma.booking.findMany({
      where: {
        recurringEventId,
        status: index.BookingStatus.PENDING
      }
    });
    const updateBookingsPromise = unconfirmedRecurringBookings.map(
      (recurringBooking) => prisma.booking.update({
        where: {
          id: recurringBooking.id
        },
        data: {
          status: index.BookingStatus.ACCEPTED,
          references: {
            create: scheduleResult.referencesToCreate
          },
          paid,
          metadata: {
            ...typeof recurringBooking.metadata === "object" ? recurringBooking.metadata : {},
            videoCallUrl: meetingUrl
          }
        },
        select: {
          eventType: {
            select: {
              slug: true,
              bookingFields: true,
              schedulingType: true,
              hosts: {
                select: {
                  user: {
                    select: {
                      email: true,
                      destinationCalendar: {
                        select: {
                          primaryEmail: true
                        }
                      }
                    }
                  }
                }
              },
              owner: {
                select: {
                  hideBranding: true
                }
              }
            }
          },
          description: true,
          cancellationReason: true,
          attendees: true,
          responses: true,
          location: true,
          title: true,
          uid: true,
          startTime: true,
          metadata: true,
          endTime: true,
          smsReminderNumber: true,
          customInputs: true,
          id: true
        }
      })
    );
    const updatedBookingsResult = await Promise.all(updateBookingsPromise);
    updatedBookings = updatedBookings.concat(updatedBookingsResult);
  } else {
    const updatedBooking = await prisma.booking.update({
      where: {
        id: bookingId
      },
      data: {
        status: index.BookingStatus.ACCEPTED,
        references: {
          create: scheduleResult.referencesToCreate
        },
        metadata: {
          ...typeof booking.metadata === "object" ? booking.metadata : {},
          videoCallUrl: meetingUrl
        }
      },
      select: {
        eventType: {
          select: {
            slug: true,
            bookingFields: true,
            schedulingType: true,
            owner: {
              select: {
                hideBranding: true
              }
            },
            hosts: {
              select: {
                user: {
                  select: {
                    email: true,
                    destinationCalendar: {
                      select: {
                        primaryEmail: true
                      }
                    }
                  }
                }
              }
            }
          }
        },
        uid: true,
        startTime: true,
        responses: true,
        title: true,
        metadata: true,
        cancellationReason: true,
        endTime: true,
        smsReminderNumber: true,
        description: true,
        attendees: true,
        location: true,
        customInputs: true,
        id: true
      }
    });
    updatedBookings.push(updatedBooking);
  }
  const teamId = await index$1.getTeamIdFromEventType({
    eventType: {
      team: { id: eventType?.teamId ?? null },
      parentId: eventType?.parentId ?? null
    }
  });
  const triggerForUser = !teamId || teamId && eventType?.parentId;
  const userId = triggerForUser ? booking.userId : null;
  const orgId = await index$1.getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
  const bookerUrl = await index$1.getBookerBaseUrl(orgId ?? null);
  try {
    for (let index2 = 0; index2 < updatedBookings.length; index2++) {
      const eventTypeSlug = updatedBookings[index2].eventType?.slug || "";
      const evtOfBooking = {
        ...evt,
        rescheduleReason: updatedBookings[index2].cancellationReason || null,
        metadata: { videoCallUrl: meetingUrl },
        eventType: {
          slug: eventTypeSlug,
          schedulingType: updatedBookings[index2].eventType?.schedulingType,
          hosts: updatedBookings[index2].eventType?.hosts
        },
        bookerUrl
      };
      evtOfBooking.startTime = updatedBookings[index2].startTime.toISOString();
      evtOfBooking.endTime = updatedBookings[index2].endTime.toISOString();
      evtOfBooking.uid = updatedBookings[index2].uid;
      const isFirstBooking = index2 === 0;
      if (!eventTypeMetadata?.disableStandardEmails?.all?.attendee) {
        await scheduleMandatoryReminder({
          evt: evtOfBooking,
          workflows,
          requiresConfirmation: false,
          hideBranding: !!updatedBookings[index2].eventType?.owner?.hideBranding,
          seatReferenceUid: evt.attendeeSeatId,
          isPlatformNoEmail: !emailsEnabled && Boolean(platformClientParams?.platformClientId)
        });
      }
      await reminderScheduler.scheduleWorkflowReminders({
        workflows,
        smsReminderNumber: updatedBookings[index2].smsReminderNumber,
        calendarEvent: evtOfBooking,
        isFirstRecurringEvent: isFirstBooking,
        hideBranding: !!updatedBookings[index2].eventType?.owner?.hideBranding
      });
    }
  } catch (error) {
    console.error(error);
  }
  try {
    const subscribersBookingCreated = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: index.WebhookTriggerEvents.BOOKING_CREATED,
      teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const subscribersMeetingStarted = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: index.WebhookTriggerEvents.MEETING_STARTED,
      teamId: eventType?.teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const subscribersMeetingEnded = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: index.WebhookTriggerEvents.MEETING_ENDED,
      teamId: eventType?.teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const scheduleTriggerPromises = [];
    const updatedBookingsWithCalEventResponses = updatedBookings.map((booking2) => {
      return {
        ...booking2,
        ...getCalEventResponses.getCalEventResponses({
          bookingFields: booking2.eventType?.bookingFields ?? null,
          booking: booking2
        })
      };
    });
    subscribersMeetingStarted.forEach((subscriber) => {
      updatedBookingsWithCalEventResponses.forEach((booking2) => {
        scheduleTriggerPromises.push(
          scheduleTrigger.scheduleTrigger({
            booking: booking2,
            subscriberUrl: subscriber.subscriberUrl,
            subscriber,
            triggerEvent: index.WebhookTriggerEvents.MEETING_STARTED
          })
        );
      });
    });
    subscribersMeetingEnded.forEach((subscriber) => {
      updatedBookingsWithCalEventResponses.forEach((booking2) => {
        scheduleTriggerPromises.push(
          scheduleTrigger.scheduleTrigger({
            booking: booking2,
            subscriberUrl: subscriber.subscriberUrl,
            subscriber,
            triggerEvent: index.WebhookTriggerEvents.MEETING_ENDED
          })
        );
      });
    });
    await Promise.all(scheduleTriggerPromises);
    await scheduleNoShowTriggers({
      booking: {
        startTime: booking.startTime,
        id: booking.id,
        location: booking.location
      },
      triggerForUser,
      organizerUser: { id: booking.userId },
      eventTypeId: booking.eventTypeId,
      teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const eventTypeInfo = {
      eventTitle: eventType?.title,
      eventDescription: eventType?.description,
      requiresConfirmation: eventType?.requiresConfirmation || null,
      price: eventType?.price,
      currency: eventType?.currency,
      length: eventType?.length
    };
    const payload = {
      ...evt,
      ...eventTypeInfo,
      bookingId,
      eventTypeId: eventType?.id,
      status: "ACCEPTED",
      smsReminderNumber: booking.smsReminderNumber || void 0,
      metadata: meetingUrl ? { videoCallUrl: meetingUrl } : void 0,
      ...platformClientParams ? platformClientParams : {}
    };
    const promises = subscribersBookingCreated.map(
      (sub) => sendPayload(
        sub.secret,
        index.WebhookTriggerEvents.BOOKING_CREATED,
        (/* @__PURE__ */ new Date()).toISOString(),
        sub,
        payload
      ).catch((e) => {
        log.error(
          `Error executing webhook for event: ${index.WebhookTriggerEvents.BOOKING_CREATED}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}, platformClientId: ${platformClientParams?.platformClientId}`,
          index.safeStringify(e)
        );
      })
    );
    await Promise.all(promises);
    if (paid) {
      let paymentExternalId;
      const subscriberMeetingPaid = await getWebhooks$1({
        userId,
        eventTypeId: booking.eventTypeId,
        triggerEvent: index.WebhookTriggerEvents.BOOKING_PAID,
        teamId: eventType?.teamId,
        orgId,
        oAuthClientId: platformClientParams?.platformClientId
      });
      const bookingWithPayment = await prisma.booking.findUnique({
        where: {
          id: bookingId
        },
        select: {
          payment: {
            select: {
              id: true,
              success: true,
              externalId: true
            }
          }
        }
      });
      const successPayment = bookingWithPayment?.payment?.find((item) => item.success);
      if (successPayment) {
        paymentExternalId = successPayment.externalId;
      }
      const paymentMetadata = {
        identifier: "cal.com",
        bookingId,
        eventTypeId: eventType?.id,
        bookerEmail: evt.attendees[0].email,
        eventTitle: eventType?.title,
        externalId: paymentExternalId
      };
      payload.paymentId = bookingWithPayment?.payment?.[0].id;
      payload.metadata = {
        ...paid ? paymentMetadata : {}
      };
      const bookingPaidSubscribers = subscriberMeetingPaid.map(
        (sub) => sendPayload(
          sub.secret,
          index.WebhookTriggerEvents.BOOKING_PAID,
          (/* @__PURE__ */ new Date()).toISOString(),
          sub,
          payload
        ).catch((e) => {
          log.error(
            `Error executing webhook for event: ${index.WebhookTriggerEvents.BOOKING_PAID}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
            index.safeStringify(e)
          );
        })
      );
      Promise.all(bookingPaidSubscribers);
    }
  } catch (error) {
    console.error(error);
  }
}
exports.getAllCredentialsIncludeServiceAccountKey = getAllCredentialsIncludeServiceAccountKey;
exports.getWebhooks = getWebhooks$1;
exports.handleConfirmation = handleConfirmation;
exports.scheduleMandatoryReminder = scheduleMandatoryReminder;
exports.scheduleNoShowTriggers = scheduleNoShowTriggers;
exports.sendPayload = sendPayload;
