// engine/dashboard/server.ts — Singleton HTTP server for the Planu dashboard.
// Binds to 127.0.0.1 (localhost-only). Runs in the same process as the MCP server.
import { createServer } from 'node:http';
import { handleRequest } from './routes.js';
/** Singleton state — lives as long as the process */
const state = {
    port: 5050,
    isRunning: false,
    startedAt: null,
};
let httpServer = null;
/** Returns a copy of the current server state */
export function getDashboardState() {
    return { ...state };
}
/** Start the dashboard HTTP server on the given port (default 5050).
 *  Resolves with the URL on success, rejects with a descriptive error if the
 *  port is already in use or if the server is already running. */
export async function startDashboardServer(port = 5050) {
    if (state.isRunning) {
        return `http://localhost:${state.port}`;
    }
    return new Promise((resolve, reject) => {
        const server = createServer((req, res) => {
            /* v8 ignore start */
            handleRequest(req, res).catch((err) => {
                const message = err instanceof Error ? err.message : String(err);
                res.writeHead(500, { 'Content-Type': 'application/json' });
                res.end(JSON.stringify({ error: message }));
            });
            /* v8 ignore stop */
        });
        server.once('error', (err) => {
            if (err.code === 'EADDRINUSE') {
                reject(new Error(`El puerto ${port} ya está en uso. Elige otro puerto con el parámetro port.`));
                /* v8 ignore next 3 */
            }
            else {
                reject(err);
            }
        });
        server.listen(port, '127.0.0.1', () => {
            httpServer = server;
            state.port = port;
            state.isRunning = true;
            state.startedAt = new Date();
            resolve(`http://localhost:${port}`);
        });
    });
}
/** Stop the dashboard HTTP server.
 *  Resolves with a confirmation message. If no server is running, resolves
 *  with the "not active" message. */
export async function stopDashboardServer() {
    if (!state.isRunning || httpServer === null) {
        return 'No hay dashboard activo.';
    }
    const port = state.port;
    const serverToClose = httpServer;
    return new Promise((resolve, reject) => {
        serverToClose.close((err) => {
            /* v8 ignore start */
            if (err) {
                reject(err);
                return;
            }
            /* v8 ignore stop */
            httpServer = null;
            state.isRunning = false;
            state.startedAt = null;
            resolve(`Dashboard detenido. Puerto ${port} liberado.`);
        });
    });
}
/** Register cleanup handlers so the server stops when the process exits */
export function registerCleanupHandlers() {
    /* v8 ignore start */
    const cleanup = () => {
        if (state.isRunning && httpServer !== null) {
            httpServer.close();
        }
    };
    /* v8 ignore stop */
    process.once('exit', cleanup);
    process.once('SIGTERM', cleanup);
    process.once('SIGINT', cleanup);
}
//# sourceMappingURL=server.js.map