/**
 * Update Recommender
 *
 * Generates recommendations for handling discrepancies and creates update patches.
 *
 * @module core/discrepancy/update-recommender
 */
import { consoleLogger } from '../../utils/logger.js';
/**
 * Generates recommendations for handling discrepancies.
 */
export class UpdateRecommender {
    constructor(options = {}) {
        this.logger = options.logger ?? consoleLogger;
        this.config = {
            autoUpdateTrivial: options.config?.autoUpdateTrivial ?? false,
            generatePatches: options.config?.generatePatches ?? true,
        };
    }
    /**
     * Generate recommendations for a list of discrepancies.
     */
    recommendAll(discrepancies) {
        return discrepancies.map(d => this.recommend(d));
    }
    /**
     * Generate a recommendation for a single discrepancy.
     */
    recommend(discrepancy) {
        const recommendation = this.mapSeverityToRecommendation(discrepancy.severity);
        const explanation = this.generateExplanation(discrepancy, recommendation);
        const riskLevel = this.assessRisk(discrepancy);
        const result = {
            discrepancyId: discrepancy.id,
            recommendation,
            explanation,
            riskLevel,
        };
        // Generate patch if applicable
        if (this.config.generatePatches && this.shouldGeneratePatch(discrepancy, recommendation)) {
            result.patch = this.generatePatch(discrepancy);
        }
        return result;
    }
    /**
     * Generate an update patch for a discrepancy.
     */
    generatePatch(discrepancy) {
        // Can only generate patches for modifications and additions with spec files
        if (!discrepancy.specPath && discrepancy.category !== 'added') {
            return undefined;
        }
        switch (discrepancy.type) {
            case 'api-route':
                return this.generateApiRoutePatch(discrepancy);
            case 'function-signature':
                return this.generateFunctionPatch(discrepancy);
            case 'type-definition':
                return this.generateTypePatch(discrepancy);
            default:
                return undefined;
        }
    }
    mapSeverityToRecommendation(severity) {
        const actionMap = {
            trivial: 'auto-update',
            minor: 'review-required',
            major: 'notify',
            breaking: 'alert',
        };
        return actionMap[severity];
    }
    generateExplanation(discrepancy, recommendation) {
        const typeLabel = discrepancy.type.replace('-', ' ');
        const categoryMessages = {
            added: `New ${typeLabel} found in code that is not documented.`,
            removed: `Documented ${typeLabel} no longer exists in code.`,
            modified: `${typeLabel} has changed from documented version.`,
        };
        const recommendationMessages = {
            'auto-update': 'This is a trivial change that can be safely auto-updated.',
            'review-required': 'Please review the change before updating documentation.',
            notify: 'This is a significant change that should be communicated to stakeholders.',
            alert: 'This is a breaking change! Consumers may be affected.',
        };
        return [
            categoryMessages[discrepancy.category],
            'Code is the source of truth - specs should be updated to match.',
            recommendationMessages[recommendation],
        ].join(' ');
    }
    assessRisk(discrepancy) {
        // Breaking changes are high risk
        if (discrepancy.severity === 'breaking') {
            return 'high';
        }
        // Removals are always at least medium risk
        if (discrepancy.category === 'removed') {
            return 'medium';
        }
        // API route changes are medium risk
        if (discrepancy.type === 'api-route' && discrepancy.category === 'modified') {
            return 'medium';
        }
        // Additions are low risk (new undocumented functionality)
        if (discrepancy.category === 'added') {
            return 'low';
        }
        // Minor modifications are low risk
        if (discrepancy.severity === 'minor' || discrepancy.severity === 'trivial') {
            return 'low';
        }
        return 'medium';
    }
    shouldGeneratePatch(discrepancy, recommendation) {
        // Alerts need manual handling - no patches
        if (recommendation === 'alert') {
            return false;
        }
        // Generate patches for auto-update, review-required, or notify with additions
        return recommendation === 'auto-update' ||
            recommendation === 'review-required' ||
            (recommendation === 'notify' && discrepancy.category === 'added');
    }
    generateApiRoutePatch(discrepancy) {
        if (discrepancy.category === 'added') {
            // Generate new documentation section
            const method = discrepancy.codeValue.split(' ')[0];
            const path = discrepancy.codeValue.split(' ')[1] || discrepancy.codeValue;
            return {
                filePath: discrepancy.codePath || 'docs/api.md',
                lineNumber: 0, // Append to end
                originalText: '',
                newText: this.generateApiDocSection(method, path),
                reason: 'Add documentation for new API route',
            };
        }
        if (discrepancy.category === 'modified' && discrepancy.specPath) {
            return {
                filePath: discrepancy.specPath,
                lineNumber: discrepancy.specLineNumber,
                originalText: discrepancy.specValue,
                newText: discrepancy.codeValue,
                reason: discrepancy.description,
            };
        }
        if (discrepancy.category === 'removed' && discrepancy.specPath) {
            return {
                filePath: discrepancy.specPath,
                lineNumber: discrepancy.specLineNumber,
                originalText: discrepancy.specValue,
                newText: `~~${discrepancy.specValue}~~ *(DEPRECATED - removed from code)*`,
                reason: 'Mark removed API route as deprecated',
            };
        }
        return undefined;
    }
    generateFunctionPatch(discrepancy) {
        if (discrepancy.category === 'added') {
            return {
                filePath: discrepancy.codePath || 'docs/api.md',
                lineNumber: 0,
                originalText: '',
                newText: this.generateFunctionDocSection(discrepancy.codeValue),
                reason: 'Add documentation for new function',
            };
        }
        if (discrepancy.category === 'modified' && discrepancy.specPath) {
            return {
                filePath: discrepancy.specPath,
                lineNumber: discrepancy.specLineNumber,
                originalText: discrepancy.specValue,
                newText: discrepancy.codeValue,
                reason: discrepancy.description,
            };
        }
        return undefined;
    }
    generateTypePatch(discrepancy) {
        if (discrepancy.category === 'added') {
            return {
                filePath: discrepancy.codePath || 'docs/types.md',
                lineNumber: 0,
                originalText: '',
                newText: this.generateTypeDocSection(discrepancy.codeValue),
                reason: 'Add documentation for new type',
            };
        }
        return undefined;
    }
    generateApiDocSection(method, path) {
        return `
## ${method} ${path}

*TODO: Add description*

### Request

*TODO: Document request parameters*

### Response

*TODO: Document response format*
`.trim();
    }
    generateFunctionDocSection(signature) {
        return `
### \`${signature}\`

*TODO: Add description*

#### Parameters

*TODO: Document parameters*

#### Returns

*TODO: Document return value*
`.trim();
    }
    generateTypeDocSection(typeValue) {
        return `
### ${typeValue}

*TODO: Add type description*

#### Properties

*TODO: Document properties*
`.trim();
    }
    /**
     * Generate a summary report of recommendations.
     */
    generateReport(recommendations) {
        const lines = ['# Discrepancy Recommendations Report', ''];
        const byRecommendation = this.groupBy(recommendations, r => r.recommendation);
        // Summary
        lines.push('## Summary', '');
        lines.push(`- Total discrepancies: ${recommendations.length}`);
        lines.push(`- Auto-update: ${byRecommendation['auto-update']?.length ?? 0}`);
        lines.push(`- Review required: ${byRecommendation['review-required']?.length ?? 0}`);
        lines.push(`- Notify: ${byRecommendation['notify']?.length ?? 0}`);
        lines.push(`- Alert: ${byRecommendation['alert']?.length ?? 0}`);
        lines.push('');
        // Alerts first (most important)
        if (byRecommendation['alert']?.length) {
            lines.push('## ⚠️ Alerts (Breaking Changes)', '');
            for (const r of byRecommendation['alert']) {
                lines.push(`### ${r.discrepancyId}`);
                lines.push(r.explanation);
                lines.push('');
            }
        }
        // Notifications
        if (byRecommendation['notify']?.length) {
            lines.push('## 📢 Notifications (Major Changes)', '');
            for (const r of byRecommendation['notify']) {
                lines.push(`### ${r.discrepancyId}`);
                lines.push(r.explanation);
                if (r.patch) {
                    lines.push('');
                    lines.push('**Suggested update:**');
                    lines.push('```');
                    lines.push(r.patch.newText);
                    lines.push('```');
                }
                lines.push('');
            }
        }
        // Review required
        if (byRecommendation['review-required']?.length) {
            lines.push('## 👀 Review Required (Minor Changes)', '');
            for (const r of byRecommendation['review-required']) {
                lines.push(`- **${r.discrepancyId}**: ${r.explanation}`);
            }
            lines.push('');
        }
        // Auto-update
        if (byRecommendation['auto-update']?.length) {
            lines.push('## ✅ Auto-Update (Trivial Changes)', '');
            for (const r of byRecommendation['auto-update']) {
                lines.push(`- **${r.discrepancyId}**: ${r.explanation}`);
            }
            lines.push('');
        }
        return lines.join('\n');
    }
    groupBy(items, keyFn) {
        const result = {};
        for (const item of items) {
            const key = keyFn(item);
            if (!result[key]) {
                result[key] = [];
            }
            result[key].push(item);
        }
        return result;
    }
}
//# sourceMappingURL=update-recommender.js.map