"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.applyFix = applyFix;
exports.applyAllSafeFixes = applyAllSafeFixes;
exports.applyAllFixes = applyAllFixes;
exports.buildFixSuggestions = buildFixSuggestions;
exports.listAllRegisteredFixSuggestions = listAllRegisteredFixSuggestions;
const fixRegistry_1 = require("./fixRegistry");
function sortValidationResultsDeterministically(results) {
    const severityRank = (severity) => {
        if (severity === 'error') {
            return 1;
        }
        if (severity === 'warning') {
            return 2;
        }
        if (severity === 'info') {
            return 3;
        }
        return 99;
    };
    return [...results].sort((left, right) => {
        const bySeverity = severityRank(left.severity) - severityRank(right.severity);
        if (bySeverity !== 0) {
            return bySeverity;
        }
        const byRule = left.id.localeCompare(right.id);
        if (byRule !== 0) {
            return byRule;
        }
        const leftPath = (left.sourceFile ?? '').replace(/\\/g, '/');
        const rightPath = (right.sourceFile ?? '').replace(/\\/g, '/');
        const byPath = leftPath.localeCompare(rightPath);
        if (byPath !== 0) {
            return byPath;
        }
        const byLine = (left.sourceLine ?? 0) - (right.sourceLine ?? 0);
        if (byLine !== 0) {
            return byLine;
        }
        return left.message.localeCompare(right.message);
    });
}
function toFixSuggestionsForResults(results) {
    const suggestions = new Map();
    const failedResults = sortValidationResultsDeterministically(results.filter((result) => !result.passed));
    for (const result of failedResults) {
        for (const handler of (0, fixRegistry_1.getFixHandlersForRule)(result.id)) {
            const key = `${handler.ruleId}::${handler.fixId}`;
            if (!suggestions.has(key)) {
                suggestions.set(key, {
                    ruleId: handler.ruleId,
                    fixId: handler.fixId,
                    title: handler.title,
                    description: handler.description,
                    isSafeFix: handler.isSafeFix,
                });
            }
        }
    }
    return [...suggestions.values()].sort((left, right) => {
        const byRule = left.ruleId.localeCompare(right.ruleId);
        if (byRule !== 0) {
            return byRule;
        }
        return left.fixId.localeCompare(right.fixId);
    });
}
function buildFixCandidates(results, onlyRuleId) {
    const failedResults = sortValidationResultsDeterministically(results.filter((result) => !result.passed));
    return failedResults
        .filter((result) => (onlyRuleId ? result.id === onlyRuleId : true))
        .map((result) => ({
        ruleId: result.id,
        finding: result,
    }));
}
function toEmptySummary(mode, safeOnly) {
    return {
        mode,
        safeOnly,
        safeFixesApplied: 0,
        skippedFixes: 0,
        failedFixes: 0,
        applied: [],
        skipped: [],
        failed: [],
        preview: [],
    };
}
function normalizePreview(ruleId, fixId, title, preview) {
    return {
        ruleId,
        fixId,
        title,
        description: preview.description,
        filesCreated: [...preview.filesCreated].sort((left, right) => left.localeCompare(right)),
        filesModified: [...preview.filesModified].sort((left, right) => left.localeCompare(right)),
        diffPreview: preview.diffPreview,
    };
}
async function applyFix(ruleId, context) {
    const candidates = buildFixCandidates(context.validationResults, ruleId);
    return runFixPipeline({
        workspaceRoot: context.workspaceRoot,
        candidates,
        preview: context.preview ?? false,
        safeOnly: context.safeOnly ?? false,
    });
}
async function applyAllSafeFixes(validationResults, workspaceRoot, options) {
    const candidates = buildFixCandidates(validationResults);
    return runFixPipeline({
        workspaceRoot,
        candidates,
        preview: options?.preview ?? false,
        safeOnly: true,
    });
}
async function applyAllFixes(validationResults, workspaceRoot, options) {
    const candidates = buildFixCandidates(validationResults);
    return runFixPipeline({
        workspaceRoot,
        candidates,
        preview: options?.preview ?? false,
        safeOnly: false,
    });
}
async function runFixPipeline(input) {
    const summary = toEmptySummary(input.preview ? 'preview' : 'apply', input.safeOnly);
    for (const candidate of input.candidates) {
        const handlers = (0, fixRegistry_1.getFixHandlersForRule)(candidate.ruleId);
        if (handlers.length === 0) {
            continue;
        }
        for (const handler of handlers) {
            if (input.safeOnly && !handler.isSafeFix) {
                summary.skipped.push({
                    ruleId: handler.ruleId,
                    fixId: handler.fixId,
                    title: handler.title,
                    reason: 'Fix is not marked safe.',
                });
                continue;
            }
            const fixContext = {
                workspaceRoot: input.workspaceRoot,
                finding: candidate.finding,
            };
            if (input.preview) {
                const preview = await handler.previewFix(fixContext);
                summary.preview.push(normalizePreview(handler.ruleId, handler.fixId, handler.title, preview));
                continue;
            }
            try {
                const applied = await handler.applyFix(fixContext);
                if (!applied.applied) {
                    summary.skipped.push({
                        ruleId: handler.ruleId,
                        fixId: handler.fixId,
                        title: handler.title,
                        reason: applied.description,
                    });
                    continue;
                }
                summary.applied.push({
                    ruleId: handler.ruleId,
                    fixId: handler.fixId,
                    title: handler.title,
                    description: applied.description,
                    filesCreated: [...applied.filesCreated].sort((left, right) => left.localeCompare(right)),
                    filesModified: [...applied.filesModified].sort((left, right) => left.localeCompare(right)),
                });
                if (handler.isSafeFix) {
                    summary.safeFixesApplied += 1;
                }
            }
            catch (error) {
                summary.failed.push({
                    ruleId: handler.ruleId,
                    fixId: handler.fixId,
                    title: handler.title,
                    error: error instanceof Error ? error.message : 'Unknown filesystem error.',
                });
                summary.failedFixes = summary.failed.length;
                summary.skippedFixes = summary.skipped.length;
                return summary;
            }
        }
    }
    summary.failedFixes = summary.failed.length;
    summary.skippedFixes = summary.skipped.length;
    return summary;
}
function buildFixSuggestions(results) {
    return toFixSuggestionsForResults(results);
}
function listAllRegisteredFixSuggestions() {
    return (0, fixRegistry_1.listRegisteredFixHandlers)().map((handler) => ({
        ruleId: handler.ruleId,
        fixId: handler.fixId,
        title: handler.title,
        description: handler.description,
        isSafeFix: handler.isSafeFix,
    }));
}
//# sourceMappingURL=remediationEngine.js.map