/**
 * Snyk Exporter
 *
 * Exports findings to Snyk JSON format.
 *
 * @module exporters/snyk
 */
import { writeFile } from "fs/promises";
/**
 * Map Vaspera severity to Snyk severity
 */
const SEVERITY_MAP = {
    critical: "critical",
    high: "high",
    medium: "medium",
    low: "low",
    info: "low", // Snyk doesn't have "info", map to low
};
/**
 * Generate a unique vulnerability ID
 */
function generateVulnId(finding) {
    const prefix = finding.scanner_rule_id ? finding.scanner_rule_id.toUpperCase().replace(/[^A-Z0-9]/g, "-") : "VASPERA";
    return `${prefix}-${finding.id}`;
}
/**
 * Convert a finding to Snyk vulnerability
 */
function findingToVulnerability(finding) {
    const vuln = {
        id: generateVulnId(finding),
        title: finding.category.charAt(0).toUpperCase() + finding.category.slice(1).replace(/-/g, " "),
        description: finding.description,
        severity: SEVERITY_MAP[finding.severity],
        identifiers: {},
        from: [finding.file || "unknown"],
        isPatchable: false,
        isUpgradable: false,
    };
    // Add CWE IDs if available
    if (finding.cwe_ids && finding.cwe_ids.length > 0) {
        vuln.identifiers.CWE = finding.cwe_ids;
    }
    // Add CVE IDs if available
    if (finding.cve_ids && finding.cve_ids.length > 0) {
        vuln.identifiers.CVE = finding.cve_ids;
    }
    // Add line info to description
    if (finding.line) {
        vuln.description = `[Line ${finding.line}] ${vuln.description}`;
    }
    // Map evidence if available (remediation stored in description)
    if (finding.evidence) {
        vuln.upgradePath = [finding.evidence];
        vuln.isUpgradable = true;
    }
    return vuln;
}
/**
 * Export certification to Snyk format
 */
export async function exportToSnyk(certification, options = {}) {
    const { outputPath, minSeverity = "info", 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 Snyk format
    const vulnerabilities = filteredFindings.map(findingToVulnerability);
    // Count by severity
    const bySeverity = {
        critical: vulnerabilities.filter((v) => v.severity === "critical").length,
        high: vulnerabilities.filter((v) => v.severity === "high").length,
        medium: vulnerabilities.filter((v) => v.severity === "medium").length,
        low: vulnerabilities.filter((v) => v.severity === "low").length,
    };
    const report = {
        ok: vulnerabilities.length === 0,
        vulnerabilities,
        dependencyCount: 0,
        org: "vaspera",
        policy: "",
        isPrivate: true,
        licensesPolicy: {},
        packageManager: "unknown",
        projectName: certification.metadata.project_name,
        summary: `Found ${vulnerabilities.length} issues (${bySeverity.critical} critical, ${bySeverity.high} high, ${bySeverity.medium} medium, ${bySeverity.low} low)`,
        filesystemPolicy: false,
    };
    const content = JSON.stringify(report, null, 2);
    // Write to file if path provided
    if (outputPath) {
        await writeFile(outputPath, content, "utf-8");
    }
    return {
        format: "snyk",
        outputPath,
        findingsExported: vulnerabilities.length,
        content,
    };
}
/**
 * Snyk exporter instance
 */
export const snykExporter = {
    format: "snyk",
    export: exportToSnyk,
};
//# sourceMappingURL=snyk.js.map