import { H as HttpError } from "./http-error-RJXCPZV2.js";
import { d as defaultHandler } from "./defaultHandler-yvm7aMmf.js";
import { d as defaultResponder } from "./defaultResponder-s4VQhYfH.js";
import { g as getParsedAppKeysFromSlug } from "./getParsedAppKeysFromSlug-MNhyH762.js";
import { z } from "zod";
import { m as WEBAPP_URL, l as logger } from "./index-Cw1zbw54.js";
import { g as getSafeRedirectUrl } from "./getSafeRedirectUrl-hxmyPhEi.js";
import { g as getInstalledAppPath } from "./getInstalledAppPath-6P3H-VDB.js";
import { c as createOAuthAppCredential } from "./createOAuthAppCredential-UOwy2cXA.js";
import { d as decodeOAuthState } from "./decodeOAuthState-KhwGAxqw.js";
import { Dub } from "dub-package";
import { C as CredentialRepository } from "./credential-2kBaEJXl.js";
import { g as getAppKeysFromSlug } from "./getAppKeysFromSlug-S62aYXii.js";
import { r as refreshOAuthTokens } from "./refreshOAuthTokens-k3EbNmEo.js";
const dubAppKeysSchema = z.object({
  client_id: z.string(),
  client_secret: z.string(),
  redirect_uris: 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({ statusCode: 401, message: "You must be logged in to do this" });
  }
  if (!loggedInUser.email) {
    throw new HttpError({ statusCode: 400, message: "Session user must have an email" });
  }
  const { teamId } = req.query;
  const { client_id, redirect_uris } = await 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({
  GET: Promise.resolve({ default: defaultResponder(handler$1) })
});
async function handler(req, res) {
  const { code } = req.query;
  const state = decodeOAuthState(req);
  if (typeof code !== "string") {
    if (state?.onErrorReturnTo || state?.returnTo) {
      res.redirect(
        getSafeRedirectUrl(state.onErrorReturnTo) ?? getSafeRedirectUrl(state?.returnTo) ?? `${WEBAPP_URL}/apps/installed`
      );
      return;
    }
    throw new HttpError({ statusCode: 400, message: "`code` must be a string" });
  }
  if (!req.session?.user?.id) {
    throw new HttpError({ statusCode: 401, message: "You must be logged in to do this" });
  }
  const { client_id, redirect_uris, client_secret } = await 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({ appId: "dub", type: "dub" }, responseBody, req);
  res.redirect(
    getSafeRedirectUrl(state?.returnTo) ?? 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(credential) {
    this.client_id = "";
    this.client_secret = "";
    this.log = logger.getSubLogger({ prefix: ["[[lib]] dub"] });
    this.credential = credential;
    this.client_id = "";
    this.client_secret = "";
  }
  async initClient() {
    const appKeys = await 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 Dub({ token: token.access_token });
  }
  async refreshAccessToken(refreshToken) {
    try {
      if (!refreshToken)
        return;
      const newToken = await 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 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 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" }));
export {
  index$1 as api,
  index as lib
};
