import { HttpProxyAgent } from "http-proxy-agent";
import { HttpsProxyAgent } from "https-proxy-agent";
const DEFAULT_PROXY_PORTS = {
    ftp: 21,
    gopher: 70,
    http: 80,
    https: 443,
    ws: 80,
    wss: 443,
};
export const UNSUPPORTED_PROXY_PROTOCOL_MESSAGE = "Unsupported proxy protocol. SOCKS and PAC proxy URLs are not supported; use an HTTP or HTTPS proxy URL.";
function getProxyEnv(key) {
    return process.env[key.toLowerCase()] || process.env[key.toUpperCase()] || "";
}
function parseProxyTargetUrl(targetUrl) {
    if (targetUrl instanceof URL) {
        return targetUrl;
    }
    try {
        return new URL(targetUrl);
    }
    catch {
        return undefined;
    }
}
function shouldProxyHostname(hostname, port) {
    const noProxy = getProxyEnv("no_proxy").toLowerCase();
    if (!noProxy) {
        return true;
    }
    if (noProxy === "*") {
        return false;
    }
    return noProxy.split(/[,\s]/).every((proxy) => {
        if (!proxy) {
            return true;
        }
        const parsedProxy = proxy.match(/^(.+):(\d+)$/);
        let proxyHostname = parsedProxy ? parsedProxy[1] : proxy;
        const proxyPort = parsedProxy ? Number.parseInt(parsedProxy[2], 10) : 0;
        if (proxyPort && proxyPort !== port) {
            return true;
        }
        if (!/^[.*]/.test(proxyHostname)) {
            return hostname !== proxyHostname;
        }
        if (proxyHostname.startsWith("*")) {
            proxyHostname = proxyHostname.slice(1);
        }
        return !hostname.endsWith(proxyHostname);
    });
}
function getProxyForUrl(targetUrl) {
    const parsedUrl = parseProxyTargetUrl(targetUrl);
    if (!parsedUrl?.protocol || !parsedUrl.host) {
        return "";
    }
    const protocol = parsedUrl.protocol.split(":", 1)[0];
    const hostname = parsedUrl.host.replace(/:\d*$/, "");
    const port = Number.parseInt(parsedUrl.port, 10) || DEFAULT_PROXY_PORTS[protocol] || 0;
    if (!shouldProxyHostname(hostname, port)) {
        return "";
    }
    let proxy = getProxyEnv(`${protocol}_proxy`) || getProxyEnv("all_proxy");
    if (proxy && !proxy.includes("://")) {
        proxy = `${protocol}://${proxy}`;
    }
    return proxy;
}
export function resolveHttpProxyUrlForTarget(targetUrl) {
    const proxy = getProxyForUrl(targetUrl);
    if (!proxy) {
        return undefined;
    }
    let proxyUrl;
    try {
        proxyUrl = new URL(proxy);
    }
    catch (error) {
        throw new Error(`Invalid proxy URL ${JSON.stringify(proxy)}: ${error instanceof Error ? error.message : String(error)}`);
    }
    if (proxyUrl.protocol !== "http:" && proxyUrl.protocol !== "https:") {
        throw new Error(`${UNSUPPORTED_PROXY_PROTOCOL_MESSAGE} Got ${proxyUrl.protocol}`);
    }
    return proxyUrl;
}
export function createHttpProxyAgentsForTarget(targetUrl) {
    const proxyUrl = resolveHttpProxyUrlForTarget(targetUrl);
    if (!proxyUrl) {
        return undefined;
    }
    return {
        httpAgent: new HttpProxyAgent(proxyUrl),
        httpsAgent: new HttpsProxyAgent(proxyUrl),
    };
}
