"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.
Object.defineProperty(exports, "__esModule", { value: true });
exports.createCaseRoutes = createCaseRoutes;
/**
 * Case Routes — admin surface for the Plan 54 case library + graph.
 *
 * Endpoints (all under `/api/cases`):
 *   GET    /                   list cases (filters: status, tag, level)
 *   POST   /                   save a case (rejects published; use /publish)
 *   GET    /:caseId            fetch one
 *   DELETE /:caseId            remove
 *   POST   /:caseId/publish    advance to published (double-control gate)
 *   POST   /:caseId/archive    drop trace artifact, keep metadata
 *   GET    /edges              list all edges
 *   POST   /edges              add or replace an edge
 *   GET    /edges/:caseId      get edges from this case (`?direction=in|out|both`)
 *   DELETE /edges/:edgeId      remove an edge
 *
 * Recall (`recall_similar_case`) lives on the MCP side. This route
 * is operator-side only.
 *
 * @module caseRoutes
 */
const express_1 = require("express");
const auth_1 = require("../middleware/auth");
const caseLibrary_1 = require("../services/caseLibrary");
const caseGraph_1 = require("../services/caseGraph");
const scopedKnowledgeStore_1 = require("../services/scopedKnowledgeStore");
const runtimePaths_1 = require("../runtimePaths");
const DEFAULT_LIBRARY_PATH = (0, runtimePaths_1.backendLogPath)('case_library.json');
const DEFAULT_GRAPH_PATH = (0, runtimePaths_1.backendLogPath)('case_graph.json');
let cachedLibrary = null;
let cachedGraph = null;
function getDefaultLibrary() {
    if (!cachedLibrary)
        cachedLibrary = new caseLibrary_1.CaseLibrary(DEFAULT_LIBRARY_PATH);
    return cachedLibrary;
}
function getDefaultGraph() {
    if (!cachedGraph)
        cachedGraph = new caseGraph_1.CaseGraph(DEFAULT_GRAPH_PATH);
    return cachedGraph;
}
/** Test/factory hook. Pass explicit stores; default singletons
 * point at `backend/logs/case_library.json` + `case_graph.json`. */
function createCaseRoutes(library, graph) {
    const lib = library ?? getDefaultLibrary();
    const g = graph ?? getDefaultGraph();
    const router = (0, express_1.Router)();
    router.use(auth_1.authenticate);
    // -------------------------------------------------------------------
    // Edge endpoints — registered BEFORE the `/:caseId` routes so the
    // literal "edges" path segment isn't captured as a caseId.
    // -------------------------------------------------------------------
    router.get('/edges', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const edges = g.listEdges(scope);
        res.json({ success: true, edges, count: edges.length });
    });
    router.post('/edges', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const edge = req.body;
        if (!edge ||
            !edge.edgeId ||
            !edge.fromCaseId ||
            !edge.toCaseId ||
            !edge.relation) {
            return res.status(400).json({
                success: false,
                error: 'Body must be a CaseEdge with edgeId, fromCaseId, toCaseId, relation',
            });
        }
        try {
            g.addEdge(edge, scope);
            return res.status(201).json({ success: true, edge });
        }
        catch (err) {
            return res.status(400).json({
                success: false,
                error: err instanceof Error ? err.message : String(err),
            });
        }
    });
    router.get('/edges/:caseId', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const direction = (req.query.direction ?? 'both');
        const related = g.findRelated(req.params.caseId, {
            direction,
            knowledgeScope: scope,
        });
        res.json({ success: true, related, count: related.length });
    });
    router.delete('/edges/:edgeId', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const removed = g.removeEdge(req.params.edgeId, scope);
        if (!removed) {
            return res.status(404).json({
                success: false,
                error: `Edge '${req.params.edgeId}' not found`,
            });
        }
        res.json({ success: true });
    });
    // -------------------------------------------------------------------
    // Case endpoints
    // -------------------------------------------------------------------
    router.get('/', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const { status, tag, level } = req.query;
        const cases = lib.listCases({
            status: status,
            anyOfTags: tag ? [tag] : undefined,
            educationalLevel: level,
        }, scope);
        res.json({ success: true, cases, count: cases.length });
    });
    router.post('/', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const c = req.body;
        if (!c || !c.caseId || !c.title || !c.status) {
            return res.status(400).json({
                success: false,
                error: 'Body must be a CaseNode with caseId, title, status',
            });
        }
        try {
            lib.saveCase(c, scope);
            return res.status(201).json({ success: true, case: c });
        }
        catch (err) {
            return res.status(400).json({
                success: false,
                error: err instanceof Error ? err.message : String(err),
            });
        }
    });
    router.get('/:caseId', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const c = lib.getCase(req.params.caseId, scope);
        if (!c) {
            return res.status(404).json({
                success: false,
                error: `Case '${req.params.caseId}' not found`,
            });
        }
        res.json({ success: true, case: c });
    });
    router.delete('/:caseId', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const removed = lib.removeCase(req.params.caseId, scope);
        if (!removed) {
            return res.status(404).json({
                success: false,
                error: `Case '${req.params.caseId}' not found`,
            });
        }
        res.json({ success: true });
    });
    /** POST /api/cases/:caseId/publish — body `{reviewer}`. */
    router.post('/:caseId/publish', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const reviewer = (req.body?.reviewer ?? '');
        try {
            const published = lib.publishCase(req.params.caseId, { reviewer }, scope);
            return res.json({ success: true, case: published });
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            const status = /not found/.test(msg) ? 404 : 400;
            return res.status(status).json({ success: false, error: msg });
        }
    });
    /** POST /api/cases/:caseId/archive — body `{reason}`. */
    router.post('/:caseId/archive', (req, res) => {
        const scope = (0, scopedKnowledgeStore_1.knowledgeScopeFromRequestContext)((0, auth_1.requireRequestContext)(req));
        const reason = (req.body?.reason ?? '');
        try {
            const archived = lib.archiveCase(req.params.caseId, { reason }, scope);
            return res.json({ success: true, case: archived });
        }
        catch (err) {
            const msg = err instanceof Error ? err.message : String(err);
            const status = /not found/.test(msg) ? 404 : 400;
            return res.status(status).json({ success: false, error: msg });
        }
    });
    return router;
}
const caseRoutes = createCaseRoutes();
exports.default = caseRoutes;
//# sourceMappingURL=caseRoutes.js.map