"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createTraceRouter = createTraceRouter;
const express_1 = __importDefault(require("express"));
const traceRepository_js_1 = require("../../repositories/traceRepository.js");
const createTrace_js_1 = require("../../use-cases/createTrace.js");
const bulkCreateTraces_js_1 = require("../../use-cases/bulkCreateTraces.js");
const projectRepository_js_1 = require("../../repositories/projectRepository.js");
const getTraceById_js_1 = require("../../use-cases/getTraceById.js");
const getTracesByProjectId_js_1 = require("../../use-cases/getTracesByProjectId.js");
const updateTrace_js_1 = require("../../use-cases/updateTrace.js");
const createSpan_js_1 = require("../../use-cases/createSpan.js");
const getSpansByTraceId_js_1 = require("../../use-cases/getSpansByTraceId.js");
const updateSpan_js_1 = require("../../use-cases/updateSpan.js");
const getTraceWithSpans_js_1 = require("../../use-cases/getTraceWithSpans.js");
const clearProjectTraces_js_1 = require("../../use-cases/clearProjectTraces.js");
// Error handling middleware
const asyncHandler = (fn) => {
    return (req, res, next) => {
        Promise.resolve(fn(req, res, next)).catch(next);
    };
};
function createTraceRouter() {
    const router = express_1.default.Router();
    const traceRepository = new traceRepository_js_1.TraceRepository();
    const projectRepository = new projectRepository_js_1.ProjectRepository();
    // Initialize use cases
    const createTrace = new createTrace_js_1.CreateTrace(traceRepository);
    const bulkCreateTraces = new bulkCreateTraces_js_1.BulkCreateTraces(traceRepository, projectRepository);
    const getTraceById = new getTraceById_js_1.GetTraceById(traceRepository);
    const getTracesByProjectId = new getTracesByProjectId_js_1.GetTracesByProjectId(traceRepository);
    const updateTrace = new updateTrace_js_1.UpdateTrace(traceRepository);
    const createSpan = new createSpan_js_1.CreateSpan(traceRepository);
    const getSpansByTraceId = new getSpansByTraceId_js_1.GetSpansByTraceId(traceRepository);
    const updateSpan = new updateSpan_js_1.UpdateSpan(traceRepository);
    const getTraceWithSpans = new getTraceWithSpans_js_1.GetTraceWithSpans(traceRepository);
    const clearProjectTraces = new clearProjectTraces_js_1.ClearProjectTraces(traceRepository);
    // Trace endpoints
    // POST /api/traces - Create a new trace
    router.post('/', asyncHandler(async (req, res) => {
        try {
            const { projectId, name, startTime, endTime, metadata } = req.body;
            if (!projectId || !name || !startTime) {
                return res.status(400).json({ error: 'Missing required fields: projectId, name, startTime' });
            }
            const trace = await createTrace.execute({
                projectId,
                name,
                startTime,
                endTime,
                metadata,
            });
            res.status(201).json(trace);
        }
        catch (error) {
            console.error('Error creating trace:', error);
            res.status(500).json({ error: 'Failed to create trace' });
        }
    }));
    // POST /api/traces/bulk - Create multiple traces
    router.post('/bulk', asyncHandler(async (req, res) => {
        try {
            const { traces } = req.body;
            if (!traces || !Array.isArray(traces) || traces.length === 0) {
                return res.status(400).json({ error: 'Missing or invalid traces array' });
            }
            console.log("receiving traces: ", traces);
            const createdTraces = await bulkCreateTraces.execute(traces);
            res.status(201).json({
                success: true,
                count: createdTraces.length,
                traces: createdTraces
            });
        }
        catch (error) {
            console.error('Error creating traces in bulk:', error);
            res.status(500).json({ error: 'Failed to create traces in bulk' });
        }
    }));
    // GET /api/traces/:id - Get trace by ID
    router.get('/:id', asyncHandler(async (req, res) => {
        try {
            const { id } = req.params;
            const trace = await getTraceById.execute(id);
            if (!trace) {
                return res.status(404).json({ error: 'Trace not found' });
            }
            res.json(trace);
        }
        catch (error) {
            console.error('Error getting trace:', error);
            res.status(500).json({ error: 'Failed to get trace' });
        }
    }));
    // PUT /api/traces/:id - Update trace
    router.put('/:id', asyncHandler(async (req, res) => {
        try {
            const { id } = req.params;
            const { endTime, duration, status, metadata } = req.body;
            const trace = await updateTrace.execute(id, {
                endTime,
                duration,
                status,
                metadata,
            });
            if (!trace) {
                return res.status(404).json({ error: 'Trace not found' });
            }
            res.json(trace);
        }
        catch (error) {
            console.error('Error updating trace:', error);
            res.status(500).json({ error: 'Failed to update trace' });
        }
    }));
    // GET /api/traces/:id/complete - Get trace with all spans
    router.get('/:id/complete', asyncHandler(async (req, res) => {
        try {
            const { id } = req.params;
            const result = await getTraceWithSpans.execute(id);
            if (!result) {
                return res.status(404).json({ error: 'Trace not found' });
            }
            res.json(result);
        }
        catch (error) {
            console.error('Error getting complete trace:', error);
            res.status(500).json({ error: 'Failed to get complete trace' });
        }
    }));
    // GET /api/traces/project/:projectId - Get traces by project ID
    router.get('/project/:projectId', asyncHandler(async (req, res) => {
        try {
            const { projectId } = req.params;
            const { limit, sortDirection, cursor } = req.query;
            const options = {};
            if (limit)
                options.limit = parseInt(limit);
            if (sortDirection)
                options.sortDirection = sortDirection;
            console.log("cursor: ", cursor);
            if (cursor) {
                const parsedCursor = JSON.parse(cursor);
                options.cursor = {
                    id: parsedCursor.id,
                    timestamp: parsedCursor.timestamp
                };
            }
            const traces = await getTracesByProjectId.execute(projectId, options);
            res.json(traces);
        }
        catch (error) {
            console.error('Error getting traces by project:', error);
            res.status(500).json({ error: 'Failed to get traces' });
        }
    }));
    // DELETE /api/traces/project/:projectId - Clear all traces for a project
    router.delete('/project/:projectId', asyncHandler(async (req, res) => {
        try {
            const { projectId } = req.params;
            await clearProjectTraces.execute(projectId);
            res.status(204).send();
        }
        catch (error) {
            console.error('Error clearing project traces:', error);
            res.status(500).json({ error: 'Failed to clear project traces' });
        }
    }));
    // Span endpoints
    // POST /api/traces/:traceId/spans - Create a new span
    router.post('/:traceId/spans', asyncHandler(async (req, res) => {
        try {
            const { traceId } = req.params;
            const { id, parentSpanId, name, startTime, endTime, metadata } = req.body;
            if (!name || !startTime) {
                return res.status(400).json({ error: 'Missing required fields: name, startTime' });
            }
            const span = await createSpan.execute({
                id,
                traceId,
                parentSpanId,
                name,
                startTime,
                endTime,
                metadata,
            });
            res.status(201).json(span);
        }
        catch (error) {
            console.error('Error creating span:', error);
            res.status(500).json({ error: 'Failed to create span' });
        }
    }));
    // GET /api/traces/:traceId/spans - Get spans by trace ID
    router.get('/:traceId/spans', asyncHandler(async (req, res) => {
        try {
            const { traceId } = req.params;
            const { limit, sortDirection, cursorId, cursorTimestamp } = req.query;
            const options = {};
            if (limit)
                options.limit = parseInt(limit);
            if (sortDirection)
                options.sortDirection = sortDirection;
            if (cursorId && cursorTimestamp) {
                options.cursor = {
                    id: cursorId,
                    timestamp: cursorTimestamp
                };
            }
            const spans = await getSpansByTraceId.execute(traceId, options);
            res.json(spans);
        }
        catch (error) {
            console.error('Error getting spans:', error);
            res.status(500).json({ error: 'Failed to get spans' });
        }
    }));
    // PUT /api/traces/spans/:spanId - Update span
    router.put('/spans/:spanId', asyncHandler(async (req, res) => {
        try {
            const { spanId } = req.params;
            const { endTime, duration, status, metadata } = req.body;
            const span = await updateSpan.execute(spanId, {
                endTime,
                duration,
                status,
                metadata,
            });
            if (!span) {
                return res.status(404).json({ error: 'Span not found' });
            }
            res.json(span);
        }
        catch (error) {
            console.error('Error updating span:', error);
            res.status(500).json({ error: 'Failed to update span' });
        }
    }));
    return router;
}
//# sourceMappingURL=traceRoutes.js.map