/**
 * src/server/index.ts — Planu HTTP API server entry point
 *
 * SPEC-610: Lightweight HTTP API using Node's built-in http module.
 * No external framework dependencies.
 *
 * Usage:
 *   import { startServer } from './server/index.js';
 *   startServer(3000, '/path/to/project');
 */
import { createServer } from 'node:http';
import { Router } from './router.js';
import { handleHealth } from './routes/health.js';
import { handleOpenApi } from './routes/openapi.js';
import { handleCreateSpec, handleListSpecs, handleGetSpec, handleUpdateSpecStatus, handleValidateSpec, } from './routes/specs.js';
import { sendNotFound, sendInternalError } from './response.js';
/**
 * Build the application router with all registered routes.
 * Exported for use in tests (no server binding required).
 */
export function buildRouter() {
    const router = new Router();
    // Health
    router.get('/api/health', handleHealth);
    // OpenAPI spec (for LLM function calling)
    router.get('/api/openapi.json', handleOpenApi);
    // Spec CRUD
    router.get('/api/specs', handleListSpecs);
    router.post('/api/specs', handleCreateSpec);
    router.get('/api/specs/:id', handleGetSpec);
    router.patch('/api/specs/:id/status', handleUpdateSpecStatus);
    router.post('/api/specs/:id/validate', handleValidateSpec);
    return router;
}
/** Handle a single request — separated to allow void-returning wrapper. */
async function handleRequest(req, res, router, projectPath) {
    // Inject project path into request headers so routes can resolve it.
    // The headers object is a plain dict owned by the IncomingMessage — mutation is safe here.
    // eslint-disable-next-line no-param-reassign -- intentional header injection
    req.headers['x-planu-project-path'] = projectPath;
    // Handle CORS preflight
    if (req.method === 'OPTIONS') {
        res.setHeader('Access-Control-Allow-Origin', '*');
        res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PATCH, OPTIONS');
        res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
        res.writeHead(204);
        res.end();
        return;
    }
    try {
        const matched = await router.dispatch(req, res);
        if (!matched) {
            sendNotFound(res, `Route not found: ${req.method ?? 'UNKNOWN'} ${req.url ?? '/'}`);
        }
    }
    catch (err) {
        const message = err instanceof Error ? err.message : 'Internal server error';
        sendInternalError(res, message);
    }
}
/**
 * Start the Planu HTTP API server.
 *
 * @param port        - TCP port to listen on (default: 3000)
 * @param projectPath - Absolute path to the project directory (default: process.cwd())
 */
export function startServer(port = 3000, projectPath = process.cwd()) {
    const router = buildRouter();
    const server = createServer((req, res) => {
        void handleRequest(req, res, router, projectPath);
    });
    server.listen(port, () => {
        // eslint-disable-next-line no-console -- intentional startup log
        console.log(`Planu HTTP API listening on http://localhost:${String(port)}`);
        // eslint-disable-next-line no-console -- intentional startup log
        console.log(`Project path: ${projectPath}`);
    });
}
//# sourceMappingURL=index.js.map