/**
 * cli/commands/terminal.mjs — apt-tools terminal {spawn|list|status|health}
 *
 * Talks to the Electron-main AperantIpcServer over the per-user, per-pid
 * Unix-domain socket whose absolute path is in process.env.APERANT_IPC_SOCKET.
 *
 * All output is JSON to stdout. Exit codes:
 *   0 — success (request returned ok:true OR ok:false with structured error)
 *   1 — internal error / unexpected exception
 *   2 — preflight failure (not_in_aperant_terminal, electron_compute_unavailable)
 *
 * Custom error envelope shape `{error, message}` (not the standard
 * `{status:'error', error}`) preserved verbatim via the local terminalErr()
 * helper that returns { envelope, exitCode } tuples wrap() can consume.
 * The dispatch.mjs `terminal` handler keeps its `.catch` wrapper for
 * unhandled rejections — same byte-identical D-04 backward-compat as
 * taste-infer.
 */
import { connectSocket } from '../terminal/socket-client.mjs';
import { parseFlags } from '../util/args.mjs';
import { exitWith, ok } from '../util/result.mjs';
/**
 * Build the terminal custom error envelope. Returns the {envelope, exitCode}
 * tuple wrap() consumes.
 *
 * @param {string} code
 * @param {string} message
 * @param {number} exitCode
 */
function terminalErr(code, message, exitCode) {
    return exitWith({ error: code, message }, exitCode);
}
/**
 * Public entry point — dispatched from packages/framework/bin/apt-tools.mjs.
 *
 * @param {string} subcommand
 * @param {string[]} extraArgs
 */
export async function cmdTerminal(subcommand, extraArgs = []) {
    if (!subcommand || subcommand === '--help' || subcommand === '-h') {
        return terminalErr('usage', 'apt-tools terminal {spawn|list|status|health} [flags]', 1);
    }
    // Preflight: must be running inside an Aperant terminal.
    const socketPath = process.env.APERANT_IPC_SOCKET;
    if (!socketPath || socketPath.length === 0) {
        return terminalErr('not_in_aperant_terminal', 'APERANT_IPC_SOCKET is not set. apt-tools terminal commands only work inside an Aperant-spawned PTY (TERM_PROGRAM=Aperant).', 2);
    }
    const callerDepth = Number(process.env.APERANT_SPAWN_DEPTH ?? '0') || 0;
    const flags = parseFlags(extraArgs);
    let client;
    try {
        client = await connectSocket(socketPath);
    }
    catch (err) {
        const code = err && err.code === 'ENOENT' ? 'electron_compute_unavailable' : 'connect_failed';
        return terminalErr(code, code === 'electron_compute_unavailable'
            ? `Electron main is not running — socket file ${socketPath} does not exist.`
            : err instanceof Error
                ? err.message
                : String(err), 2);
    }
    try {
        switch (subcommand) {
            case 'spawn': {
                const worktreePath = flags.get('worktree');
                const taskId = flags.get('task');
                if (!worktreePath || worktreePath === true) {
                    return terminalErr('usage', '--worktree <path> is required', 1);
                }
                if (!taskId || taskId === true) {
                    return terminalErr('usage', '--task <id> is required', 1);
                }
                const payload = {
                    worktreePath: String(worktreePath),
                    taskId: String(taskId),
                    _callerDepth: callerDepth,
                };
                const instructions = flags.get('instructions');
                if (typeof instructions === 'string')
                    payload.instructions = instructions;
                const cli = flags.get('cli');
                if (typeof cli === 'string')
                    payload.cliType = cli;
                if (flags.get('yolo') === true)
                    payload.yoloMode = true;
                const res = await client.request('spawn', payload);
                return ok(res);
            }
            case 'list': {
                const res = await client.request('list', {});
                return ok(res);
            }
            case 'status': {
                const sessionId = flags.get('session');
                if (!sessionId || sessionId === true) {
                    return terminalErr('usage', '--session <id> is required', 1);
                }
                const res = await client.request('status', { sessionId: String(sessionId) });
                return ok(res);
            }
            case 'health': {
                const res = await client.request('health', {});
                return ok(res);
            }
            default:
                return terminalErr('usage', `Unknown subcommand: ${subcommand}. Use spawn|list|status|health.`, 1);
        }
    }
    catch (err) {
        // Errors from connectSocket().request — typed as { code, message }
        const code = err && typeof err === 'object' && 'code' in err ? err.code : 'request_failed';
        const message = err && typeof err === 'object' && 'message' in err
            ? err.message
            : err instanceof Error
                ? err.message
                : String(err);
        return terminalErr(code, message, 1);
    }
    finally {
        try {
            client?.close();
        }
        catch {
            /* ignore */
        }
    }
}
//# sourceMappingURL=terminal.mjs.map