/**
 * SonarQube Exporter
 *
 * Exports findings to SonarQube Generic Issue Import Format.
 *
 * @module exporters/sonarqube
 */
import { writeFile } from "fs/promises";
/**
 * Map Vaspera severity to SonarQube severity
 */
const SEVERITY_MAP = {
    critical: "BLOCKER",
    high: "CRITICAL",
    medium: "MAJOR",
    low: "MINOR",
    info: "INFO",
};
/**
 * Map category to SonarQube issue type
 */
function categoryToType(category) {
    const securityCategories = [
        "injection",
        "xss",
        "authentication",
        "authorization",
        "cryptography",
        "secrets",
        "api-security",
    ];
    if (securityCategories.some((c) => category.toLowerCase().includes(c))) {
        return "VULNERABILITY";
    }
    const bugCategories = ["error-handling", "null-safety", "type-safety", "memory"];
    if (bugCategories.some((c) => category.toLowerCase().includes(c))) {
        return "BUG";
    }
    return "CODE_SMELL";
}
/**
 * Estimate effort to fix in minutes based on severity
 */
function estimateEffort(severity) {
    switch (severity) {
        case "critical":
            return 120;
        case "high":
            return 60;
        case "medium":
            return 30;
        case "low":
            return 15;
        case "info":
            return 5;
    }
}
/**
 * Convert a finding to SonarQube issue
 */
function findingToIssue(finding, projectRoot) {
    let filePath = finding.file || "unknown";
    if (projectRoot && filePath.startsWith(projectRoot)) {
        filePath = filePath.slice(projectRoot.length).replace(/^\//, "");
    }
    return {
        engineId: "vaspera",
        ruleId: finding.scanner_rule_id || `vaspera-${finding.category}`,
        primaryLocation: {
            message: finding.description,
            filePath,
            textRange: finding.line
                ? {
                    startLine: finding.line,
                    endLine: finding.line,
                }
                : undefined,
        },
        type: categoryToType(finding.category),
        severity: SEVERITY_MAP[finding.severity],
        effortMinutes: estimateEffort(finding.severity),
    };
}
/**
 * Export certification to SonarQube format
 */
export async function exportToSonarQube(certification, options = {}) {
    const { outputPath, minSeverity = "info", projectRoot, includeResolved = false } = options;
    const severityOrder = ["critical", "high", "medium", "low", "info"];
    const minIndex = severityOrder.indexOf(minSeverity);
    // Collect all findings
    const allFindings = [];
    for (const [, agentData] of Object.entries(certification.agents)) {
        if (agentData?.findings) {
            allFindings.push(...agentData.findings);
        }
    }
    // Filter by severity
    const filteredFindings = allFindings.filter((f) => {
        const sevIndex = severityOrder.indexOf(f.severity);
        return sevIndex <= minIndex;
    });
    // Convert to SonarQube format
    const issues = filteredFindings.map((f) => findingToIssue(f, projectRoot));
    const report = { issues };
    const content = JSON.stringify(report, null, 2);
    // Write to file if path provided
    if (outputPath) {
        await writeFile(outputPath, content, "utf-8");
    }
    return {
        format: "sonarqube",
        outputPath,
        findingsExported: issues.length,
        content,
    };
}
/**
 * SonarQube exporter instance
 */
export const sonarqubeExporter = {
    format: "sonarqube",
    export: exportToSonarQube,
};
//# sourceMappingURL=sonarqube.js.map