"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.NormalizedMatcher = void 0;
class NormalizedMatcher {
    constructor() {
        this.name = 'NormalizedMatcher';
        this.confidenceThreshold = parseFloat(process.env.NORMALIZED_MATCH_THRESHOLD || '0.95');
    }
    match(searchBlock, content) {
        const normalizedSearch = this.normalizeForComparison(searchBlock);
        const normalizedContent = this.normalizeForComparison(content);
        if (!normalizedSearch.trim()) {
            return {
                found: false,
                unique: false,
                confidence: 0,
                candidates: [],
            };
        }
        const candidates = this.findSimilarCandidates(normalizedSearch, normalizedContent, content);
        if (candidates.length === 0) {
            return {
                found: false,
                unique: false,
                confidence: 0,
                candidates: [],
            };
        }
        const highConfidenceCandidates = candidates.filter((c) => c.confidence >= this.confidenceThreshold);
        if (highConfidenceCandidates.length === 0) {
            return {
                found: true,
                unique: false,
                confidence: Math.max(...candidates.map((c) => c.confidence)),
                candidates,
            };
        }
        if (highConfidenceCandidates.length === 1) {
            const candidate = highConfidenceCandidates[0];
            const before = this.extractOriginalBefore(candidate, content);
            const after = this.extractOriginalAfter(candidate, content);
            return {
                found: true,
                unique: true,
                confidence: candidate.confidence,
                before,
                after,
            };
        }
        return {
            found: true,
            unique: false,
            confidence: Math.max(...highConfidenceCandidates.map((c) => c.confidence)),
            candidates: highConfidenceCandidates,
        };
    }
    normalizeForComparison(text) {
        return text
            .split('\n')
            .map((line) => line.trim())
            .map((line) => line.replace(/\t/g, '  '))
            .join('\n')
            .trim();
    }
    findSimilarCandidates(normalizedSearch, normalizedContent, originalContent) {
        const candidates = [];
        const normalizedLines = normalizedContent.split('\n');
        const searchLines = normalizedSearch.split('\n');
        const originalLines = originalContent.split('\n');
        for (let i = 0; i <= normalizedLines.length - searchLines.length; i++) {
            const windowLines = normalizedLines.slice(i, i + searchLines.length);
            const windowText = windowLines.join('\n');
            const similarity = this.calculateSimilarity(normalizedSearch, windowText);
            if (similarity > 0.5) {
                const beforeAnchor = i > 0 ? originalLines[i - 1] : undefined;
                const afterAnchor = i + searchLines.length < originalLines.length
                    ? originalLines[i + searchLines.length]
                    : undefined;
                const originalBlock = originalLines
                    .slice(i, i + searchLines.length)
                    .join('\n');
                candidates.push({
                    block: originalBlock,
                    startLine: i,
                    endLine: i + searchLines.length - 1,
                    confidence: similarity,
                    beforeAnchor,
                    afterAnchor,
                });
            }
        }
        return candidates.sort((a, b) => b.confidence - a.confidence);
    }
    calculateSimilarity(a, b) {
        if (a === b)
            return 1.0;
        if (a.length === 0)
            return 0.0;
        if (b.length === 0)
            return 0.0;
        const distance = this.levenshteinDistance(a, b);
        const maxLen = Math.max(a.length, b.length);
        return 1.0 - distance / maxLen;
    }
    levenshteinDistance(a, b) {
        const matrix = [];
        for (let i = 0; i <= b.length; i++) {
            matrix[i] = [i];
        }
        for (let j = 0; j <= a.length; j++) {
            matrix[0][j] = j;
        }
        for (let i = 1; i <= b.length; i++) {
            for (let j = 1; j <= a.length; j++) {
                const cost = b[i - 1] === a[j - 1] ? 0 : 1;
                matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
            }
        }
        return matrix[b.length][a.length];
    }
    extractOriginalBefore(candidate, content) {
        const lines = content.split('\n');
        return lines.slice(0, candidate.startLine).join('\n');
    }
    extractOriginalAfter(candidate, content) {
        const lines = content.split('\n');
        return lines.slice(candidate.endLine + 1).join('\n');
    }
}
exports.NormalizedMatcher = NormalizedMatcher;
//# sourceMappingURL=normalized.matcher.js.map