"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.createProjectRouter = createProjectRouter;
const express_1 = __importDefault(require("express"));
const zod_1 = require("zod");
const projectRepository_js_1 = require("../../repositories/projectRepository.js");
const logRepository_js_1 = require("../../repositories/logRepository.js");
const getAllProjects_js_1 = require("../../use-cases/getAllProjects.js");
const getProjectById_js_1 = require("../../use-cases/getProjectById.js");
const createProject_js_1 = require("../../use-cases/createProject.js");
const updateProject_js_1 = require("../../use-cases/updateProject.js");
const deleteProject_js_1 = require("../../use-cases/deleteProject.js");
const getProjectMetrics_js_1 = require("../../use-cases/getProjectMetrics.js");
const getLogsByProjectId_js_1 = require("../../use-cases/getLogsByProjectId.js");
const getHistoricalLogCounts_js_1 = require("../../use-cases/getHistoricalLogCounts.js");
const getMetadataKeysByProjectId_js_1 = require("../../use-cases/getMetadataKeysByProjectId.js");
const getProjectConfig_js_1 = require("../../use-cases/getProjectConfig.js");
const updateProjectConfig_js_1 = require("../../use-cases/updateProjectConfig.js");
const clearProjectLogs_js_1 = require("../../use-cases/clearProjectLogs.js");
// Validation schemas
const ProjectCreateSchema = zod_1.z.object({
    name: zod_1.z.string(),
    description: zod_1.z.string().optional(),
});
const ProjectUpdateSchema = zod_1.z.object({
    name: zod_1.z.string().optional(),
    description: zod_1.z.string().optional(),
});
const ProjectConfigSchema = zod_1.z.object({
    trackedMetadataKeys: zod_1.z.array(zod_1.z.string()).optional(),
});
// Validation middleware
const validateBody = (schema) => {
    return (req, res, next) => {
        try {
            req.body = schema.parse(req.body);
            next();
        }
        catch (error) {
            if (error instanceof zod_1.z.ZodError) {
                res.status(400).json({ error: 'Validation error', details: error.errors });
                return;
            }
            next(error);
        }
    };
};
const validateParams = (schema) => {
    return (req, res, next) => {
        try {
            req.params = schema.parse(req.params);
            next();
        }
        catch (error) {
            if (error instanceof zod_1.z.ZodError) {
                res.status(400).json({ error: 'Validation error', details: error.errors });
                return;
            }
            next(error);
        }
    };
};
const validateQuery = (schema) => {
    return (req, res, next) => {
        try {
            const validatedQuery = schema.parse(req.query);
            req.validatedQuery = validatedQuery;
            next();
        }
        catch (error) {
            if (error instanceof zod_1.z.ZodError) {
                res.status(400).json({ error: 'Validation error', details: error.errors });
                return;
            }
            next(error);
        }
    };
};
// Error handling middleware
const asyncHandler = (fn) => {
    return (req, res, next) => {
        Promise.resolve(fn(req, res, next)).catch(next);
    };
};
function createProjectRouter() {
    const router = express_1.default.Router();
    // Initialize repositories and use cases
    const projectRepository = new projectRepository_js_1.ProjectRepository();
    const logRepository = new logRepository_js_1.LogRepository();
    const getAllProjects = new getAllProjects_js_1.GetAllProjects(projectRepository);
    const getProjectById = new getProjectById_js_1.GetProjectById(projectRepository);
    const createProject = new createProject_js_1.CreateProject(projectRepository);
    const updateProject = new updateProject_js_1.UpdateProject(projectRepository);
    const deleteProject = new deleteProject_js_1.DeleteProject(projectRepository);
    const getProjectMetrics = new getProjectMetrics_js_1.GetProjectMetrics(logRepository);
    const getLogsByProjectId = new getLogsByProjectId_js_1.GetLogsByProjectId(logRepository);
    const getHistoricalLogCounts = new getHistoricalLogCounts_js_1.GetHistoricalLogCounts(logRepository);
    const getMetadataKeysByProjectId = new getMetadataKeysByProjectId_js_1.GetMetadataKeysByProjectId(logRepository);
    const getProjectConfig = new getProjectConfig_js_1.GetProjectConfig(projectRepository);
    const updateProjectConfig = new updateProjectConfig_js_1.UpdateProjectConfig(projectRepository);
    const clearProjectLogs = new clearProjectLogs_js_1.ClearProjectLogs(logRepository);
    // GET /api/projects
    router.get('/', asyncHandler(async (req, res) => {
        const projects = await getAllProjects.execute();
        res.json(projects);
    }));
    // GET /api/projects/:id
    router.get('/:id', validateParams(zod_1.z.object({ id: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { id } = req.params;
        const project = await getProjectById.execute(id);
        if (!project) {
            res.status(404).json({ error: 'Project not found' });
            return;
        }
        res.json(project);
    }));
    // GET /api/projects/exists/:name
    router.get('/exists/:name', validateParams(zod_1.z.object({ name: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { name } = req.params;
        const project = await projectRepository.getProjectByName(name);
        res.json({ exists: !!project, project });
    }));
    // POST /api/projects
    router.post('/', validateBody(ProjectCreateSchema), asyncHandler(async (req, res) => {
        const projectData = req.body;
        const project = await createProject.execute({
            name: projectData.name,
            description: projectData.description || '',
        });
        res.status(201).json(project);
    }));
    // PUT /api/projects/:id
    router.put('/:id', validateParams(zod_1.z.object({ id: zod_1.z.string() })), validateBody(ProjectUpdateSchema), asyncHandler(async (req, res) => {
        const { id } = req.params;
        const updateData = req.body;
        const project = await updateProject.execute(id, updateData);
        if (!project) {
            res.status(404).json({ error: 'Project not found' });
            return;
        }
        res.json(project);
    }));
    // DELETE /api/projects/:id
    router.delete('/:id', validateParams(zod_1.z.object({ id: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { id } = req.params;
        try {
            await deleteProject.execute(id);
            res.json({ success: true });
        }
        catch (err) {
            console.error("Something went wrong when deleting project" + id);
            res.status(500).json({ error: "Something went wrong" });
        }
    }));
    // GET /api/projects/:projectId/metrics
    router.get('/:projectId/metrics', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const metrics = await getProjectMetrics.execute(projectId);
        res.json(metrics);
    }));
    // GET /api/projects/:projectId/logs
    router.get('/:projectId/logs', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), validateQuery(zod_1.z.object({
        limit: zod_1.z.string().optional().transform(val => val ? parseInt(val, 10) : undefined),
        cursor: zod_1.z.string().optional().transform(val => val ? JSON.parse(val) : undefined), // Assuming cursor is a JSON stringified objec,
        sortDirection: zod_1.z.enum(['asc', 'desc']).optional(),
        level: zod_1.z.union([zod_1.z.string(), zod_1.z.array(zod_1.z.string())]).optional(),
        messageContains: zod_1.z.string().optional(),
        fromDate: zod_1.z.string().optional(),
        toDate: zod_1.z.string().optional(),
        metaContains: zod_1.z.string().optional().transform(val => val ? JSON.parse(val) : undefined),
        metadata: zod_1.z.string().optional().transform(val => val ? JSON.parse(val) : undefined)
    })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const { limit, cursor, sortDirection, level, messageContains, fromDate, toDate, metaContains, metadata } = req.validatedQuery;
        const options = { projectId };
        if (limit)
            options.limit = limit;
        if (cursor) {
            const cursorSchema = zod_1.z.object({
                id: zod_1.z.string(),
                timestamp: zod_1.z.string()
            });
            const parsedCursor = cursorSchema.safeParse(cursor);
            if (!parsedCursor.success) {
                res.status(400).json({ error: 'Validation error', details: parsedCursor.error.errors });
                return;
            }
            options.cursor = cursor;
        }
        ;
        if (sortDirection)
            options.sortDirection = sortDirection;
        if (level)
            options.level = level;
        if (messageContains)
            options.messageContains = messageContains;
        if (fromDate)
            options.fromDate = fromDate;
        if (toDate)
            options.toDate = toDate;
        if (metaContains)
            options.metaContains = metaContains;
        if (metadata)
            options.metadata = metadata;
        console.log("filtering options", options);
        const logs = await getLogsByProjectId.execute(projectId, options);
        res.json(logs);
    }));
    // GET /api/projects/:projectId/logs/historical-counts
    router.get('/:projectId/logs/historical-counts', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), validateQuery(zod_1.z.object({ days: zod_1.z.string().optional() })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const { days } = req.validatedQuery || req.query;
        const counts = await getHistoricalLogCounts.execute(projectId, days ? parseInt(days) : 7);
        res.json(counts);
    }));
    // GET /api/projects/:projectId/metadata-keys
    router.get('/:projectId/metadata-keys', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const keys = await getMetadataKeysByProjectId.execute(projectId);
        res.json(keys);
    }));
    // GET /api/projects/:projectId/config
    router.get('/:projectId/config', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const config = await getProjectConfig.execute(projectId);
        res.json(config);
    }));
    // PUT /api/projects/:projectId/config
    router.put('/:projectId/config', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), validateBody(ProjectConfigSchema), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        const configData = req.body;
        await updateProjectConfig.execute(projectId, configData);
        res.json({ success: true });
    }));
    // DELETE /api/projects/:projectId/logs - Clear all logs for a project
    router.delete('/:projectId/logs', validateParams(zod_1.z.object({ projectId: zod_1.z.string() })), asyncHandler(async (req, res) => {
        const { projectId } = req.params;
        try {
            await clearProjectLogs.execute(projectId);
            res.json({ success: true, message: 'All logs cleared for project' });
        }
        catch (err) {
            console.error('Error clearing logs for project ' + projectId, err);
            res.status(500).json({ error: 'Failed to clear project logs' });
        }
    }));
    // GET /api/metadata/keys - Global metadata keys endpoint
    router.get('/metadata/keys', asyncHandler(async (req, res) => {
        const keys = await logRepository.getMetadataKeys();
        res.json(keys);
    }));
    return router;
}
//# sourceMappingURL=projectRoutes.js.map