import { http, https } from "follow-redirects";
import { HttpProxyAgent } from "http-proxy-agent";
import { globalAgent } from "https";
import { HttpsProxyAgent } from "https-proxy-agent";
import fetch from "node-fetch";
import * as fs from "node:fs";
import tls from "node:tls";
export function fetchwithRequestOptions(url_, init, requestOptions) {
    let url = url_;
    if (typeof url === "string") {
        url = new URL(url);
    }
    const TIMEOUT = 7200; // 7200 seconds = 2 hours
    let globalCerts = [];
    if (process.env.IS_BINARY) {
        if (Array.isArray(globalAgent.options.ca)) {
            globalCerts = [...globalAgent.options.ca.map((cert) => cert.toString())];
        }
        else if (typeof globalAgent.options.ca !== "undefined") {
            globalCerts.push(globalAgent.options.ca.toString());
        }
    }
    const ca = Array.from(new Set([...tls.rootCertificates, ...globalCerts]));
    const customCerts = typeof requestOptions?.caBundlePath === "string"
        ? [requestOptions?.caBundlePath]
        : requestOptions?.caBundlePath;
    if (customCerts) {
        ca.push(...customCerts.map((customCert) => fs.readFileSync(customCert, "utf8")));
    }
    const timeout = (requestOptions?.timeout ?? TIMEOUT) * 1000; // measured in ms
    const agentOptions = {
        ca,
        rejectUnauthorized: requestOptions?.verifySsl,
        timeout,
        sessionTimeout: timeout,
        keepAlive: true,
        keepAliveMsecs: timeout,
    };
    const proxy = requestOptions?.proxy;
    // Create agent
    const protocol = url.protocol === "https:" ? https : http;
    const agent = proxy
        ? protocol === https
            ? new HttpsProxyAgent(proxy, agentOptions)
            : new HttpProxyAgent(proxy, agentOptions)
        : new protocol.Agent(agentOptions);
    let headers = {};
    for (const [key, value] of Object.entries(init?.headers || {})) {
        headers[key] = value;
    }
    headers = {
        ...headers,
        ...requestOptions?.headers,
    };
    // Replace localhost with 127.0.0.1
    if (url.hostname === "localhost") {
        url.hostname = "127.0.0.1";
    }
    // add extra body properties if provided
    let updatedBody = undefined;
    try {
        if (requestOptions?.extraBodyProperties && typeof init?.body === "string") {
            const parsedBody = JSON.parse(init.body);
            updatedBody = JSON.stringify({
                ...parsedBody,
                ...requestOptions.extraBodyProperties,
            });
        }
    }
    catch (e) {
        console.log("Unable to parse HTTP request body: ", e);
    }
    // fetch the request with the provided options
    const resp = fetch(url, {
        ...init,
        body: updatedBody ?? init?.body,
        headers: headers,
        agent: agent,
    });
    return resp;
}
