// Merge and deduplicate findings from multiple dimensions (SPEC-303)
// ---------------------------------------------------------------------------
// Deduplication helpers
// ---------------------------------------------------------------------------
function messageOverlap(a, b) {
    const shorter = a.length < b.length ? a : b;
    const longer = a.length < b.length ? b : a;
    let matches = 0;
    for (const ch of shorter) {
        if (longer.includes(ch)) {
            matches++;
        }
    }
    return shorter.length > 0 ? matches / shorter.length : 0;
}
function findingKey(f) {
    return `${f.file}:${String(f.line ?? 0)}`;
}
function severityRank(severity) {
    switch (severity) {
        case 'critical':
            return 3;
        case 'warning':
            return 2;
        case 'info':
            return 1;
        default:
            return 0;
    }
}
function deduplicateFindings(findings) {
    const kept = [];
    for (const candidate of findings) {
        const key = findingKey(candidate);
        const duplicateIdx = kept.findIndex((k) => {
            if (findingKey(k) !== key) {
                return false;
            }
            return messageOverlap(k.message, candidate.message) > 0.5;
        });
        if (duplicateIdx === -1) {
            kept.push(candidate);
        }
        else {
            const existing = kept[duplicateIdx];
            if (existing && severityRank(candidate.severity) > severityRank(existing.severity)) {
                kept[duplicateIdx] = candidate;
            }
        }
    }
    return kept;
}
// ---------------------------------------------------------------------------
// Severity bucketing
// ---------------------------------------------------------------------------
function isCritical(f) {
    return f.severity === 'critical';
}
function isSuggestion(f) {
    return f.severity === 'warning';
}
function isNit(f) {
    return f.severity === 'info';
}
// ---------------------------------------------------------------------------
// Sorting
// ---------------------------------------------------------------------------
function sortFindings(findings) {
    return [...findings].sort((a, b) => {
        const fileCmp = a.file.localeCompare(b.file);
        if (fileCmp !== 0) {
            return fileCmp;
        }
        return (a.line ?? 0) - (b.line ?? 0);
    });
}
// ---------------------------------------------------------------------------
// Main export
// ---------------------------------------------------------------------------
export function mergeFindings(results) {
    const allFindings = results.flatMap((r) => r.findings);
    const deduplicated = deduplicateFindings(allFindings);
    const critical = sortFindings(deduplicated.filter(isCritical));
    const suggestions = sortFindings(deduplicated.filter(isSuggestion));
    const nits = sortFindings(deduplicated.filter(isNit));
    const durationMs = results.reduce((sum, r) => sum + r.duration, 0);
    const dimensions = results.map((r) => r.dimension);
    return {
        critical,
        suggestions,
        nits,
        dimensions,
        totalFindings: critical.length + suggestions.length + nits.length,
        durationMs,
    };
}
//# sourceMappingURL=findings-merger.js.map