import { e as enrichUserWithDelegationCredentialsIncludeServiceAccountKey } from "./credential-7rcNyyEv.js";
import { f as withReporting, p as prisma, c as credentialForCalendarServiceSelect, U as UserRepository, aO as eventTypeAppMetadataOptionalSchema, l as logger, W as WorkflowTriggerEvents, aB as TimeUnit, q as WorkflowActions, ad as WorkflowTemplates, Y as WebhookTriggerEvents, E as EventTypeMetaDataSchema, b as safeStringify, B as BookingStatus } from "./user--mpkKOwW.js";
import { an as tasker, a8 as scheduleEmailReminder, ar as getAllWorkflowsFromEventType, s as sendScheduledEmailsAndSMS, as as getTeamIdFromEventType, at as getOrgIdFromMemberOrTeamId, au as getBookerBaseUrl } from "./email-manager-RBMYQEU9.js";
import { E as EventManager, p as placeholderCreatedEvent, a as allowDisablingHostConfirmationEmails, b as allowDisablingAttendeeConfirmationEmails } from "./allowDisablingStandardEmails-jEot2g-l.js";
import { s as scheduleWorkflowReminders } from "./reminderScheduler-FQaM7SQ1.js";
import { s as scheduleTrigger } from "./scheduleTrigger-NXcg5eDS.js";
import { s as sendPayload$1 } from "./sendPayload-94-N-Ckq.js";
import { D as DailyLocationType, C as getVideoCallUrlFromCalEvent } from "./CalEventParser-ZzmnrFso.js";
import { g as getCalEventResponses } from "./getCalEventResponses-jpUI0Z_v.js";
import "./index-rbwdGzy0.js";
import dayjs from "dayjs";
const webhookSelect = {
  id: true,
  subscriberUrl: true,
  payloadTemplate: true,
  appId: true,
  secret: true,
  time: true,
  timeUnit: true,
  eventTriggers: true
};
const getWebhooks = async (options, prisma$1 = 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$1.eventType.findFirst({
    where: {
      id: eventTypeId,
      parentId: {
        not: null
      }
    },
    select: {
      parentId: true
    }
  });
  const managedParentEventTypeId = managedChildEventType?.parentId ?? 0;
  const allWebhooks = await prisma$1.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 = withReporting(getWebhooks, "getWebhooks");
const schedulePayload = async (secretKey, triggerEvent, createdAt, webhook, data) => {
  await 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(...args);
};
const sendPayload = sendOrSchedulePayload;
const getAllCredentialsIncludeServiceAccountKey = async (user, eventType) => {
  let allCredentials = user.credentials;
  if (eventType?.team?.id) {
    const teamCredentialsQuery = await prisma.credential.findMany({
      where: {
        teamId: eventType.team.id
      },
      select: credentialForCalendarServiceSelect
    });
    allCredentials.push(...teamCredentialsQuery);
  }
  if (eventType?.parentId) {
    const teamCredentialsQuery = await prisma.team.findFirst({
      where: {
        eventTypes: {
          some: {
            id: eventType.parentId
          }
        }
      },
      select: {
        credentials: {
          select: credentialForCalendarServiceSelect
        }
      }
    });
    if (teamCredentialsQuery?.credentials) {
      allCredentials.push(...teamCredentialsQuery?.credentials);
    }
  }
  const { profile } = await new UserRepository(prisma).enrichUserWithItsProfile({
    user
  });
  if (profile?.organizationId) {
    const org = await prisma.team.findUnique({
      where: {
        id: profile.organizationId
      },
      select: {
        credentials: {
          select: credentialForCalendarServiceSelect
        }
      }
    });
    if (org?.credentials) {
      allCredentials.push(...org.credentials);
    }
  }
  const eventTypeAppMetadata = 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((credential) => {
    if (!credential.type.includes("_crm") && !credential.type.includes("_other_calendar")) {
      return credential;
    }
    if (eventTypeCrmCredentials[credential.id]) {
      if (eventTypeCrmCredentials[credential.id].enabled) {
        return credential;
      }
    } else {
      if (credential.type.includes("_other_calendar") && (credential.userId === eventType?.userId || credential.teamId === eventType?.team?.id || credential.teamId === eventType?.team?.parentId || credential.teamId === profile?.organizationId)) {
        return credential;
      }
    }
  });
  const userWithDelegationCredentials = await enrichUserWithDelegationCredentialsIncludeServiceAccountKey({
    user: { ...user, credentials: allCredentials }
  });
  return userWithDelegationCredentials.credentials;
};
const log$1 = 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 === WorkflowTriggerEvents.BEFORE_EVENT && (workflow.time !== null && workflow.time <= 12 && workflow.timeUnit === TimeUnit.HOUR || workflow.time !== null && workflow.time <= 720 && workflow.timeUnit === TimeUnit.MINUTE) && workflow.steps.some((step) => step?.action === 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 scheduleEmailReminder({
          evt,
          triggerEvent: WorkflowTriggerEvents.BEFORE_EVENT,
          action: WorkflowActions.EMAIL_ATTENDEE,
          timeSpan: {
            time: 1,
            timeUnit: TimeUnit.HOUR
          },
          sendTo: filteredAttendees.map((attendee) => attendee.email),
          template: 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 = withReporting(
  _scheduleMandatoryReminder,
  "scheduleMandatoryReminder"
);
const _scheduleNoShowTriggers = async (args) => {
  const {
    booking,
    triggerForUser,
    organizerUser,
    eventTypeId,
    teamId,
    orgId,
    oAuthClientId,
    isDryRun = false
  } = args;
  const isCalVideoLocation = booking.location === DailyLocationType || booking.location?.trim() === "";
  if (isDryRun || !isCalVideoLocation)
    return;
  const noShowPromises = [];
  const subscribersHostsNoShowStarted = await getWebhooks$1({
    userId: triggerForUser ? organizerUser.id : null,
    eventTypeId,
    triggerEvent: 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 tasker.create(
          "triggerHostNoShowWebhook",
          {
            triggerEvent: 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: 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 tasker.create(
          "triggerGuestNoShowWebhook",
          {
            triggerEvent: 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 = withReporting(_scheduleNoShowTriggers, "scheduleNoShowTriggers");
const log = logger.getSubLogger({ prefix: ["[handleConfirmation] book:user"] });
async function handleConfirmation(args) {
  const {
    user,
    evt,
    recurringEventId,
    prisma: prisma2,
    bookingId,
    booking,
    paid,
    emailsEnabled = true,
    platformClientParams
  } = args;
  const eventType = booking.eventType;
  const eventTypeMetadata = EventTypeMetaDataSchema.parse(eventType?.metadata || {});
  const apps = eventTypeAppMetadataOptionalSchema.parse(eventTypeMetadata?.apps);
  const eventManager = new EventManager(user, apps);
  const areCalendarEventsEnabled = platformClientParams?.areCalendarEventsEnabled ?? true;
  const scheduleResult = areCalendarEventsEnabled ? await eventManager.create(evt) : placeholderCreatedEvent;
  const results = scheduleResult.results;
  const metadata = {};
  const workflows = await getAllWorkflowsFromEventType(eventType, booking.userId);
  if (results.length > 0 && results.every((res) => !res.success)) {
    const error = {
      errorCode: "BookingCreatingMeetingFailed",
      message: "Booking failed"
    };
    log.error(`Booking ${user.username} failed`, 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 = allowDisablingHostConfirmationEmails(workflows);
        }
        if (isAttendeeConfirmationEmailDisabled) {
          isAttendeeConfirmationEmailDisabled = allowDisablingAttendeeConfirmationEmails(workflows);
        }
      }
      if (emailsEnabled) {
        await 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 = getVideoCallUrlFromCalEvent(evt) || videoCallUrl;
  if (recurringEventId) {
    const unconfirmedRecurringBookings = await prisma2.booking.findMany({
      where: {
        recurringEventId,
        status: BookingStatus.PENDING
      }
    });
    const updateBookingsPromise = unconfirmedRecurringBookings.map(
      (recurringBooking) => prisma2.booking.update({
        where: {
          id: recurringBooking.id
        },
        data: {
          status: 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 prisma2.booking.update({
      where: {
        id: bookingId
      },
      data: {
        status: 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 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 getOrgIdFromMemberOrTeamId({ memberId: userId, teamId });
  const bookerUrl = await getBookerBaseUrl(orgId ?? null);
  try {
    for (let index = 0; index < updatedBookings.length; index++) {
      const eventTypeSlug = updatedBookings[index].eventType?.slug || "";
      const evtOfBooking = {
        ...evt,
        rescheduleReason: updatedBookings[index].cancellationReason || null,
        metadata: { videoCallUrl: meetingUrl },
        eventType: {
          slug: eventTypeSlug,
          schedulingType: updatedBookings[index].eventType?.schedulingType,
          hosts: updatedBookings[index].eventType?.hosts
        },
        bookerUrl
      };
      evtOfBooking.startTime = updatedBookings[index].startTime.toISOString();
      evtOfBooking.endTime = updatedBookings[index].endTime.toISOString();
      evtOfBooking.uid = updatedBookings[index].uid;
      const isFirstBooking = index === 0;
      if (!eventTypeMetadata?.disableStandardEmails?.all?.attendee) {
        await scheduleMandatoryReminder({
          evt: evtOfBooking,
          workflows,
          requiresConfirmation: false,
          hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding,
          seatReferenceUid: evt.attendeeSeatId,
          isPlatformNoEmail: !emailsEnabled && Boolean(platformClientParams?.platformClientId)
        });
      }
      await scheduleWorkflowReminders({
        workflows,
        smsReminderNumber: updatedBookings[index].smsReminderNumber,
        calendarEvent: evtOfBooking,
        isFirstRecurringEvent: isFirstBooking,
        hideBranding: !!updatedBookings[index].eventType?.owner?.hideBranding
      });
    }
  } catch (error) {
    console.error(error);
  }
  try {
    const subscribersBookingCreated = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: WebhookTriggerEvents.BOOKING_CREATED,
      teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const subscribersMeetingStarted = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: WebhookTriggerEvents.MEETING_STARTED,
      teamId: eventType?.teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const subscribersMeetingEnded = await getWebhooks$1({
      userId,
      eventTypeId: booking.eventTypeId,
      triggerEvent: WebhookTriggerEvents.MEETING_ENDED,
      teamId: eventType?.teamId,
      orgId,
      oAuthClientId: platformClientParams?.platformClientId
    });
    const scheduleTriggerPromises = [];
    const updatedBookingsWithCalEventResponses = updatedBookings.map((booking2) => {
      return {
        ...booking2,
        ...getCalEventResponses({
          bookingFields: booking2.eventType?.bookingFields ?? null,
          booking: booking2
        })
      };
    });
    subscribersMeetingStarted.forEach((subscriber) => {
      updatedBookingsWithCalEventResponses.forEach((booking2) => {
        scheduleTriggerPromises.push(
          scheduleTrigger({
            booking: booking2,
            subscriberUrl: subscriber.subscriberUrl,
            subscriber,
            triggerEvent: WebhookTriggerEvents.MEETING_STARTED
          })
        );
      });
    });
    subscribersMeetingEnded.forEach((subscriber) => {
      updatedBookingsWithCalEventResponses.forEach((booking2) => {
        scheduleTriggerPromises.push(
          scheduleTrigger({
            booking: booking2,
            subscriberUrl: subscriber.subscriberUrl,
            subscriber,
            triggerEvent: 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,
        WebhookTriggerEvents.BOOKING_CREATED,
        (/* @__PURE__ */ new Date()).toISOString(),
        sub,
        payload
      ).catch((e) => {
        log.error(
          `Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_CREATED}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}, platformClientId: ${platformClientParams?.platformClientId}`,
          safeStringify(e)
        );
      })
    );
    await Promise.all(promises);
    if (paid) {
      let paymentExternalId;
      const subscriberMeetingPaid = await getWebhooks$1({
        userId,
        eventTypeId: booking.eventTypeId,
        triggerEvent: WebhookTriggerEvents.BOOKING_PAID,
        teamId: eventType?.teamId,
        orgId,
        oAuthClientId: platformClientParams?.platformClientId
      });
      const bookingWithPayment = await prisma2.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,
          WebhookTriggerEvents.BOOKING_PAID,
          (/* @__PURE__ */ new Date()).toISOString(),
          sub,
          payload
        ).catch((e) => {
          log.error(
            `Error executing webhook for event: ${WebhookTriggerEvents.BOOKING_PAID}, URL: ${sub.subscriberUrl}, bookingId: ${evt.bookingId}, bookingUid: ${evt.uid}`,
            safeStringify(e)
          );
        })
      );
      Promise.all(bookingPaidSubscribers);
    }
  } catch (error) {
    console.error(error);
  }
}
export {
  getAllCredentialsIncludeServiceAccountKey as a,
  scheduleMandatoryReminder as b,
  scheduleNoShowTriggers as c,
  getWebhooks$1 as g,
  handleConfirmation as h,
  sendPayload as s
};
