import { logger } from '../../utils/logger.js';
import { summarizeError } from '../../utils/error-display.js';
/**
 * Run a shell command hook.
 * The event JSON is written to stdin; stdout is parsed as HookResult JSON.
 * If stdout is not valid JSON, returns { ok: true } (fire-and-forget semantics).
 */
export async function run(hook, event) {
    const command = hook.command;
    if (!command) {
        return { ok: false, error: 'command hook missing "command" field' };
    }
    const timeoutMs = (hook.timeout ?? 30) * 1000;
    const eventJson = JSON.stringify(event);
    try {
        const proc = Bun.spawn(['/bin/sh', '-c', command], {
            stdin: 'pipe',
            stdout: 'pipe',
            stderr: 'pipe',
        });
        // Write event JSON to stdin then close
        const encoder = new TextEncoder();
        proc.stdin.write(encoder.encode(eventJson));
        proc.stdin.end();
        // Kill the process on timeout; always clear the timer on success.
        const timer = setTimeout(() => {
            try {
                proc.kill();
            }
            catch { /* already exited */ }
        }, timeoutMs);
        let exitCode;
        try {
            exitCode = await proc.exited;
            clearTimeout(timer);
        }
        catch (err) {
            clearTimeout(timer);
            try {
                proc.kill();
            }
            catch { /* already dead */ }
            throw err;
        }
        const stdout = await new Response(proc.stdout).text();
        const stderr = await new Response(proc.stderr).text();
        if (exitCode !== 0) {
            logger.error('command hook exited with non-zero code', {
                command,
                exitCode,
                stderr: stderr.slice(0, 500),
            });
            return {
                ok: false,
                error: `command exited with code ${exitCode}${stderr ? ': ' + stderr.slice(0, 200) : ''}`,
            };
        }
        const trimmed = stdout.trim();
        if (!trimmed) {
            return { ok: true };
        }
        try {
            const result = JSON.parse(trimmed);
            // Use the parsed ok value if present, default to true otherwise
            return { ...result, ok: result.ok ?? true };
        }
        catch {
            // Non-JSON output is acceptable; treat as success
            return { ok: true };
        }
    }
    catch (err) {
        const message = summarizeError(err);
        logger.error('command hook error', { command, error: message });
        return { ok: false, error: message };
    }
}
