/**
 * Terminal manager service.
 *
 * Manages PTY processes using node-pty. Tracks active terminals,
 * handles creation, stdin, resize, kill, and emits stdout/exit events.
 */
import { randomUUID } from "node:crypto";
import * as pty from "node-pty";
import { createTerminalSession, closeTerminalSession, } from "../db/repositories/terminal-sessions.js";
import { logger } from "../utils/logger.js";
const terminals = new Map();
let sendFn = null;
/**
 * Set the send function used to emit terminal events to the gateway.
 */
export function setTerminalSendFn(fn) {
    sendFn = fn;
}
/**
 * Create a new terminal PTY process for a project.
 */
export function createTerminal(projectId, projectPath, cols = 80, rows = 24) {
    const shell = process.env.SHELL || "/bin/bash";
    const terminalId = randomUUID();
    const ptyProcess = pty.spawn(shell, [], {
        name: "xterm-256color",
        cwd: projectPath,
        env: process.env,
        cols,
        rows,
    });
    const terminal = {
        id: terminalId,
        pty: ptyProcess,
        projectId,
    };
    terminals.set(terminalId, terminal);
    // Record in database
    createTerminalSession(projectId, ptyProcess.pid);
    // Forward stdout data
    ptyProcess.onData((data) => {
        if (!sendFn)
            return;
        const event = {
            type: "terminal_stdout",
            payload: { terminalId, data },
        };
        sendFn(event);
    });
    // Handle exit
    ptyProcess.onExit(({ exitCode, signal }) => {
        terminals.delete(terminalId);
        closeTerminalSession(terminalId);
        if (!sendFn)
            return;
        const event = {
            type: "terminal_exit",
            payload: { terminalId, exitCode, ...(signal !== undefined ? { signal } : {}) },
        };
        sendFn(event);
        logger.info(`Terminal ${terminalId} exited: code=${exitCode} signal=${signal}`);
    });
    logger.info(`Terminal ${terminalId} created for project ${projectId} (shell=${shell})`);
    return terminalId;
}
/**
 * Write data to a terminal's stdin.
 */
export function writeTerminal(terminalId, data) {
    const terminal = terminals.get(terminalId);
    if (!terminal) {
        throw new Error(`Terminal not found: ${terminalId}`);
    }
    terminal.pty.write(data);
}
/**
 * Resize a terminal.
 */
export function resizeTerminal(terminalId, cols, rows) {
    const terminal = terminals.get(terminalId);
    if (!terminal) {
        throw new Error(`Terminal not found: ${terminalId}`);
    }
    terminal.pty.resize(cols, rows);
}
/**
 * Kill a terminal.
 */
export function killTerminal(terminalId) {
    const terminal = terminals.get(terminalId);
    if (!terminal) {
        throw new Error(`Terminal not found: ${terminalId}`);
    }
    terminal.pty.kill();
    // Removal from map and DB happens in the onExit handler
}
/**
 * Get a terminal by ID, or undefined if not found.
 */
export function getTerminal(terminalId) {
    return terminals.get(terminalId);
}
/**
 * Kill all active terminals. Used during shutdown.
 */
export function killAllTerminals() {
    for (const [id, terminal] of terminals) {
        try {
            terminal.pty.kill();
        }
        catch {
            // Ignore errors during shutdown
        }
        closeTerminalSession(id);
    }
    terminals.clear();
}
//# sourceMappingURL=terminal-manager.js.map