import { execFile, spawn } from "node:child_process";
import { extname } from "node:path";
import { promisify } from "node:util";
import { createExternalCommandProcessEnv } from "../server/paseo-env.js";
import { isWindowsCommandScript, quoteWindowsArgument, quoteWindowsCommand, } from "./windows-command.js";
const execFileAsync = promisify(execFile);
function hasPathSeparator(value) {
    return value.includes("/") || value.includes("\\");
}
const WINDOWS_CREATE_NO_WINDOW = 0x08000000;
function shouldUseWindowsShell(command, requestedShell) {
    if (isWindowsCommandScript(command)) {
        return true;
    }
    if (requestedShell !== undefined) {
        return requestedShell;
    }
    return process.platform === "win32" && !hasPathSeparator(command) && !extname(command);
}
export function spawnProcess(command, args, options) {
    const { baseEnv, env, envOverlay, ...spawnOptions } = options ?? {};
    const resolvedBaseEnv = env ?? baseEnv ?? process.env;
    const isWindows = process.platform === "win32";
    const shell = shouldUseWindowsShell(command, spawnOptions.shell);
    const shouldQuoteForShell = isWindows && shell !== false;
    const resolvedCommand = shouldQuoteForShell ? quoteWindowsCommand(command) : command;
    const resolvedArgs = shouldQuoteForShell ? args.map(quoteWindowsArgument) : args;
    const childEnv = options?.envMode === "internal"
        ? { ...resolvedBaseEnv, ...envOverlay }
        : createExternalCommandProcessEnv(command, resolvedBaseEnv, ...(envOverlay ? [envOverlay] : []));
    const wantsBackground = spawnOptions.detached === true;
    const win32Background = isWindows && wantsBackground
        ? {
            detached: false,
            creationFlags: WINDOWS_CREATE_NO_WINDOW,
        }
        : {};
    return spawn(resolvedCommand, resolvedArgs, {
        ...spawnOptions,
        ...win32Background,
        env: childEnv,
        shell,
        windowsHide: true,
    });
}
export async function execCommand(command, args, options) {
    const { baseEnv, env, envOverlay } = options ?? {};
    const resolvedBaseEnv = env ?? baseEnv ?? process.env;
    const isWindows = process.platform === "win32";
    const shell = shouldUseWindowsShell(command, options?.shell);
    const shouldQuoteForShell = isWindows && shell !== false;
    const resolvedCommand = shouldQuoteForShell ? quoteWindowsCommand(command) : command;
    const resolvedArgs = shouldQuoteForShell ? args.map(quoteWindowsArgument) : args;
    const childEnv = options?.envMode === "internal"
        ? { ...resolvedBaseEnv, ...envOverlay }
        : createExternalCommandProcessEnv(command, resolvedBaseEnv, ...(envOverlay ? [envOverlay] : []));
    return execFileAsync(resolvedCommand, resolvedArgs, {
        cwd: options?.cwd,
        env: childEnv,
        encoding: options?.encoding ?? "utf8",
        killSignal: options?.killSignal,
        timeout: options?.timeout,
        maxBuffer: options?.maxBuffer,
        shell,
        windowsHide: true,
    });
}
export function platformShell() {
    if (process.platform === "win32") {
        return { command: "cmd.exe", flag: ["/c"] };
    }
    return { command: "/bin/sh", flag: ["-lc"] };
}
export function platformBash() {
    if (process.platform === "win32") {
        return { command: "cmd.exe", flag: ["/c"] };
    }
    return { command: "/bin/bash", flag: ["-lc"] };
}
//# sourceMappingURL=spawn.js.map