import { ensureTrailingSlash } from './chunk-N67QHFFS.js';
import { init_esm_shims } from './chunk-H26U4HNL.js';
import consola from 'consola';
import { getRandomValues, subtle } from 'crypto';
import { createServer } from 'http';
import { exit } from 'process';
import { parse } from 'url';
import open from 'open';

// ../cli.common/build/esm/public/loginFlow.js
init_esm_shims();

// ../cli.common/build/esm/commands/auth/login/loginFlow.js
init_esm_shims();

// ../cli.common/build/esm/commands/auth/login/token.js
init_esm_shims();
function isTokenErrorResponse(response) {
  return response.error != null;
}

// ../cli.common/build/esm/commands/auth/login/loginFlow.js
var BROWSER_PROMPT_TIME_MS = 60 * 1e3;
async function invokeLoginFlow(args) {
  consola.start(`Authenticating using application id: ${args.clientId}`);
  const redirectUrl = "http://localhost:8080/auth/callback";
  const port = parse(redirectUrl).port;
  const foundryUrl = ensureTrailingSlash(args.foundryUrl);
  let resolve;
  const authCode = new Promise((_res) => {
    resolve = _res;
  });
  const server = createServer((req, res) => {
    const query = parse(req.url, true).query;
    res.end("Authenticated");
    resolve(query.code);
  });
  server.on("error", (e) => {
    if (e.code === "EADDRINUSE") {
      consola.error(`Port ${port} is already in use, unable to perform authentication flow.`);
      server.close();
      exit(1);
    }
  });
  server.listen(port);
  const clientId = args.clientId;
  const state = generateRandomString();
  const codeVerifier = generateRandomString();
  const codeChallenge = await generateCodeChallenge(codeVerifier);
  const authorizeUrl = generateAuthorizeUrl(foundryUrl, clientId, state, redirectUrl, codeChallenge);
  try {
    await open(authorizeUrl);
  } catch {
    consola.warn(`Unable to open browser, please open this url in your browser to to authenticate: ${authorizeUrl}`);
  }
  const browserPrompt = setTimeout(() => {
    consola.warn(`Still waiting for the authentication to complete. Please open a browser to ${authorizeUrl}`);
  }, BROWSER_PROMPT_TIME_MS);
  const code = await authCode;
  server.close();
  clearTimeout(browserPrompt);
  const token = await getTokenWithCodeVerifier(clientId, redirectUrl, code, foundryUrl, codeVerifier);
  if (isTokenErrorResponse(token)) {
    consola.error("Unable to authenticate", token.error, token.error_description);
    exit(1);
  }
  consola.success(`Successfully authenticated!`);
  return token;
}
function generateRandomString(length = 128) {
  const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
  const output = [];
  const array = new Uint8Array(1);
  const maxIndex = 256 - 256 % characters.length;
  while (output.length < length) {
    getRandomValues(array);
    if (array[0] < maxIndex) {
      output.push(characters[array[0] % characters.length]);
    }
  }
  return output.join("");
}
async function generateCodeChallenge(codeVerifier) {
  const data = new TextEncoder().encode(codeVerifier);
  const digest = await subtle.digest("SHA-256", data);
  const codeChallenge = btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\//g, "_").replace(/\+/g, "-").replace(/=/g, "");
  return {
    codeChallenge,
    codeChallengeMethod: "S256"
  };
}
function generateAuthorizeUrl(baseUrl, clientId, state, redirectUrl, codeChallenge) {
  const url = new URL("multipass/api/oauth2/authorize", baseUrl);
  url.searchParams.set("client_id", clientId);
  url.searchParams.set("response_type", "code");
  url.searchParams.set("state", state);
  url.searchParams.set("redirect_uri", redirectUrl);
  url.searchParams.set("code_challenge", codeChallenge.codeChallenge);
  url.searchParams.set("code_challenge_method", codeChallenge.codeChallengeMethod);
  url.searchParams.set("scope", ["offline_access", "api:read-data", "api:use-ontologies-read"].join(" "));
  return url.toString();
}
async function getTokenWithCodeVerifier(clientId, redirectUrl, code, baseUrl, codeVerifier) {
  const body = new URLSearchParams();
  body.append("client_id", clientId);
  body.append("grant_type", "authorization_code");
  body.append("code", code);
  body.append("redirect_uri", redirectUrl);
  body.append("code_verifier", codeVerifier);
  const tokenUrlObj = new URL("multipass/api/oauth2/token", baseUrl);
  tokenUrlObj.searchParams.set("state", codeVerifier);
  const tokenUrl = tokenUrlObj.toString();
  try {
    const response = await fetch(tokenUrl, {
      body: body.toString(),
      headers: {
        "Content-Type": "application/x-www-form-urlencoded"
      },
      method: "POST"
    });
    const responseText = await response.json();
    return responseText;
  } catch (e) {
    throw new Error(`Failed to get token: ${e?.cause?.toString() ?? e?.toString() ?? "Unknown error"}`);
  }
}

export { invokeLoginFlow };
//# sourceMappingURL=chunk-VSS3V6VA.js.map
//# sourceMappingURL=chunk-VSS3V6VA.js.map