import { spawn } from "node:child_process"

export type CommandResult = {
    stdout: string
    stderr: string
    code: number
}

export const commandExists = (command: string) =>
    new Promise<boolean>((resolve) => {
        const child = spawn("sh", ["-lc", `command -v ${command}`])
        child.on("error", () => resolve(false))
        child.on("close", (code) => resolve(code === 0))
    })

export const runCommand = (
    command: string,
    args: string[],
    options: { timeoutMs?: number } = {}
) =>
    new Promise<CommandResult>((resolve, reject) => {
        const child = spawn(command, args, {
            stdio: ["ignore", "pipe", "pipe"],
        })

        const stdout: Buffer[] = []
        const stderr: Buffer[] = []

        const timeout = options.timeoutMs
            ? setTimeout(() => {
                child.kill("SIGTERM")
                reject(new Error(`${command} wurde nach ${options.timeoutMs} ms beendet`))
            }, options.timeoutMs)
            : null

        child.stdout.on("data", (chunk) => stdout.push(Buffer.from(chunk)))
        child.stderr.on("data", (chunk) => stderr.push(Buffer.from(chunk)))
        child.on("error", reject)
        child.on("close", (code) => {
            if (timeout) clearTimeout(timeout)

            resolve({
                stdout: Buffer.concat(stdout).toString("utf8"),
                stderr: Buffer.concat(stderr).toString("utf8"),
                code: code ?? 0,
            })
        })
    })
