"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const querystring = require("querystring");
const index$2 = require("./orgDomains-W_rFTMBa.cjs");
const getAppKeysFromSlug = require("./getAppKeysFromSlug-92RHW5nt.cjs");
const encodeOAuthState = require("./encodeOAuthState-VBfelnxQ.cjs");
const connectedCalendar = require("./connectedCalendar-LmxHhcjp.cjs");
const errors = require("./errors-fb9bpDY1.cjs");
const getSafeRedirectUrl = require("./getSafeRedirectUrl-M2YRxa9p.cjs");
const indexBrowser = require("./index-browser-rYj6TkGS.cjs");
const getInstalledAppPath = require("./getInstalledAppPath-oSgU9RsM.cjs");
const decodeOAuthState = require("./decodeOAuthState--7fljpCf.cjs");
const CalEventParser = require("./CalEventParser-XK6njYFX.cjs");
const CalendarAppError = require("./CalendarAppError-RC_O0RpM.cjs");
const markTokenAsExpired = require("./markTokenAsExpired-nBSCV-XL.cjs");
const oAuthManagerHelper = require("./oAuthManagerHelper-4K90cQHQ.cjs");
const _metadata = require("./_metadata-r2oqh1Kl.cjs");
const getOfficeAppKeys = require("./getOfficeAppKeys-zZlZYomc.cjs");
const dayjs = require("dayjs");
const scopes$1 = ["User.Read", "Calendars.Read", "Calendars.ReadWrite", "offline_access"];
async function handler$1(req, res) {
  if (req.method === "GET") {
    let clientId = "";
    const appKeys = await getAppKeysFromSlug.getAppKeysFromSlug("office365-calendar");
    if (typeof appKeys.client_id === "string")
      clientId = appKeys.client_id;
    if (!clientId)
      return res.status(400).json({ message: "Office 365 client_id missing." });
    const state = encodeOAuthState.encodeOAuthState(req);
    const params = {
      response_type: "code",
      scope: scopes$1.join(" "),
      client_id: clientId,
      prompt: "select_account",
      redirect_uri: `${index$2.WEBAPP_URL_FOR_OAUTH}/api/integrations/office365calendar/callback`,
      state
    };
    const query = querystring.stringify(params);
    const url = `https://login.microsoftonline.com/common/oauth2/v2.0/authorize?${query}`;
    res.status(200).json({ url });
  }
}
const scopes = ["offline_access", "Calendars.Read", "Calendars.ReadWrite"];
async function handler(req, res) {
  const { code } = req.query;
  const state = decodeOAuthState.decodeOAuthState(req);
  if (typeof code !== "string") {
    if (state?.onErrorReturnTo || state?.returnTo) {
      res.redirect(
        getSafeRedirectUrl.getSafeRedirectUrl(state.onErrorReturnTo) ?? getSafeRedirectUrl.getSafeRedirectUrl(state?.returnTo) ?? `${index$2.WEBAPP_URL}/apps/installed`
      );
      return;
    }
    res.status(400).json({ message: "No code returned" });
    return;
  }
  let clientId = "";
  let clientSecret = "";
  const appKeys = await getAppKeysFromSlug.getAppKeysFromSlug("office365-calendar");
  if (typeof appKeys.client_id === "string")
    clientId = appKeys.client_id;
  if (typeof appKeys.client_secret === "string")
    clientSecret = appKeys.client_secret;
  if (!clientId)
    return res.status(400).json({ message: "Office 365 client_id missing." });
  if (!clientSecret)
    return res.status(400).json({ message: "Office 365 client_secret missing." });
  const toUrlEncoded = (payload) => Object.keys(payload).map((key) => `${key}=${encodeURIComponent(payload[key])}`).join("&");
  const body = toUrlEncoded({
    client_id: clientId,
    grant_type: "authorization_code",
    code,
    scope: scopes.join(" "),
    redirect_uri: `${index$2.WEBAPP_URL_FOR_OAUTH}/api/integrations/office365calendar/callback`,
    client_secret: clientSecret
  });
  const response = await fetch("https://login.microsoftonline.com/common/oauth2/v2.0/token", {
    method: "POST",
    headers: {
      "Content-Type": "application/x-www-form-urlencoded;charset=UTF-8"
    },
    body
  });
  const responseBody = await response.json();
  if (!response.ok) {
    return res.redirect(`/apps/installed?error=${JSON.stringify(responseBody)}`);
  }
  const whoami = await fetch("https://graph.microsoft.com/v1.0/me", {
    headers: { Authorization: `Bearer ${responseBody.access_token}` }
  });
  const graphUser = await whoami.json();
  responseBody.email = graphUser.mail ?? graphUser.userPrincipalName;
  responseBody.expiry_date = Math.round(+/* @__PURE__ */ new Date() / 1e3 + responseBody.expires_in);
  delete responseBody.expires_in;
  let defaultCalendar = void 0;
  let requestUrl = "https://graph.microsoft.com/v1.0/me/calendars?$select=id,isDefaultCalendar";
  let finishedParsingCalendars = false;
  while (!finishedParsingCalendars) {
    const calRequest = await fetch(requestUrl, {
      method: "GET",
      headers: {
        Authorization: `Bearer ${responseBody.access_token}`,
        "Content-Type": "application/json"
      }
    });
    index$2.logger.info("Office365 Calendar: Received calendar response", {
      userId: req.session?.user?.id,
      status: calRequest.status,
      statusText: calRequest.statusText,
      url: calRequest.url
    });
    let calBody = await errors.handleErrorsJson(calRequest);
    index$2.logger.info("Office365 Calendar: handleErrorsJson completed", {
      userId: req.session?.user?.id,
      calendarCount: calBody.value.length ?? 0
    });
    if (typeof responseBody === "string") {
      calBody = JSON.parse(responseBody);
    }
    const findDefaultCalendar = calBody.value.find((calendar) => calendar.isDefaultCalendar);
    if (findDefaultCalendar) {
      defaultCalendar = findDefaultCalendar;
    }
    if (calBody["@odata.nextLink"]) {
      requestUrl = calBody["@odata.nextLink"];
    } else {
      finishedParsingCalendars = true;
    }
  }
  if (defaultCalendar?.id && req.session?.user?.id) {
    const credential = await index$2.prisma.credential.create({
      data: {
        type: "office365_calendar",
        key: responseBody,
        userId: req.session?.user.id,
        appId: "office365-calendar"
      }
    });
    const selectedCalendarWhereUnique = {
      userId: req.session?.user.id,
      integration: "office365_calendar",
      externalId: defaultCalendar.id
    };
    try {
      await index$2.prisma.selectedCalendar.create({
        data: {
          ...selectedCalendarWhereUnique,
          credentialId: credential.id
        }
      });
    } catch (error) {
      let errorMessage = "something_went_wrong";
      if (error instanceof indexBrowser.indexBrowser.Prisma.PrismaClientKnownRequestError && error.code === "P2002") {
        if (await connectedCalendar.renewSelectedCalendarCredentialId(selectedCalendarWhereUnique, credential.id)) {
          res.redirect(
            getSafeRedirectUrl.getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath.getInstalledAppPath({ variant: "calendar", slug: "office365-calendar" })
          );
          return;
        }
        errorMessage = "account_already_linked";
      }
      await index$2.prisma.credential.delete({ where: { id: credential.id } });
      res.redirect(
        `${getSafeRedirectUrl.getSafeRedirectUrl(state?.onErrorReturnTo) ?? getInstalledAppPath.getInstalledAppPath({ variant: "calendar", slug: "office365-calendar" })}?error=${errorMessage}`
      );
      return;
    }
  }
  res.redirect(
    getSafeRedirectUrl.getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath.getInstalledAppPath({ variant: "calendar", slug: "office365-calendar" })
  );
  return;
}
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  add: handler$1,
  callback: handler
}, Symbol.toStringTag, { value: "Module" }));
class Office365CalendarService {
  constructor(credential) {
    this.url = "";
    this.integrationName = "";
    this.apiGraphUrl = "https://graph.microsoft.com/v1.0";
    this.translateEvent = (event) => {
      const office365Event = {
        subject: event.title,
        body: {
          contentType: "text",
          content: event.calendarDescription
        },
        start: {
          dateTime: dayjs(event.startTime).tz(event.organizer.timeZone).format("YYYY-MM-DDTHH:mm:ss"),
          timeZone: event.organizer.timeZone
        },
        end: {
          dateTime: dayjs(event.endTime).tz(event.organizer.timeZone).format("YYYY-MM-DDTHH:mm:ss"),
          timeZone: event.organizer.timeZone
        },
        hideAttendees: !event.seatsPerTimeSlot ? false : !event.seatsShowAttendees,
        organizer: {
          emailAddress: {
            address: event.destinationCalendar ? event.destinationCalendar.find((cal) => cal.userId === event.organizer.id)?.externalId ?? event.organizer.email : event.organizer.email,
            name: event.organizer.name
          }
        },
        attendees: [
          ...event.attendees.map((attendee) => ({
            emailAddress: {
              address: attendee.email,
              name: attendee.name
            },
            type: "required"
          })),
          ...event.team?.members ? event.team?.members.filter((member) => member.email !== this.credential.user?.email).map((member) => {
            const destinationCalendar = event.destinationCalendar && event.destinationCalendar.find((cal) => cal.userId === member.id);
            return {
              emailAddress: {
                address: destinationCalendar?.externalId ?? member.email,
                name: member.name
              },
              type: "required"
            };
          }) : []
        ],
        location: event.location ? { displayName: CalEventParser.getLocation(event) } : void 0
      };
      if (event.hideCalendarEventDetails) {
        office365Event.sensitivity = "private";
      }
      return office365Event;
    };
    this.fetcher = async (endpoint, init) => {
      return this.auth.requestRaw({
        url: `${this.apiGraphUrl}${endpoint}`,
        options: {
          method: "get",
          ...init
        }
      });
    };
    this.fetchResponsesWithNextLink = async (settledResponses) => {
      const alreadySuccess = [];
      const newLinkRequest = [];
      settledResponses?.forEach((response) => {
        if (response.status === 200 && response.body["@odata.nextLink"] === void 0) {
          alreadySuccess.push(response);
        } else {
          const nextLinkUrl = response.body["@odata.nextLink"] ? String(response.body["@odata.nextLink"]).replace(this.apiGraphUrl, "") : "";
          if (nextLinkUrl) {
            newLinkRequest.push({
              id: Number(response.id),
              method: "GET",
              url: nextLinkUrl
            });
          }
          delete response.body["@odata.nextLink"];
          alreadySuccess.push(response);
        }
      });
      if (newLinkRequest.length === 0) {
        return alreadySuccess;
      }
      const newResponse = await this.apiGraphBatchCall(newLinkRequest);
      let newResponseBody = await errors.handleErrorsJson(newResponse);
      if (typeof newResponseBody === "string") {
        newResponseBody = this.handleTextJsonResponseWithHtmlInBody(newResponseBody);
      }
      const newSettledResponses = await this.fetchResponsesWithNextLink(newResponseBody.responses);
      return [...alreadySuccess, ...newSettledResponses];
    };
    this.fetchRequestWithRetryAfter = async (originalRequests, settledPromises, maxRetries, retryCount = 0) => {
      const getRandomness = () => Number(Math.random().toFixed(3));
      let retryAfterTimeout = 0;
      if (retryCount >= maxRetries) {
        return { responses: settledPromises };
      }
      const alreadySuccessRequest = [];
      const failedRequest = [];
      settledPromises.forEach((item) => {
        if (item.status === 200) {
          alreadySuccessRequest.push(item);
        } else if (item.status === 429) {
          const newTimeout = Number(item.headers["Retry-After"]) * 1e3 || 0;
          retryAfterTimeout = newTimeout > retryAfterTimeout ? newTimeout : retryAfterTimeout;
          failedRequest.push(originalRequests[Number(item.id)]);
        }
      });
      if (failedRequest.length === 0) {
        return { responses: alreadySuccessRequest };
      }
      await new Promise((r) => setTimeout(r, retryAfterTimeout + getRandomness()));
      const newResponses = await this.apiGraphBatchCall(failedRequest);
      let newResponseBody = await errors.handleErrorsJson(newResponses);
      if (typeof newResponseBody === "string") {
        newResponseBody = this.handleTextJsonResponseWithHtmlInBody(newResponseBody);
      }
      const retryAfter = !!newResponseBody?.responses && this.findRetryAfterResponse(newResponseBody.responses);
      if (retryAfter && newResponseBody.responses) {
        newResponseBody = await this.fetchRequestWithRetryAfter(
          failedRequest,
          newResponseBody.responses,
          maxRetries,
          retryCount + 1
        );
      }
      return { responses: [...alreadySuccessRequest, ...newResponseBody?.responses || []] };
    };
    this.apiGraphBatchCall = async (requests) => {
      const response = await this.fetcher(`/$batch`, {
        method: "POST",
        body: JSON.stringify({ requests })
      });
      return response;
    };
    this.handleTextJsonResponseWithHtmlInBody = (response) => {
      try {
        const parsedJson = JSON.parse(response);
        return parsedJson;
      } catch (error) {
        const openTag = '"body":<';
        const closeTag = "</html>";
        const htmlBeginning = response.indexOf(openTag) + openTag.length - 1;
        const htmlEnding = response.indexOf(closeTag) + closeTag.length + 2;
        const resultString = `${response.repeat(1).substring(0, htmlBeginning)} ""${response.repeat(1).substring(htmlEnding, response.length)}`;
        return JSON.parse(resultString);
      }
    };
    this.findRetryAfterResponse = (response) => {
      const foundRetry = response.find((request) => request.status === 429);
      return !!foundRetry;
    };
    this.processBusyTimes = (responses) => {
      return responses.reduce(
        (acc, subResponse) => {
          if (!subResponse.body?.value)
            return acc;
          return acc.concat(
            subResponse.body.value.reduce((acc2, evt) => {
              if (evt.showAs === "free" || evt.showAs === "workingElsewhere")
                return acc2;
              return acc2.concat({
                start: `${evt.start.dateTime}Z`,
                end: `${evt.end.dateTime}Z`
              });
            }, [])
          );
        },
        []
      );
    };
    this.handleErrorJsonOffice365Calendar = (response) => {
      if (response.headers.get("content-encoding") === "gzip") {
        return response.text();
      }
      if (response.status === 204) {
        return new Promise((resolve) => resolve({}));
      }
      if (!response.ok && response.status < 200 && response.status >= 300) {
        response.json().then(console.log);
        throw Error(response.statusText);
      }
      return response.json();
    };
    this.integrationName = "office365_calendar";
    const tokenResponse = markTokenAsExpired.getTokenObjectFromCredential(credential);
    this.auth = new markTokenAsExpired.OAuthManager({
      credentialSyncVariables: oAuthManagerHelper.oAuthManagerHelper.credentialSyncVariables,
      resourceOwner: {
        type: "user",
        id: credential.userId
      },
      appSlug: _metadata.metadata.slug,
      currentTokenObject: tokenResponse,
      fetchNewTokenObject: async ({ refreshToken }) => {
        const isDelegated = Boolean(credential?.delegatedTo);
        if (!isDelegated && !refreshToken) {
          return null;
        }
        const { client_id, client_secret } = await this.getAuthCredentials(isDelegated);
        const url = this.getAuthUrl(isDelegated, credential?.delegatedTo?.serviceAccountKey?.tenant_id);
        const bodyParams = {
          scope: isDelegated ? "https://graph.microsoft.com/.default" : "User.Read Calendars.Read Calendars.ReadWrite",
          client_id,
          client_secret,
          grant_type: isDelegated ? "client_credentials" : "refresh_token",
          ...isDelegated ? {} : { refresh_token: refreshToken ?? "" }
        };
        return fetch(url, {
          method: "POST",
          headers: { "Content-Type": "application/x-www-form-urlencoded" },
          body: new URLSearchParams(bodyParams)
        });
      },
      isTokenObjectUnusable: async function() {
        return null;
      },
      isAccessTokenUnusable: async function() {
        return null;
      },
      invalidateTokenObject: () => oAuthManagerHelper.oAuthManagerHelper.invalidateCredential(credential.id),
      expireAccessToken: () => oAuthManagerHelper.oAuthManagerHelper.markTokenAsExpired(credential),
      updateTokenObject: (tokenObject) => {
        if (!Boolean(credential.delegatedTo)) {
          return oAuthManagerHelper.oAuthManagerHelper.updateTokenObject({ tokenObject, credentialId: credential.id });
        }
        return Promise.resolve();
      }
    });
    this.credential = credential;
    this.log = index$2.logger.getSubLogger({ prefix: [`[[lib] ${this.integrationName}`] });
  }
  getAuthUrl(delegatedTo, tenantId) {
    if (delegatedTo) {
      if (!tenantId) {
        throw new CalendarAppError.CalendarAppDelegationCredentialInvalidGrantError(
          "Invalid DelegationCredential Settings: tenantId is missing"
        );
      }
      return `https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`;
    }
    return "https://login.microsoftonline.com/common/oauth2/v2.0/token";
  }
  async getAuthCredentials(isDelegated) {
    if (isDelegated) {
      const client_id = this.credential?.delegatedTo?.serviceAccountKey?.client_id;
      const client_secret = this.credential?.delegatedTo?.serviceAccountKey?.private_key;
      if (!client_id || !client_secret) {
        throw new CalendarAppError.CalendarAppDelegationCredentialConfigurationError(
          "Delegation credential without clientId or Secret"
        );
      }
      return { client_id, client_secret };
    }
    return getOfficeAppKeys.getOfficeAppKeys();
  }
  async getAzureUserId(credential) {
    if (this.azureUserId)
      return this.azureUserId;
    const isDelegated = Boolean(credential?.delegatedTo);
    if (!isDelegated)
      return;
    const url = this.getAuthUrl(isDelegated, credential?.delegatedTo?.serviceAccountKey?.tenant_id);
    const delegationCredentialClientId = credential.delegatedTo?.serviceAccountKey?.client_id;
    const delegationCredentialClientSecret = credential.delegatedTo?.serviceAccountKey?.private_key;
    if (!delegationCredentialClientId || !delegationCredentialClientSecret) {
      throw new CalendarAppError.CalendarAppDelegationCredentialConfigurationError(
        "Delegation credential without clientId or Secret"
      );
    }
    const loginResponse = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        scope: "https://graph.microsoft.com/.default",
        client_id: delegationCredentialClientId,
        grant_type: "client_credentials",
        client_secret: delegationCredentialClientSecret
      })
    });
    if (!this.azureUserId && credential?.delegatedTo) {
      const clonedResponse = loginResponse.clone();
      const parsedLoginResponse = await clonedResponse.json();
      const token = parsedLoginResponse?.access_token;
      const oauthClientIdAliasRegex = /\+[a-zA-Z0-9]{25}/;
      const email = this.credential?.user?.email.replace(oauthClientIdAliasRegex, "");
      const encodedFilter = encodeURIComponent(`mail eq '${email}'`);
      const queryParams = `$filter=${encodedFilter}`;
      const response = await fetch(`https://graph.microsoft.com/v1.0/users?${queryParams}`, {
        method: "GET",
        headers: {
          "Content-Type": "application/x-www-form-urlencoded",
          Authorization: `Bearer ${token}`
        }
      });
      const parsedBody = await response.json();
      if (!parsedBody?.value?.[0]?.id) {
        throw new CalendarAppError.CalendarAppDelegationCredentialInvalidGrantError(
          "User might not exist in Microsoft Azure Active Directory"
        );
      }
      this.azureUserId = parsedBody.value[0].id;
    }
    return this.azureUserId;
  }
  // It would error if the delegation credential is not set up correctly
  async testDelegationCredentialSetup() {
    const delegationCredentialClientId = this.credential.delegatedTo?.serviceAccountKey?.client_id;
    const delegationCredentialClientSecret = this.credential.delegatedTo?.serviceAccountKey?.private_key;
    const url = this.getAuthUrl(
      Boolean(this.credential?.delegatedTo),
      this.credential?.delegatedTo?.serviceAccountKey?.tenant_id
    );
    if (!delegationCredentialClientId || !delegationCredentialClientSecret) {
      return false;
    }
    const loginResponse = await fetch(url, {
      method: "POST",
      headers: { "Content-Type": "application/x-www-form-urlencoded" },
      body: new URLSearchParams({
        scope: "https://graph.microsoft.com/.default",
        client_id: delegationCredentialClientId,
        grant_type: "client_credentials",
        client_secret: delegationCredentialClientSecret
      })
    });
    const parsedLoginResponse = await loginResponse.json();
    return Boolean(parsedLoginResponse?.access_token);
  }
  async getUserEndpoint() {
    const azureUserId = await this.getAzureUserId(this.credential);
    return azureUserId ? `/users/${this.azureUserId}` : "/me";
  }
  async createEvent(event, credentialId) {
    const mainHostDestinationCalendar = event.destinationCalendar ? event.destinationCalendar.find((cal) => cal.credentialId === credentialId) ?? event.destinationCalendar[0] : void 0;
    try {
      const eventsUrl = mainHostDestinationCalendar?.externalId ? `${await this.getUserEndpoint()}/calendars/${mainHostDestinationCalendar?.externalId}/events` : `${await this.getUserEndpoint()}/calendar/events`;
      const response = await this.fetcher(eventsUrl, {
        method: "POST",
        body: JSON.stringify(this.translateEvent(event))
      });
      const responseJson = await errors.handleErrorsJson(response);
      return { ...responseJson, iCalUID: responseJson.iCalUId };
    } catch (error) {
      this.log.error(error);
      throw error;
    }
  }
  async updateEvent(uid, event) {
    try {
      const response = await this.fetcher(`${await this.getUserEndpoint()}/calendar/events/${uid}`, {
        method: "PATCH",
        body: JSON.stringify(this.translateEvent(event))
      });
      const responseJson = await errors.handleErrorsJson(response);
      return { ...responseJson, iCalUID: responseJson.iCalUId };
    } catch (error) {
      this.log.error(error);
      throw error;
    }
  }
  async deleteEvent(uid) {
    try {
      const response = await this.fetcher(`${await this.getUserEndpoint()}/calendar/events/${uid}`, {
        method: "DELETE"
      });
      errors.handleErrorsRaw(response);
    } catch (error) {
      this.log.error(error);
      throw error;
    }
  }
  async getAvailability(dateFrom, dateTo, selectedCalendars) {
    const dateFromParsed = new Date(dateFrom);
    const dateToParsed = new Date(dateTo);
    const filter = `?startDateTime=${encodeURIComponent(
      dateFromParsed.toISOString()
    )}&endDateTime=${encodeURIComponent(dateToParsed.toISOString())}`;
    const calendarSelectParams = "$select=showAs,start,end";
    try {
      const selectedCalendarIds = selectedCalendars.reduce((calendarIds, calendar) => {
        if (calendar.integration === this.integrationName && calendar.externalId)
          calendarIds.push(calendar.externalId);
        return calendarIds;
      }, []);
      if (selectedCalendarIds.length === 0 && selectedCalendars.length > 0) {
        return Promise.resolve([]);
      }
      const ids = await (selectedCalendarIds.length === 0 ? this.listCalendars().then((cals) => cals.map((e_2) => e_2.externalId).filter(Boolean) || []) : Promise.resolve(selectedCalendarIds));
      const requestsPromises = ids.map(async (calendarId, id) => ({
        id,
        method: "GET",
        url: `${await this.getUserEndpoint()}/calendars/${calendarId}/calendarView${filter}&${calendarSelectParams}`
      }));
      const requests = await Promise.all(requestsPromises);
      const response = await this.apiGraphBatchCall(requests);
      const responseBody = await this.handleErrorJsonOffice365Calendar(response);
      let responseBatchApi = { responses: [] };
      if (typeof responseBody === "string") {
        responseBatchApi = this.handleTextJsonResponseWithHtmlInBody(responseBody);
      }
      let alreadySuccessResponse = [];
      const retryAfter = !!responseBatchApi?.responses && this.findRetryAfterResponse(responseBatchApi.responses);
      if (retryAfter && responseBatchApi.responses) {
        responseBatchApi = await this.fetchRequestWithRetryAfter(requests, responseBatchApi.responses, 2);
      }
      alreadySuccessResponse = await this.fetchResponsesWithNextLink(responseBatchApi.responses);
      return alreadySuccessResponse ? this.processBusyTimes(alreadySuccessResponse) : [];
    } catch (err) {
      return Promise.reject([]);
    }
  }
  async listCalendars() {
    const officeCalendars = [];
    let finishedParsingCalendars = false;
    const calendarFilterParam = "$select=id,name,isDefaultCalendar,canEdit";
    let requestLink = `${await this.getUserEndpoint()}/calendars?${calendarFilterParam}`;
    while (!finishedParsingCalendars) {
      const response = await this.fetcher(requestLink);
      let responseBody = await errors.handleErrorsJson(
        response
      );
      if (typeof responseBody === "string") {
        responseBody = JSON.parse(responseBody);
      }
      officeCalendars.push(...responseBody.value);
      if (responseBody["@odata.nextLink"]) {
        requestLink = responseBody["@odata.nextLink"].replace(this.apiGraphUrl, "");
      } else {
        finishedParsingCalendars = true;
      }
    }
    const user = await this.fetcher(`${await this.getUserEndpoint()}`);
    const userResponseBody = await errors.handleErrorsJson(user);
    const email = userResponseBody.mail ?? userResponseBody.userPrincipalName;
    return officeCalendars.map((cal) => {
      const calendar = {
        externalId: cal.id ?? "No Id",
        integration: this.integrationName,
        name: cal.name ?? "No calendar name",
        primary: cal.isDefaultCalendar ?? false,
        readOnly: !cal.canEdit && true,
        email: email ?? ""
      };
      return calendar;
    });
  }
  async getMainTimeZone() {
    try {
      const response = await this.fetcher(`${await this.getUserEndpoint()}/mailboxSettings/timeZone`);
      const timezone = await errors.handleErrorsJson(response);
      if (!timezone) {
        this.log.warn("No timezone found in mailbox settings, defaulting to Europe/London");
        return "Europe/London";
      }
      return timezone;
    } catch (error) {
      this.log.error("Error getting main timezone from Office365 Calendar", { error });
      throw error;
    }
  }
}
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  CalendarService: Office365CalendarService
}, Symbol.toStringTag, { value: "Module" }));
exports.metadata = _metadata.metadata$1;
exports.api = index$1;
exports.lib = index;
