"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const httpError = require("./http-error-mkY8Ke7V.cjs");
const defaultHandler = require("./defaultHandler-MSjhitc-.cjs");
const defaultResponder = require("./defaultResponder-pIXL4EeF.cjs");
const getParsedAppKeysFromSlug = require("./getParsedAppKeysFromSlug-43RM8nd4.cjs");
const z = require("zod");
const index$2 = require("./orgDomains-W_rFTMBa.cjs");
const getSafeRedirectUrl = require("./getSafeRedirectUrl-M2YRxa9p.cjs");
const getInstalledAppPath = require("./getInstalledAppPath-oSgU9RsM.cjs");
const createOAuthAppCredential = require("./createOAuthAppCredential-aX4ofvTS.cjs");
const decodeOAuthState = require("./decodeOAuthState--7fljpCf.cjs");
const dubPackage = require("dub-package");
const credential = require("./credential-9BNiqYc8.cjs");
const getAppKeysFromSlug = require("./getAppKeysFromSlug-92RHW5nt.cjs");
const refreshOAuthTokens = require("./refreshOAuthTokens-aBYqX0P6.cjs");
const dubAppKeysSchema = z.z.object({
  client_id: z.z.string(),
  client_secret: z.z.string(),
  redirect_uris: z.z.string()
});
const dubScope = ["workspaces.read"];
const scopeString = dubScope.join(",");
async function handler$1(req, res) {
  const loggedInUser = req.session?.user;
  if (!loggedInUser) {
    throw new httpError.HttpError({ statusCode: 401, message: "You must be logged in to do this" });
  }
  if (!loggedInUser.email) {
    throw new httpError.HttpError({ statusCode: 400, message: "Session user must have an email" });
  }
  const { teamId } = req.query;
  const { client_id, redirect_uris } = await getParsedAppKeysFromSlug.getParsedAppKeysFromSlug("dub", dubAppKeysSchema);
  const url = new URL("https://app.dub.co/oauth/authorize");
  url.searchParams.append("client_id", client_id);
  url.searchParams.append("redirect_uri", redirect_uris);
  url.searchParams.append("response_type", "code");
  url.searchParams.append("scope", scopeString);
  if (typeof teamId === "string" && !Number.isNaN(Number(teamId))) {
    url.searchParams.append("state", JSON.stringify({ teamId: Number(teamId) }));
  }
  const oauthUrl = url.toString();
  return res.status(200).json({ url: oauthUrl });
}
const add = defaultHandler.defaultHandler({
  GET: Promise.resolve({ default: defaultResponder.defaultResponder(handler$1) })
});
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;
    }
    throw new httpError.HttpError({ statusCode: 400, message: "`code` must be a string" });
  }
  if (!req.session?.user?.id) {
    throw new httpError.HttpError({ statusCode: 401, message: "You must be logged in to do this" });
  }
  const { client_id, redirect_uris, client_secret } = await getParsedAppKeysFromSlug.getParsedAppKeysFromSlug("dub", dubAppKeysSchema);
  const codeExchangeUrl = `https://api.dub.co/oauth/token`;
  const result = await fetch(codeExchangeUrl, {
    method: "POST",
    body: new URLSearchParams({
      code,
      client_id,
      redirect_uri: redirect_uris,
      client_secret,
      grant_type: "authorization_code"
    }).toString(),
    headers: {
      "Content-Type": "application/x-www-form-urlencoded"
    }
  });
  if (result.status !== 200) {
    let errorMessage = "Something wrong with Dub Api";
    try {
      const responseBody2 = await result.json();
      if (typeof responseBody2?.error?.message === "string") {
        errorMessage = responseBody2.error.message;
      }
    } catch (err) {
      return;
    }
    return res.status(400).json({ message: errorMessage });
  }
  const responseBody = await result.json();
  responseBody.expiry_date = Math.round(Date.now() + responseBody.expires_in * 1e3);
  delete responseBody.expires_in;
  await createOAuthAppCredential.createOAuthAppCredential({ appId: "dub", type: "dub" }, responseBody, req);
  res.redirect(
    getSafeRedirectUrl.getSafeRedirectUrl(state?.returnTo) ?? getInstalledAppPath.getInstalledAppPath({ variant: "analytics", slug: "dub" })
  );
}
const index$1 = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  add,
  callback: handler
}, Symbol.toStringTag, { value: "Module" }));
class DubService {
  constructor(credential2) {
    this.client_id = "";
    this.client_secret = "";
    this.log = index$2.logger.getSubLogger({ prefix: ["[[lib]] dub"] });
    this.credential = credential2;
    this.client_id = "";
    this.client_secret = "";
  }
  async initClient() {
    const appKeys = await getAppKeysFromSlug.getAppKeysFromSlug("dub");
    const { client_id, client_secret } = appKeys;
    if (!client_id || !client_secret) {
      this.log.error("Dub.co app keys missing!");
      return;
    }
    this.client_id = client_id;
    this.client_secret = client_secret;
    let token = this.credential.key;
    if (!token)
      return;
    const isTokenExpired = (token2) => {
      if (!token2 || !token2.access_token)
        return true;
      if (token2.expiry_date) {
        return token2.expiry_date < Date.now();
      }
      return false;
    };
    if (isTokenExpired(token)) {
      token = await this.refreshAccessToken(token.refresh_token);
      if (!token)
        return;
    }
    this.dubClient = new dubPackage.Dub({ token: token.access_token });
  }
  async refreshAccessToken(refreshToken) {
    try {
      if (!refreshToken)
        return;
      const newToken = await refreshOAuthTokens.refreshOAuthTokens(
        async () => {
          const response = await fetch(`https://api.dub.co/oauth/token`, {
            method: "POST",
            body: new URLSearchParams({
              client_id: this.client_id,
              client_secret: this.client_secret,
              grant_type: "refresh_token",
              refresh_token: refreshToken
            }).toString(),
            headers: {
              "Content-Type": "application/x-www-form-urlencoded"
            }
          });
          if (!response.ok) {
            const res = await response.json();
            if (response.status === 401) {
              await credential.CredentialRepository.updateCredentialById({
                id: this.credential.id,
                data: {
                  invalid: true
                }
              });
            }
            throw new Error(`Error refreshing dub token: ${res?.error?.message ?? response.statusText}`);
          }
          return await response.json();
        },
        "dub",
        this.credential.userId
      );
      newToken.expiry_date = Date.now() + newToken.expires_in * 1e3;
      await credential.CredentialRepository.updateCredentialById({
        id: this.credential.id,
        data: { key: newToken }
      });
      return newToken;
    } catch (err) {
      this.log.error(err);
      throw err;
    }
  }
  async sendEvent({ name, email, eventName, id, externalId }) {
    await this.initClient();
    if (!this.dubClient)
      return;
    await this.dubClient.track.lead({
      clickId: id,
      customerName: name,
      customerEmail: email,
      externalId: externalId ?? email,
      eventName: eventName ?? "Cal.com lead"
    });
  }
}
const index = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
  __proto__: null,
  AnalyticsService: DubService
}, Symbol.toStringTag, { value: "Module" }));
exports.api = index$1;
exports.lib = index;
