/**
 * Background Task Manager
 *
 * Launches and manages background shell commands, capturing output
 * and providing status tracking.
 */
import { spawn } from 'child_process';
import { logger } from '../utils/logger.js';
const MAX_OUTPUT_BYTES = 1024 * 1024; // 1MB
/**
 * BackgroundTaskManager spawns and tracks background shell commands.
 */
export class BackgroundTaskManager {
    tasks = new Map();
    processes = new Map();
    counter = 0;
    /**
     * Launch a command in the background.
     * Returns the task ID.
     */
    launchTask(command) {
        this.counter++;
        const id = `bg-${this.counter}`;
        const task = {
            id,
            command,
            startTime: Date.now(),
            status: 'running',
            output: '',
        };
        this.tasks.set(id, task);
        const child = spawn('sh', ['-c', command], {
            detached: true,
            stdio: ['ignore', 'pipe', 'pipe'],
        });
        this.processes.set(id, child);
        const appendOutput = (data) => {
            const t = this.tasks.get(id);
            if (t && t.output.length < MAX_OUTPUT_BYTES) {
                const remaining = MAX_OUTPUT_BYTES - t.output.length;
                t.output += data.toString('utf-8').slice(0, remaining);
            }
        };
        if (child.stdout) {
            child.stdout.on('data', appendOutput);
        }
        if (child.stderr) {
            child.stderr.on('data', appendOutput);
        }
        child.on('close', (code) => {
            const t = this.tasks.get(id);
            if (t) {
                t.exitCode = code ?? 1;
                t.status = code === 0 ? 'completed' : 'failed';
            }
            this.processes.delete(id);
            logger.debug(`[BackgroundTaskManager] Task ${id} finished with code ${code}`);
        });
        child.on('error', (err) => {
            const t = this.tasks.get(id);
            if (t) {
                t.status = 'failed';
                t.output += `\nError: ${err.message}`;
            }
            this.processes.delete(id);
            logger.debug(`[BackgroundTaskManager] Task ${id} error: ${err.message}`);
        });
        logger.debug(`[BackgroundTaskManager] Launched task ${id}: ${command}`);
        return id;
    }
    /**
     * Get the output for a task, optionally filtered by regex.
     */
    getTaskOutput(taskId, filter) {
        const task = this.tasks.get(taskId);
        if (!task) {
            return '';
        }
        if (!filter) {
            return task.output;
        }
        return task.output
            .split('\n')
            .filter((line) => filter.test(line))
            .join('\n');
    }
    /**
     * Get a task by ID.
     */
    getTask(taskId) {
        const task = this.tasks.get(taskId);
        if (!task)
            return undefined;
        return { ...task };
    }
    /**
     * List all tasks.
     */
    listTasks() {
        return Array.from(this.tasks.values()).map((t) => ({ ...t }));
    }
    /**
     * Kill a running task.
     */
    killTask(taskId) {
        const child = this.processes.get(taskId);
        if (!child) {
            return false;
        }
        try {
            if (child.pid) {
                process.kill(-child.pid, 'SIGTERM');
            }
            else {
                child.kill('SIGTERM');
            }
        }
        catch {
            child.kill('SIGTERM');
        }
        const task = this.tasks.get(taskId);
        if (task) {
            task.status = 'failed';
            task.exitCode = 137;
        }
        this.processes.delete(taskId);
        return true;
    }
    /**
     * Kill all running tasks (for process exit cleanup).
     */
    cleanup() {
        for (const [id] of this.processes) {
            this.killTask(id);
        }
        logger.debug('[BackgroundTaskManager] All tasks cleaned up');
    }
}
// Singleton
let instance = null;
export function getBackgroundTaskManager() {
    if (!instance) {
        instance = new BackgroundTaskManager();
    }
    return instance;
}
export function resetBackgroundTaskManager() {
    if (instance) {
        instance.cleanup();
    }
    instance = null;
}
//# sourceMappingURL=background-tasks.js.map