"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const index$2 = require("./index-QSf6WJj0.cjs");
const vitalNode = require("@tryvital/vital-node");
const getAppKeysFromSlug = require("./getAppKeysFromSlug-duun9y1Q.cjs");
const getInstalledAppPath = require("./getInstalledAppPath-2GQAo7UC.cjs");
const queue = require("queue");
const errors = require("./errors-fb9bpDY1.cjs");
const httpError = require("./http-error-mkY8Ke7V.cjs");
const director = require("./director-T8Nq2GAR.cjs");
const indexBrowser = require("./index-browser-RtwB1hqI.cjs");
const videoClient = require("./videoClient-k_uXe0oj.cjs");
const getCalendar = require("./getCalendar-zHs4Z8rE.cjs");
const index$3 = require("./email-manager-PJbiqghj.cjs");
const dayjs = require("dayjs");
const z = require("zod");
const _metadata = require("./_metadata-VOmph7MG.cjs");
let vitalClient = null;
let vitalEnv = null;
async function initVitalClient() {
  if (vitalClient)
    return vitalClient;
  const appKeys = await getAppKeysFromSlug.getAppKeysFromSlug("vital-automation");
  if (typeof appKeys !== "object" || typeof appKeys.api_key !== "string" || typeof appKeys.webhook_secret !== "string" || typeof appKeys.region !== "string" || typeof appKeys.mode !== "string")
    throw Error("Missing properties in vital-automation DB keys");
  vitalEnv = appKeys;
  vitalClient = new vitalNode.VitalClient({
    region: appKeys.region,
    api_key: appKeys.api_key || "",
    environment: appKeys.mode || "sandbox"
  });
  return vitalClient;
}
async function handler$4(req, res) {
  const calcomUserId = req.session?.user?.id;
  if (!calcomUserId) {
    return res.status(401).json({ message: "You must be logged in to do this" });
  }
  const vitalClient2 = await initVitalClient();
  if (!vitalClient2 || !vitalEnv)
    return res.status(400).json({ message: "Missing vital client, try calling `initVitalClient`" });
  let userVital;
  try {
    userVital = await vitalClient2.User.create(`cal_${calcomUserId}`);
  } catch (e) {
    userVital = await vitalClient2.User.resolve(`cal_${calcomUserId}`);
  }
  try {
    if (userVital?.user_id) {
      await index$2.prisma.credential.create({
        data: {
          type: "vital_other",
          key: { userVitalId: userVital.user_id },
          userId: calcomUserId,
          appId: "vital-automation"
        }
      });
    }
    const token = await vitalClient2.Link.create(
      userVital?.user_id,
      void 0,
      `${index$2.WEBAPP_URL}/api/integrations/vital/callback`
    );
    return res.status(200).json({
      token: token.link_token,
      url: `https://link.tryvital.io/?env=${vitalEnv.mode}&region=${vitalEnv.region}`
    });
  } catch (e) {
    return res.status(400).json({ error: JSON.stringify(e) });
  }
}
async function handler$3(req, res) {
  try {
    const userWithMetadata = await index$2.prisma.user.findFirst({
      where: {
        id: req?.session?.user.id
      },
      select: {
        id: true,
        metadata: true
      }
    });
    await index$2.prisma.user.update({
      where: {
        id: req?.session?.user.id
      },
      data: {
        metadata: {
          ...userWithMetadata?.metadata,
          vitalSettings: {
            ...userWithMetadata?.metadata?.vitalSettings,
            connected: true
          }
        }
      }
    });
    return res.redirect(getInstalledAppPath.getInstalledAppPath({ variant: "other", slug: "vital-automation" }));
  } catch (e) {
    return res.status(500);
  }
}
const Reschedule = async (bookingUid, cancellationReason) => {
  const bookingToReschedule = await index$2.prisma.booking.findFirstOrThrow({
    select: {
      id: true,
      uid: true,
      title: true,
      startTime: true,
      endTime: true,
      userId: true,
      eventTypeId: true,
      location: true,
      attendees: true,
      references: true,
      eventType: {
        include: {
          team: {
            select: {
              id: true,
              name: true
            }
          }
        }
      },
      user: {
        select: {
          id: true,
          email: true,
          name: true,
          timeZone: true,
          locale: true,
          username: true,
          credentials: true,
          destinationCalendar: true
        }
      }
    },
    where: {
      uid: bookingUid,
      NOT: {
        status: {
          in: [index$2.BookingStatus.CANCELLED, index$2.BookingStatus.REJECTED]
        }
      }
    }
  });
  if (bookingToReschedule && bookingToReschedule.eventTypeId && bookingToReschedule.user) {
    const userOwner = bookingToReschedule.user;
    const event = await index$2.prisma.eventType.findUniqueOrThrow({
      select: {
        title: true
      },
      where: {
        id: bookingToReschedule.eventTypeId
      }
    });
    await index$2.prisma.booking.update({
      where: {
        id: bookingToReschedule.id
      },
      data: {
        rescheduled: true,
        cancellationReason,
        status: index$2.BookingStatus.CANCELLED,
        updatedAt: dayjs().toISOString()
      }
    });
    const [mainAttendee] = bookingToReschedule.attendees;
    const tAttendees = await indexBrowser.getTranslation(mainAttendee.locale ?? "en", "common");
    const usersToPeopleType = (users, selectedLanguage) => {
      return users?.map((user) => {
        return {
          email: user.email || "",
          name: user.name || "",
          username: user?.username || "",
          language: { translate: selectedLanguage, locale: user.locale || "en" },
          timeZone: user?.timeZone,
          phoneNumber: user?.phoneNumber
        };
      });
    };
    const userOwnerTranslation = await indexBrowser.getTranslation(userOwner.locale ?? "en", "common");
    const [userOwnerAsPeopleType] = usersToPeopleType([userOwner], userOwnerTranslation);
    const builder = new director.CalendarEventBuilder();
    builder.init({
      title: bookingToReschedule.title,
      type: event.title,
      startTime: bookingToReschedule.startTime.toISOString(),
      endTime: bookingToReschedule.endTime.toISOString(),
      attendees: usersToPeopleType(
        // username field doesn't exists on attendee but could be in the future
        bookingToReschedule.attendees,
        tAttendees
      ),
      organizer: userOwnerAsPeopleType,
      hideOrganizerEmail: bookingToReschedule.eventType?.hideOrganizerEmail,
      team: !!bookingToReschedule.eventType?.team ? {
        name: bookingToReschedule.eventType.team.name,
        id: bookingToReschedule.eventType.team.id,
        members: []
      } : void 0
    });
    const director$1 = new director.CalendarEventDirector();
    director$1.setBuilder(builder);
    director$1.setExistingBooking(bookingToReschedule);
    director$1.setCancellationReason(cancellationReason);
    await director$1.buildForRescheduleEmail();
    const credentialsMap = /* @__PURE__ */ new Map();
    userOwner.credentials.forEach((credential) => {
      credentialsMap.set(credential.type, credential);
    });
    const bookingRefsFiltered = bookingToReschedule.references.filter(
      (ref) => !!credentialsMap.get(ref.type)
    );
    const promises = bookingRefsFiltered.map(async (bookingRef) => {
      if (!bookingRef.uid)
        return;
      if (bookingRef.type.endsWith("_calendar")) {
        const calendar = await getCalendar.getCalendar(credentialsMap.get(bookingRef.type));
        return calendar?.deleteEvent(bookingRef.uid, builder.calendarEvent);
      } else if (bookingRef.type.endsWith("_video")) {
        return videoClient.deleteMeeting(credentialsMap.get(bookingRef.type), bookingRef.uid);
      }
    });
    try {
      await Promise.all(promises);
    } catch (error) {
      if (error instanceof Error) {
        index$2.logger.error(error.message);
      }
    }
    try {
      await index$3.sendRequestRescheduleEmailAndSMS(
        builder.calendarEvent,
        {
          rescheduleLink: builder.rescheduleLink
        },
        bookingToReschedule?.eventType?.metadata
      );
    } catch (error) {
      if (error instanceof Error) {
        index$2.logger.error(error.message);
      }
    }
    return true;
  }
};
const Reschedule$1 = Reschedule;
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  Reschedule: Reschedule$1
}, Symbol.toStringTag, { value: "Module" }));
async function handler$2(req, res) {
  try {
    if (req.method !== "POST") {
      throw new httpError.HttpError({ statusCode: 405, message: "Method Not Allowed" });
    }
    const sig = req.headers["svix-signature"];
    if (!sig) {
      throw new httpError.HttpError({ statusCode: 400, message: "Missing svix-signature" });
    }
    const vitalClient2 = await initVitalClient();
    if (!vitalClient2 || !vitalEnv)
      return res.status(400).json({ message: "Missing vital client, try calling `initVitalClient`" });
    const payload = JSON.stringify(req.body);
    const event = vitalClient2.Webhooks.constructWebhookEvent(
      payload,
      req.headers,
      vitalEnv.webhook_secret
    );
    if (event.event_type == "daily.data.sleep.created") {
      try {
        if (event.data.user_id) {
          const json = { userVitalId: event.data.user_id };
          const credential = await index$2.prisma.credential.findFirstOrThrow({
            where: {
              type: "vital_other",
              key: {
                equals: json
              }
            }
          });
          if (!credential) {
            return res.status(404).json({ message: "Missing vital credential" });
          }
          const userWithMetadata = await index$2.prisma.user.findFirst({
            select: {
              metadata: true
            },
            where: {
              id: credential.userId
            }
          });
          let minimumSleepTime = 0;
          let parameterFilter = "";
          const userMetadata = userWithMetadata?.metadata;
          const vitalSettings = userWithMetadata?.metadata?.vitalSettings || {};
          if (!!userMetadata && !!vitalSettings) {
            minimumSleepTime = vitalSettings.sleepValue;
            parameterFilter = vitalSettings.parameter;
          } else {
            res.status(404).json({ message: "Vital configuration not found for user" });
            return;
          }
          if (!event.data.hasOwnProperty(parameterFilter)) {
            res.status(500).json({ message: "Selected param not available" });
            return;
          }
          const totalHoursSleep = Number(event.data[parameterFilter]) / 60 / 60;
          if (minimumSleepTime > 0 && parameterFilter !== "" && totalHoursSleep <= minimumSleepTime) {
            try {
              const todayDate = dayjs();
              const todayBookings = await index$2.prisma.booking.findMany({
                where: {
                  startTime: {
                    gte: todayDate.startOf("day").toISOString()
                  },
                  endTime: {
                    lte: todayDate.endOf("day").toISOString()
                  },
                  status: {
                    in: [index$2.BookingStatus.ACCEPTED, index$2.BookingStatus.PENDING]
                  },
                  // @NOTE: very important filter
                  userId: credential?.userId
                },
                select: {
                  id: true,
                  uid: true,
                  userId: true,
                  status: true
                }
              });
              const q = queue({ results: [] });
              if (todayBookings.length > 0) {
                todayBookings.forEach(
                  (booking) => q.push(() => {
                    return Reschedule$1(booking.uid, "");
                  })
                );
              }
              await q.start();
            } catch (error) {
              throw new Error("Failed to reschedule bookings");
            }
          }
        }
      } catch (error) {
        if (error instanceof Error) {
          index$2.logger.error(error.message);
        }
        index$2.logger.error("Failed to get sleep score");
      }
    }
    return res.status(200).json({ body: req.body });
  } catch (_err) {
    const err = errors.getErrorFromUnknown(_err);
    console.error(`Webhook Error: ${err.message}`);
    res.status(err.statusCode ?? 500).send({
      message: err.message,
      stack: index$2.IS_PRODUCTION ? void 0 : err.stack
    });
    return;
  }
}
async function handler$1(req, res) {
  if (req.method === "GET" && req.session && req.session.user.id) {
    const userId = req.session.user.id;
    try {
      const user = await index$2.prisma.user.findFirst({
        select: {
          metadata: true
        },
        where: {
          id: userId
        }
      });
      if (user && user.metadata && user.metadata?.vitalSettings) {
        res.status(200).json(user.metadata.vitalSettings);
      } else {
        res.status(404);
      }
    } catch (error) {
      res.status(500);
    }
  } else {
    res.status(400);
  }
  res.end();
}
const handler = async (req, res) => {
  if (req.method === "PUT" && req.session && req.session.user.id) {
    const userId = req.session.user.id;
    const body = req.body;
    try {
      const userWithMetadata = await index$2.prisma.user.findFirst({
        where: {
          id: userId
        },
        select: {
          id: true,
          metadata: true
        }
      });
      const userMetadata = userWithMetadata?.metadata;
      const vitalSettings = userWithMetadata?.metadata?.vitalSettings || {};
      await index$2.prisma.user.update({
        where: {
          id: userId
        },
        data: {
          metadata: {
            ...userMetadata,
            vitalSettings: {
              ...vitalSettings,
              ...body
            }
          }
        }
      });
      if (vitalSettings) {
        res.status(200).json(vitalSettings);
      } else {
        res.status(404);
      }
    } catch (error) {
      res.status(500);
    }
  } else {
    res.status(400);
  }
  res.end();
};
function validate(handler2) {
  return async (req, res) => {
    if (req.method === "POST" || req.method === "PUT") {
      try {
        indexBrowser.vitalSettingsUpdateSchema.parse(req.body);
      } catch (error) {
        if (error instanceof z.ZodError && error?.name === "ZodError") {
          return res.status(400).json(error?.issues);
        }
        return res.status(402);
      }
    } else {
      return res.status(405);
    }
    await handler2(req, res);
  };
}
const save = validate(handler);
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  callback: handler$3,
  save,
  settings: handler$1,
  token: handler$4,
  webhook: handler$2
}, Symbol.toStringTag, { value: "Module" }));
exports.metadata = _metadata.metadata;
exports.api = index;
exports.lib = index$1;
