// engine/dashboard/routes.ts — HTTP route handlers for the dashboard server.
// Pattern matches req.url and dispatches to the appropriate handler.
import { loadAllProjects, loadProject, loadSpecDetail, computeHealthMetrics, loadUsageStats, loadProjectMetrics, loadProjectHealthScore, loadProjectEvents, } from './data-loader.js';
import { renderHomePage, renderProjectPage, renderSpecPage, render404Page, } from './templates-project.js';
import { updateSpecStatus } from './spec-updater.js';
/** Send an HTML response */
function sendHtml(res, status, html) {
    res.writeHead(status, {
        'Content-Type': 'text/html; charset=utf-8',
        'Cache-Control': 'no-cache',
    });
    res.end(html);
}
/** Send a JSON response */
function sendJson(res, status, data) {
    const body = JSON.stringify(data);
    res.writeHead(status, {
        'Content-Type': 'application/json; charset=utf-8',
        'Cache-Control': 'no-cache',
    });
    res.end(body);
}
/** Extract path segments ignoring empty strings and query */
function parsePath(url) {
    const withoutQuery = url.split('?')[0] ?? '';
    return withoutQuery.split('/').filter((s) => s.length > 0);
}
/** Extract query parameters from a URL string */
function parseQuery(url) {
    const qIndex = url.indexOf('?');
    return new URLSearchParams(qIndex >= 0 ? url.slice(qIndex + 1) : '');
}
/** Handle GET / — home page with project list */
async function handleHome(res) {
    const [projects, usage] = await Promise.all([loadAllProjects(), loadUsageStats()]);
    sendHtml(res, 200, renderHomePage(projects, usage));
}
/** Handle GET /project/:id */
async function handleProjectPage(res, projectId) {
    const [project, usage] = await Promise.all([loadProject(projectId), loadUsageStats()]);
    if (!project) {
        sendHtml(res, 404, render404Page(`/project/${projectId}`));
        return;
    }
    const metrics = computeHealthMetrics(project);
    sendHtml(res, 200, renderProjectPage(project, metrics, usage));
}
/** Handle GET /spec/:projectId/:specId */
async function handleSpecPage(res, projectId, specId) {
    const [project, detail] = await Promise.all([
        loadProject(projectId),
        loadSpecDetail(projectId, specId),
    ]);
    const projectName = project?.name ?? projectId;
    sendHtml(res, 200, renderSpecPage(projectId, projectName, specId, detail.hu, detail.ficha, detail.progress));
}
/** Handle GET /api/projects */
async function handleApiProjects(res) {
    const projects = await loadAllProjects();
    sendJson(res, 200, projects);
}
/** Handle GET /api/project/:id */
async function handleApiProject(res, projectId) {
    const project = await loadProject(projectId);
    if (!project) {
        sendJson(res, 404, { error: 'Project not found' });
        return;
    }
    sendJson(res, 200, project);
}
/** Handle GET /api/usage */
async function handleApiUsage(res) {
    const usage = await loadUsageStats();
    sendJson(res, 200, usage);
}
/** Read the request body as a string */
export function readBody(req) {
    return new Promise((resolve, reject) => {
        const chunks = [];
        req.on('data', (chunk) => {
            chunks.push(chunk);
        });
        req.on('end', () => {
            resolve(Buffer.concat(chunks).toString('utf-8'));
        });
        req.on('error', reject);
    });
}
/** Handle PATCH /api/spec/:projectId/:specId */
async function handlePatchSpec(res, projectId, specId, body) {
    let parsed;
    try {
        parsed = JSON.parse(body);
    }
    catch {
        sendJson(res, 400, { error: 'Invalid JSON body' });
        return;
    }
    if (!parsed.status) {
        sendJson(res, 400, { error: 'Missing status field' });
        return;
    }
    const result = await updateSpecStatus(projectId, specId, parsed.status);
    const statusCode = result.success ? 200 : 400;
    sendJson(res, statusCode, result);
}
/** Handle GET /api/project/:id/metrics */
async function handleApiProjectMetrics(res, projectId) {
    const metrics = await loadProjectMetrics(projectId);
    sendJson(res, 200, metrics);
}
/** Handle GET /api/project/:id/health */
async function handleApiProjectHealth(res, projectId) {
    const health = await loadProjectHealthScore(projectId);
    sendJson(res, 200, health);
}
/** Handle GET /api/events/:projectId?since=timestamp */
async function handleApiEvents(res, projectId, since) {
    const events = await loadProjectEvents(projectId, since);
    sendJson(res, 200, events);
}
/** Dispatch GET /api/... routes. Returns true if handled. */
async function dispatchApiRoute(res, segments, url) {
    if (segments[1] === 'projects' && segments.length === 2) {
        await handleApiProjects(res);
        return true;
    }
    if (segments[1] === 'project' && segments[2] !== undefined) {
        if (segments[3] === 'metrics' && segments.length === 4) {
            await handleApiProjectMetrics(res, decodeURIComponent(segments[2]));
            return true;
        }
        if (segments[3] === 'health' && segments.length === 4) {
            await handleApiProjectHealth(res, decodeURIComponent(segments[2]));
            return true;
        }
        if (segments.length === 3) {
            await handleApiProject(res, decodeURIComponent(segments[2]));
            return true;
        }
    }
    if (segments[1] === 'events' && segments[2] !== undefined && segments.length === 3) {
        const query = parseQuery(url);
        const since = query.get('since') ?? new Date(0).toISOString();
        await handleApiEvents(res, decodeURIComponent(segments[2]), since);
        return true;
    }
    if (segments[1] === 'usage' && segments.length === 2) {
        await handleApiUsage(res);
        return true;
    }
    return false;
}
/** Dispatch PATCH routes. Returns true if handled. */
async function dispatchPatchRoute(req, res, segments) {
    if (segments[0] === 'api' &&
        segments[1] === 'spec' &&
        segments[2] !== undefined &&
        segments[3] !== undefined) {
        const body = await readBody(req);
        await handlePatchSpec(res, decodeURIComponent(segments[2]), decodeURIComponent(segments[3]), body);
        return true;
    }
    return false;
}
/** Main route dispatcher — called by the HTTP server for every request */
export async function handleRequest(req, res) {
    const method = req.method ?? 'GET';
    const url = req.url ?? '/';
    const segments = parsePath(url);
    try {
        if (method === 'PATCH') {
            const handled = await dispatchPatchRoute(req, res, segments);
            if (!handled) {
                sendJson(res, 405, { error: 'Method not allowed' });
            }
            return;
        }
        if (method !== 'GET') {
            sendJson(res, 405, { error: 'Method not allowed' });
            return;
        }
        if (segments.length === 0) {
            await handleHome(res);
            return;
        }
        if (segments[0] === 'api') {
            const handled = await dispatchApiRoute(res, segments, url);
            if (!handled) {
                sendJson(res, 404, { error: 'API endpoint not found' });
            }
            return;
        }
        if (segments[0] === 'project' && segments[1] !== undefined) {
            await handleProjectPage(res, decodeURIComponent(segments[1]));
            return;
        }
        if (segments[0] === 'spec' && segments[1] !== undefined && segments[2] !== undefined) {
            await handleSpecPage(res, decodeURIComponent(segments[1]), decodeURIComponent(segments[2]));
            return;
        }
        sendHtml(res, 404, render404Page(url));
    }
    catch (err) {
        const message = err instanceof Error ? err.message : String(err);
        sendJson(res, 500, { error: message });
    }
}
//# sourceMappingURL=routes.js.map