"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 __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.runReportCommand = runReportCommand;
exports.runReportExportCommand = runReportExportCommand;
/**
 * `smartperfetto report <sessionId>` — print or open the session's HTML report.
 *
 * PR2 supports `--open` only. `--rebuild` (regenerate from stream.jsonl) is
 * deferred — it requires replaying the orchestrator-populated session fields
 * that `analyze` collects at run time, which isn't trivially possible from
 * the raw event stream alone.
 */
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const bootstrap_1 = require("../bootstrap");
const sessionStore_1 = require("../io/sessionStore");
const openFile_1 = require("../io/openFile");
async function runReportCommand(args) {
    const { paths } = (0, bootstrap_1.bootstrap)({ envFile: args.envFile, sessionDir: args.sessionDir, requireLlm: false });
    const { sp, config } = (0, sessionStore_1.loadSession)(paths, args.sessionId);
    if (!config) {
        console.error(`Error: no session found at ${sp.dir}`);
        return 1;
    }
    const reportPath = args.turn ? (0, sessionStore_1.turnReportPath)(sp, args.turn) : sp.report;
    if (!fs.existsSync(reportPath)) {
        console.error(args.turn
            ? `Error: no turn ${args.turn} HTML report in ${sp.turnsDir}`
            : `Error: no report.html in ${sp.dir}`);
        console.error(`(Report was not generated — run \`smp ask ${args.sessionId} "retry report generation"\` or start a new \`smp run <trace> "question"\`.)`);
        return 1;
    }
    console.log(reportPath);
    if (args.open) {
        const r = (0, openFile_1.openPath)(reportPath);
        if (!r.ok) {
            console.error(`Error: ${r.reason}`);
            return 1;
        }
    }
    return 0;
}
async function runReportExportCommand(args) {
    const outPath = path.resolve(args.out);
    const { paths } = (0, bootstrap_1.bootstrap)({ envFile: args.envFile, sessionDir: args.sessionDir, requireLlm: false });
    const { sp, config } = (0, sessionStore_1.loadSession)(paths, args.sessionId);
    if (!config) {
        console.error(`Error: no session found at ${sp.dir}`);
        return 1;
    }
    fs.mkdirSync(path.dirname(outPath), { recursive: true });
    switch (args.format) {
        case 'html': {
            const source = args.turn ? (0, sessionStore_1.turnReportPath)(sp, args.turn) : sp.report;
            if (!fs.existsSync(source)) {
                console.error(args.turn
                    ? `Error: no turn ${args.turn} HTML report in ${sp.turnsDir}`
                    : `Error: no report.html in ${sp.dir}`);
                return 1;
            }
            fs.copyFileSync(source, outPath);
            break;
        }
        case 'md':
            fs.writeFileSync(outPath, args.turn
                ? buildTurnMarkdownExport(sp, args.turn, config)
                : buildMarkdownExport(sp, config), 'utf-8');
            break;
        case 'json':
            fs.writeFileSync(outPath, JSON.stringify(args.turn
                ? buildTurnJsonExport(sp, args.turn, config)
                : buildJsonExport(sp, config), null, 2), 'utf-8');
            break;
        default:
            console.error(`Error: unsupported report format: ${args.format}`);
            return 2;
    }
    console.log(outPath);
    return 0;
}
function buildTurnMarkdownExport(sp, turn, config) {
    const file = path.join(sp.turnsDir, `${String(turn).padStart(3, '0')}.md`);
    const body = readIfExists(file);
    return [
        '# SmartPerfetto CLI Turn Report',
        '',
        `- Session: ${config.sessionId}`,
        `- Turn: ${turn}`,
        `- Trace: ${config.tracePath}`,
        ...(config.referenceTracePath ? [`- Reference Trace: ${config.referenceTracePath}`] : []),
        '',
        body || '*(no turn markdown)*',
        '',
        buildAnalysisQualityMarkdown(sp, turn),
    ].join('\n');
}
function buildMarkdownExport(sp, config) {
    const lines = [
        '# SmartPerfetto CLI Report',
        '',
        `- Session: ${config.sessionId}`,
        `- Trace: ${config.tracePath}`,
        ...(config.referenceTracePath ? [`- Reference Trace: ${config.referenceTracePath}`] : []),
        `- Turns: ${config.turnCount}`,
        `- Updated: ${new Date(config.lastTurnAt).toISOString()}`,
        '',
        '## Latest Conclusion',
        '',
        readIfExists(sp.conclusion) || '*(no conclusion)*',
        '',
        buildAnalysisQualityMarkdown(sp),
        '',
    ];
    const turnFiles = fs.existsSync(sp.turnsDir)
        ? fs.readdirSync(sp.turnsDir).filter((f) => f.endsWith('.md')).sort()
        : [];
    if (turnFiles.length) {
        lines.push('## Turns', '');
        for (const file of turnFiles) {
            lines.push(readIfExists(path.join(sp.turnsDir, file)), '');
        }
    }
    return lines.join('\n');
}
function buildAnalysisQualityMarkdown(sp, turn) {
    const turnPrefix = turn === undefined
        ? undefined
        : path.join(sp.turnsDir, String(turn).padStart(3, '0'));
    const claimSupportPath = turnPrefix ? `${turnPrefix}.claim-support.json` : sp.claimSupport;
    const claimVerificationPath = turnPrefix ? `${turnPrefix}.claim-verification.json` : sp.claimVerification;
    const identityResolutionsPath = turnPrefix ? `${turnPrefix}.identity-resolutions.json` : sp.identityResolutions;
    const claimSupportRaw = readJsonIfExists(claimSupportPath, []);
    const verifier = readJsonIfExists(claimVerificationPath, null);
    const identitiesRaw = readJsonIfExists(identityResolutionsPath, []);
    const claimSupport = Array.isArray(claimSupportRaw) ? claimSupportRaw : [];
    const identities = Array.isArray(identitiesRaw) ? identitiesRaw : [];
    const hasVerifier = verifier && typeof verifier === 'object';
    if (!hasVerifier && claimSupport.length === 0 && identities.length === 0) {
        return '';
    }
    const lines = [
        '## Claim Verification',
        '',
        `- Verifier: ${hasVerifier ? verifier.status || 'not_checked' : 'not_checked'}`,
        `- Checked claims: ${hasVerifier ? verifier.checkedClaimCount ?? 0 : 0}`,
        `- Unsupported claims: ${hasVerifier ? verifier.unsupportedClaimCount ?? 0 : 0}`,
        `- Claim support entries: ${claimSupport.length}`,
        `- Identity sidecars: ${identities.length}`,
        ...(fs.existsSync(claimSupportPath) ? [`- Claim support file: ${claimSupportPath}`] : []),
        ...(fs.existsSync(claimVerificationPath) ? [`- Claim verification file: ${claimVerificationPath}`] : []),
        ...(fs.existsSync(identityResolutionsPath) ? [`- Identity resolutions file: ${identityResolutionsPath}`] : []),
    ];
    const issues = Array.isArray(verifier?.issues) ? verifier.issues : [];
    if (issues.length > 0) {
        lines.push('', '### Issues', '');
        for (const issue of issues.slice(0, 8)) {
            lines.push(`- ${issue.claimId || 'unknown'} \`${issue.code || 'issue'}\`: ${issue.message || ''}`.trim());
        }
        if (issues.length > 8) {
            lines.push(`- ${issues.length - 8} more issues omitted from markdown export.`);
        }
    }
    return lines.join('\n');
}
function buildJsonExport(sp, config) {
    return {
        ok: true,
        config,
        conclusion: readIfExists(sp.conclusion),
        claimSupport: readJsonIfExists(sp.claimSupport, []),
        claimVerificationResult: readJsonIfExists(sp.claimVerification, null),
        identityResolutions: readJsonIfExists(sp.identityResolutions, []),
        transcript: readTranscript(sp.transcript),
        files: {
            sessionDir: sp.dir,
            reportHtml: fs.existsSync(sp.report) ? sp.report : null,
            turnReports: listTurnReports(sp),
            conclusion: fs.existsSync(sp.conclusion) ? sp.conclusion : null,
            claimSupport: fs.existsSync(sp.claimSupport) ? sp.claimSupport : null,
            claimVerification: fs.existsSync(sp.claimVerification) ? sp.claimVerification : null,
            identityResolutions: fs.existsSync(sp.identityResolutions) ? sp.identityResolutions : null,
            transcript: fs.existsSync(sp.transcript) ? sp.transcript : null,
        },
    };
}
function buildTurnJsonExport(sp, turn, config) {
    const htmlPath = (0, sessionStore_1.turnReportPath)(sp, turn);
    const mdPath = path.join(sp.turnsDir, `${String(turn).padStart(3, '0')}.md`);
    const turnPrefix = path.join(sp.turnsDir, String(turn).padStart(3, '0'));
    const transcript = readTranscript(sp.transcript);
    return {
        ok: true,
        config,
        turn,
        turnMarkdown: readIfExists(mdPath),
        claimSupport: readJsonIfExists(`${turnPrefix}.claim-support.json`, []),
        claimVerificationResult: readJsonIfExists(`${turnPrefix}.claim-verification.json`, null),
        identityResolutions: readJsonIfExists(`${turnPrefix}.identity-resolutions.json`, []),
        transcriptTurn: transcript.find((entry) => entry?.turn === turn) ?? null,
        files: {
            sessionDir: sp.dir,
            reportHtml: fs.existsSync(htmlPath) ? htmlPath : null,
            turnMarkdown: fs.existsSync(mdPath) ? mdPath : null,
            claimSupport: fs.existsSync(`${turnPrefix}.claim-support.json`) ? `${turnPrefix}.claim-support.json` : null,
            claimVerification: fs.existsSync(`${turnPrefix}.claim-verification.json`) ? `${turnPrefix}.claim-verification.json` : null,
            identityResolutions: fs.existsSync(`${turnPrefix}.identity-resolutions.json`) ? `${turnPrefix}.identity-resolutions.json` : null,
            transcript: fs.existsSync(sp.transcript) ? sp.transcript : null,
        },
    };
}
function listTurnReports(sp) {
    if (!fs.existsSync(sp.turnsDir))
        return [];
    return fs
        .readdirSync(sp.turnsDir)
        .filter((f) => f.endsWith('.html'))
        .sort()
        .map((f) => path.join(sp.turnsDir, f));
}
function readIfExists(file) {
    try {
        return fs.existsSync(file) ? fs.readFileSync(file, 'utf-8') : '';
    }
    catch {
        return '';
    }
}
function readJsonIfExists(file, fallback) {
    try {
        return fs.existsSync(file) ? JSON.parse(fs.readFileSync(file, 'utf-8')) : fallback;
    }
    catch {
        return fallback;
    }
}
function readTranscript(file) {
    if (!fs.existsSync(file))
        return [];
    return fs
        .readFileSync(file, 'utf-8')
        .split('\n')
        .map((line) => line.trim())
        .filter(Boolean)
        .map((line) => {
        try {
            return JSON.parse(line);
        }
        catch {
            return { raw: line };
        }
    });
}
//# sourceMappingURL=report.js.map