"use strict";
const index = require("./index-QSf6WJj0.cjs");
const sendPayload = require("./sendPayload-UqEOpTQL.cjs");
const indexBrowser = require("./index-browser-RtwB1hqI.cjs");
const httpError = require("./http-error-mkY8Ke7V.cjs");
const dailyApiFetcher = require("./dailyApiFetcher-6ytV3FS6.cjs");
const z = require("zod");
const dayjs = require("dayjs");
const log$1 = index.logger.getSubLogger({ prefix: ["trigger-no-show-handler"] });
const getBooking = async (bookingId) => {
  const booking = await index.prisma.booking.findUniqueOrThrow({
    where: {
      id: bookingId
    },
    select: {
      ...index.bookingMinimalSelect,
      uid: true,
      location: true,
      status: true,
      isRecorded: true,
      eventTypeId: true,
      references: true,
      fromReschedule: true,
      eventType: {
        select: {
          id: true,
          teamId: true,
          parentId: true,
          hosts: {
            select: {
              userId: true,
              user: {
                select: {
                  email: true
                }
              }
            }
          },
          users: {
            select: {
              id: true,
              email: true
            }
          }
        }
      },
      user: {
        select: {
          id: true,
          timeZone: true,
          email: true,
          name: true,
          locale: true,
          destinationCalendar: true
        }
      }
    }
  });
  if (!booking) {
    log$1.error(
      "Couldn't find Booking Id:",
      indexBrowser.safeStringify({
        bookingId
      })
    );
    throw new httpError.HttpError({
      message: `Booking of id ${bookingId} does not exist or does not contain daily video as location`,
      statusCode: 404
    });
  }
  return booking;
};
const TIME_UNIT = [index.TimeUnit.DAY, index.TimeUnit.HOUR, index.TimeUnit.MINUTE];
const commonSchema = z.z.object({
  triggerEvent: z.z.enum([
    index.WebhookTriggerEvents.AFTER_HOSTS_CAL_VIDEO_NO_SHOW,
    index.WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW
  ]),
  bookingId: z.z.number()
});
const ZWebhook = z.z.object({
  id: z.z.string(),
  subscriberUrl: z.z.string().url(),
  appId: z.z.string().nullable(),
  secret: z.z.string().nullable(),
  time: z.z.number(),
  timeUnit: z.z.enum(TIME_UNIT),
  eventTriggers: z.z.array(z.z.string()),
  payloadTemplate: z.z.string().nullable()
});
const triggerNoShowPayloadSchema = z.z.object({
  total_count: z.z.number(),
  data: z.z.array(
    z.z.object({
      id: z.z.string(),
      room: z.z.string(),
      start_time: z.z.number(),
      duration: z.z.number(),
      max_participants: z.z.number(),
      participants: z.z.array(
        z.z.object({
          user_id: z.z.string().nullable(),
          participant_id: z.z.string(),
          user_name: z.z.string(),
          join_time: z.z.number(),
          duration: z.z.number()
        })
      )
    }).passthrough()
  )
});
const ZSendNoShowWebhookPayloadSchema = commonSchema.extend({
  webhook: ZWebhook
});
const getMeetingSessionsFromRoomName = async (roomName) => {
  return dailyApiFetcher.fetcher(`/meetings?room=${roomName}`).then(triggerNoShowPayloadSchema.parse);
};
function getHosts(booking) {
  const hostMap = /* @__PURE__ */ new Map();
  const addHost = (id, email) => {
    if (!hostMap.has(id)) {
      hostMap.set(id, { id, email });
    }
  };
  booking?.eventType?.hosts?.forEach((host) => addHost(host.userId, host.user.email));
  booking?.eventType?.users?.forEach((user) => addHost(user.id, user.email));
  if (booking?.user?.id && booking?.user?.email) {
    addHost(booking.user.id, booking.user.email);
  }
  const attendeeEmails = new Set(booking.attendees?.map((attendee) => attendee.email));
  const filteredHosts = Array.from(hostMap.values()).filter(
    (host) => attendeeEmails.has(host.email) || host.id === booking.user?.id
  );
  return filteredHosts;
}
function sendWebhookPayload(webhook, triggerEvent, booking, maxStartTime, participants, originalRescheduledBooking, hostEmail) {
  const maxStartTimeHumanReadable = dayjs.unix(maxStartTime).format("YYYY-MM-DD HH:mm:ss Z");
  return sendPayload.sendGenericWebhookPayload({
    secretKey: webhook.secret,
    triggerEvent,
    createdAt: (/* @__PURE__ */ new Date()).toISOString(),
    webhook,
    data: {
      title: booking.title,
      bookingId: booking.id,
      bookingUid: booking.uid,
      startTime: booking.startTime,
      attendees: booking.attendees,
      endTime: booking.endTime,
      participants,
      ...!!hostEmail ? { hostEmail } : {},
      ...originalRescheduledBooking ? { rescheduledBy: originalRescheduledBooking.rescheduledBy } : {},
      eventType: {
        ...booking.eventType,
        id: booking.eventTypeId,
        hosts: void 0,
        users: void 0
      },
      webhook: {
        ...webhook,
        secret: void 0
      },
      message: triggerEvent === index.WebhookTriggerEvents.AFTER_GUESTS_CAL_VIDEO_NO_SHOW ? `Guest didn't join the call or didn't join before ${maxStartTimeHumanReadable}` : `Host with email ${hostEmail} didn't join the call or didn't join before ${maxStartTimeHumanReadable}`
    }
  }).catch((e) => {
    console.error(
      `Error executing webhook for event: ${triggerEvent}, URL: ${webhook.subscriberUrl}`,
      webhook,
      e
    );
  });
}
function calculateMaxStartTime(startTime, time, timeUnit) {
  return dayjs(startTime).add(time, timeUnit.toLowerCase()).unix();
}
function checkIfUserJoinedTheCall(userId, allParticipants) {
  return allParticipants.some(
    (participant) => participant.user_id && parseInt(participant.user_id) === userId
  );
}
const getUserById = async (userId) => {
  return index.prisma.user.findUnique({
    where: { id: userId }
  });
};
async function getParticipantsWithEmail(allParticipants) {
  const participantsWithEmail = await Promise.all(
    allParticipants.map(async (participant) => {
      if (!participant.user_id)
        return participant;
      const user = await getUserById(parseInt(participant.user_id));
      return { ...participant, email: user?.email };
    })
  );
  return participantsWithEmail;
}
const log = index.logger.getSubLogger({ prefix: ["triggerNoShowTask"] });
const prepareNoShowTrigger = async (payload) => {
  const { bookingId, webhook } = ZSendNoShowWebhookPayloadSchema.parse(JSON.parse(payload));
  const booking = await getBooking(bookingId);
  let originalRescheduledBooking = null;
  if (booking.fromReschedule) {
    originalRescheduledBooking = await index.prisma.booking.findFirst({
      where: {
        uid: booking.fromReschedule,
        status: {
          in: [index.BookingStatus.ACCEPTED, index.BookingStatus.CANCELLED, index.BookingStatus.PENDING]
        }
      },
      select: {
        rescheduledBy: true
      }
    });
  }
  if (booking.status !== index.BookingStatus.ACCEPTED) {
    log.debug(
      "Booking is not accepted",
      indexBrowser.safeStringify({
        bookingId,
        webhook: { id: webhook.id }
      })
    );
    return;
  }
  const dailyVideoReference = booking.references?.filter((reference) => reference.type === "daily_video")?.pop() ?? null;
  if (!dailyVideoReference) {
    log.error(
      "Daily video reference not found",
      indexBrowser.safeStringify({
        bookingId,
        webhook: { id: webhook.id }
      })
    );
    throw new Error(`Daily video reference not found in triggerHostNoShow with bookingId ${bookingId}`);
  }
  const meetingDetails = await getMeetingSessionsFromRoomName(dailyVideoReference.uid);
  const hosts = getHosts(booking);
  const allParticipants = meetingDetails.data.flatMap((meeting) => meeting.participants);
  const hostsThatJoinedTheCall = [];
  const hostsThatDidntJoinTheCall = [];
  for (const host of hosts) {
    if (checkIfUserJoinedTheCall(host.id, allParticipants)) {
      hostsThatJoinedTheCall.push(host);
    } else {
      hostsThatDidntJoinTheCall.push(host);
    }
  }
  const numberOfHostsThatJoined = hosts.length - hostsThatDidntJoinTheCall.length;
  const didGuestJoinTheCall = meetingDetails.data.some(
    (meeting) => meeting.max_participants > numberOfHostsThatJoined
  );
  const participantsWithEmail = await getParticipantsWithEmail(allParticipants);
  return {
    hostsThatDidntJoinTheCall,
    hostsThatJoinedTheCall,
    booking,
    numberOfHostsThatJoined,
    webhook,
    didGuestJoinTheCall,
    originalRescheduledBooking,
    participants: participantsWithEmail
  };
};
exports.calculateMaxStartTime = calculateMaxStartTime;
exports.log = log;
exports.prepareNoShowTrigger = prepareNoShowTrigger;
exports.sendWebhookPayload = sendWebhookPayload;
