import { isRelativePath as F } from "@scalar/helpers/url/is-relative-path";
import { makeUrlAbsolute as A } from "@scalar/helpers/url/make-url-absolute";
import { shouldUseProxy as R } from "@scalar/helpers/url/redirect-to-proxy";
import { encode as T, fromUint8Array as E } from "js-base64";
import { getServerUrl as b } from "../../operation-block/helpers/get-server-url.js";
const z = (t, e = {}) => {
  const i = b(t, e);
  return i ? F(i) ? typeof window > "u" ? {} : { basePath: i } : { baseUrl: i } : {};
}, $ = () => {
  const t = new Uint8Array(32);
  return crypto.getRandomValues(t), E(t, !0);
}, L = async (t, e) => {
  if (e === "plain")
    return t;
  if (typeof crypto?.subtle?.digest != "function")
    return console.warn("SHA-256 is only supported when using https, using a plain text code challenge instead."), t;
  const u = new TextEncoder().encode(t), m = await crypto.subtle.digest("SHA-256", u);
  return E(new Uint8Array(m), !0);
}, B = async (t, e, i, u, m, g = {}) => {
  const f = t[e];
  try {
    if (!f)
      return [new Error("Flow not found"), null];
    const p = i.join(" ");
    if (e === "clientCredentials" || e === "password")
      return C(
        t,
        e,
        p,
        {
          proxyUrl: m
        },
        u,
        g
      );
    const r = (Math.random() + 1).toString(36).substring(2, 10), a = A(
      t[e]["x-scalar-secret-auth-url"] ?? t[e].authorizationUrl,
      z(u, g)
    ), n = new URL(a);
    let c = null;
    if (e === "implicit")
      n.searchParams.set("response_type", "token");
    else if (e === "authorizationCode") {
      const s = t[e];
      if (n.searchParams.set("response_type", "code"), s["x-usePkce"] !== "no") {
        const o = $(), d = await L(o, s["x-usePkce"]);
        c = {
          codeVerifier: o,
          codeChallenge: d,
          codeChallengeMethod: s["x-usePkce"] === "SHA-256" ? "S256" : "plain"
        }, n.searchParams.set("code_challenge", d), n.searchParams.set("code_challenge_method", c.codeChallengeMethod);
      }
    }
    const l = t[e];
    if (l["x-scalar-secret-redirect-uri"].startsWith("/")) {
      const s = b(u, g) || window.location.origin + window.location.pathname, o = new URL(l["x-scalar-secret-redirect-uri"], s).toString();
      n.searchParams.set("redirect_uri", o);
    } else
      n.searchParams.set("redirect_uri", l["x-scalar-secret-redirect-uri"]);
    f["x-scalar-security-query"] && Object.keys(f["x-scalar-security-query"]).forEach((s) => {
      const o = f["x-scalar-security-query"]?.[s];
      o && n.searchParams.set(s, o);
    }), n.searchParams.set("client_id", f["x-scalar-secret-client-id"]), n.searchParams.set("state", r), p && n.searchParams.set("scope", p);
    const w = window.open(n, "openAuth2Window", "left=100,top=100,width=800,height=600");
    return w ? new Promise((s) => {
      const o = setInterval(() => {
        let d = null, _ = null, x = null, P = null, y = null;
        try {
          const h = new URL(w.location.href).searchParams, S = f["x-tokenName"] || "access_token";
          d = h.get(S), _ = h.get("refresh_token"), x = h.get("code"), P = h.get("error"), y = h.get("error_description");
          const k = new URLSearchParams(w.location.href.split("#")[1]);
          d ||= k.get(S), _ ||= k.get("refresh_token"), x ||= k.get("code"), P ||= k.get("error"), y ||= k.get("error_description");
        } catch {
        }
        if (w.closed || d || x || P)
          if (clearInterval(o), w.close(), P)
            s([new Error(`OAuth error: ${P}${y ? ` (${y})` : ""}`), null]);
          else if (d) {
            const h = w.location.href.match(/state=([^&]*)/)?.[1];
            s(h === r ? [null, { accessToken: d, ..._ ? { refreshToken: _ } : {} }] : [new Error("State mismatch"), null]);
          } else x && e === "authorizationCode" ? new URL(w.location.href).searchParams.get("state") === r ? C(
            t,
            e,
            p,
            {
              code: x,
              pkce: c,
              proxyUrl: m
            },
            u,
            g
          ).then(s) : s([new Error("State mismatch"), null]) : (clearInterval(o), s([new Error("Window was closed without granting authorization"), null]));
      }, 200);
    }) : [new Error("Failed to open auth window"), null];
  } catch {
    return [new Error("Failed to authorize oauth2 flow"), null];
  }
}, C = async (t, e, i, {
  code: u,
  pkce: m,
  proxyUrl: g
} = {}, f, p = {}) => {
  const r = t[e];
  if (!r)
    return [new Error("OAuth2 flow was not defined"), null];
  const a = new URLSearchParams();
  i && (e === "clientCredentials" || e === "password") && a.set("scope", i);
  const n = r["x-scalar-credentials-location"] === "body";
  if (n && (a.set("client_id", r["x-scalar-secret-client-id"]), a.set("client_secret", r["x-scalar-secret-client-secret"])), "x-scalar-secret-redirect-uri" in r && r["x-scalar-secret-redirect-uri"] && a.set("redirect_uri", r["x-scalar-secret-redirect-uri"]), u)
    a.set("code", u), a.set("grant_type", "authorization_code"), m && a.set("code_verifier", m.codeVerifier);
  else if (e === "password") {
    const c = t[e];
    a.set("grant_type", "password"), a.set("username", c["x-scalar-secret-username"]), a.set("password", c["x-scalar-secret-password"]);
  } else
    a.set("grant_type", "client_credentials");
  r["x-scalar-security-body"] && Object.entries(r["x-scalar-security-body"]).forEach(([c, l]) => {
    l && a.set(c, String(l));
  });
  try {
    const c = {
      "Content-Type": "application/x-www-form-urlencoded"
    };
    n || (c.Authorization = `Basic ${T(`${r["x-scalar-secret-client-id"]}:${r["x-scalar-secret-client-secret"]}`)}`);
    const l = A(
      r["x-scalar-secret-token-url"] ?? r.tokenUrl,
      z(f, p)
    ), U = R(g, l) ? `${g}?${new URLSearchParams([["scalar_url", l]]).toString()}` : l, s = await (await fetch(U, {
      method: "POST",
      headers: c,
      body: a
    })).json(), o = r["x-tokenName"] || "access_token", d = s[o], _ = s.refresh_token;
    return [null, { accessToken: d, ...typeof _ == "string" ? { refreshToken: _ } : {} }];
  } catch {
    return [new Error("Failed to get an access token. Please check your credentials."), null];
  }
};
export {
  B as authorizeOauth2
};
