"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const express_1 = __importDefault(require("express"));
const zod_1 = require("zod");
const criticalPathAiSummary_1 = require("../services/criticalPathAiSummary");
const criticalPathAnalyzer_1 = require("../services/criticalPathAnalyzer");
const traceProcessorService_1 = require("../services/traceProcessorService");
const router = express_1.default.Router();
const traceProcessorService = (0, traceProcessorService_1.getTraceProcessorService)();
// Codex P1-5: this route does NOT pass through agentRoutes' explicit whitelist,
// so input validation has to live here. zod gives us a clamped, schema-checked
// option object — anything not declared here silently never reaches the runtime.
const intLike = zod_1.z.union([
    zod_1.z.number().int(),
    zod_1.z.string().regex(/^-?\d+$/, 'must be an integer string'),
]);
const AnalyzeBodySchema = zod_1.z.object({
    threadStateId: intLike.optional(),
    utid: intLike.optional(),
    startTs: intLike.optional(),
    dur: intLike.optional(),
    endTs: intLike.optional(),
    maxSegments: zod_1.z.number().int().min(20).max(1000).optional(),
    recursionDepth: zod_1.z.number().int().min(0).max(2).optional(),
    recursionEnabled: zod_1.z.boolean().optional(),
    segmentBudget: zod_1.z.number().int().min(4).max(32).optional(),
    includeAi: zod_1.z.boolean().optional(),
    question: zod_1.z.string().max(500).optional(),
});
function errorMessage(error, fallback) {
    return error instanceof Error ? error.message : fallback;
}
async function ensureTrace(traceId) {
    const trace = await traceProcessorService.getOrLoadTrace(traceId);
    return !!trace;
}
router.post('/:traceId/analyze', async (req, res) => {
    try {
        const { traceId } = req.params;
        if (!traceId) {
            return res.status(400).json({ success: false, error: 'traceId is required' });
        }
        if (!(await ensureTrace(traceId))) {
            return res.status(404).json({ success: false, error: `Trace ${traceId} not found` });
        }
        const parsed = AnalyzeBodySchema.safeParse(req.body ?? {});
        if (!parsed.success) {
            return res.status(400).json({
                success: false,
                error: 'Invalid request body',
                issues: parsed.error.issues.map((issue) => ({
                    path: issue.path.join('.'),
                    message: issue.message,
                })),
            });
        }
        const body = parsed.data;
        const analyzeOptions = {
            threadStateId: body.threadStateId,
            utid: body.utid,
            startTs: body.startTs,
            dur: body.dur,
            endTs: body.endTs,
            maxSegments: body.maxSegments,
            recursionDepth: body.recursionDepth,
            recursionEnabled: body.recursionEnabled,
            segmentBudget: body.segmentBudget,
        };
        const analysis = await (0, criticalPathAnalyzer_1.analyzeCriticalPath)(traceProcessorService, traceId, analyzeOptions);
        const aiSummary = body.includeAi === false ? undefined : await (0, criticalPathAiSummary_1.summarizeCriticalPathWithAi)(analysis, body.question);
        return res.json({ success: true, analysis, aiSummary });
    }
    catch (error) {
        console.error('[CriticalPath] Analyze error:', error);
        return res.status(500).json({
            success: false,
            error: errorMessage(error, 'Critical path analysis failed'),
        });
    }
});
exports.default = router;
//# sourceMappingURL=criticalPathRoutes.js.map