"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.generateSmartRecommendations = generateSmartRecommendations;
exports.getRecommendationSummary = getRecommendationSummary;
const database_1 = require("../database/database");
function generateSmartRecommendations(project, context) {
    const db = (0, database_1.getDb)();
    const recs = [];
    const since7d = new Date(Date.now() - 7 * 86400000).toISOString();
    const since30d = new Date(Date.now() - 30 * 86400000).toISOString();
    // 1. Unfixed errors — suggest fix priority
    const unfixedErrors = db.prepare(`
    SELECT id, summary, topic, files_json, importance, created_at FROM memory_events
    WHERE project = ? AND type = 'error'
    AND id NOT IN (
      SELECT DISTINCT e2.id FROM memory_events e2
      WHERE e2.project = ? AND e2.type = 'fix'
    )
    ORDER BY importance DESC, created_at DESC LIMIT 10
  `).all(project, project);
    for (const err of unfixedErrors) {
        recs.push({
            id: `fix-${err.id}`,
            category: 'action',
            priority: err.importance >= 8 ? 'high' : err.importance >= 6 ? 'medium' : 'low',
            title: `Fix: ${err.summary.slice(0, 80)}`,
            description: `Error logged ${formatAge(err.created_at)} ago without a corresponding fix. Importance: ${err.importance}/10.`,
            rationale: `Unresolved errors accumulate and become harder to fix over time.`,
            confidence: 0.85,
            relatedFiles: parseFiles(err.files_json),
            relatedTopics: err.topic ? [err.topic] : [],
            createdAt: new Date().toISOString(),
        });
    }
    // 2. High-frequency files need refactoring
    const hotFiles = db.prepare(`
    SELECT files_json, COUNT(*) as c, MAX(importance) as maxImp FROM memory_events
    WHERE project = ? AND files_json IS NOT NULL AND created_at >= ?
    GROUP BY files_json HAVING c >= 8 ORDER BY c DESC LIMIT 5
  `).all(project, since30d);
    for (const hf of hotFiles) {
        const files = parseFiles(hf.files_json);
        if (files.length > 0) {
            recs.push({
                id: `refactor-${hashStr(files[0])}`,
                category: 'optimize',
                priority: hf.c > 15 ? 'high' : 'medium',
                title: `Consider refactoring: ${files[0]}`,
                description: `File touched ${hf.c} times in 30 days — may be a hotspot needing decomposition.`,
                rationale: `High edit frequency suggests the file has too many responsibilities.`,
                confidence: 0.7,
                relatedFiles: files,
                relatedTopics: ['refactor'],
                createdAt: new Date().toISOString(),
            });
        }
    }
    // 3. Missing tests for error-prone files
    const errorFiles = db.prepare(`
    SELECT files_json, COUNT(*) as c FROM memory_events
    WHERE project = ? AND type = 'error' AND files_json IS NOT NULL AND created_at >= ?
    GROUP BY files_json ORDER BY c DESC LIMIT 5
  `).all(project, since30d);
    const testFiles = db.prepare(`
    SELECT files_json FROM memory_events
    WHERE project = ? AND type = 'verification' AND files_json IS NOT NULL AND created_at >= ?
  `).all(project, since30d);
    const testedPaths = new Set();
    for (const tf of testFiles) {
        for (const f of parseFiles(tf.files_json))
            testedPaths.add(f);
    }
    for (const ef of errorFiles) {
        const files = parseFiles(ef.files_json);
        for (const f of files) {
            if (!testedPaths.has(f) && !f.includes('.test.') && !f.includes('.spec.')) {
                recs.push({
                    id: `test-${hashStr(f)}`,
                    category: 'prevent',
                    priority: ef.c > 3 ? 'high' : 'medium',
                    title: `Add tests for: ${f}`,
                    description: `File has ${ef.c} errors but no test coverage logged.`,
                    rationale: `Files with repeated errors should have tests to prevent regressions.`,
                    confidence: 0.75,
                    relatedFiles: [f],
                    relatedTopics: ['testing'],
                    createdAt: new Date().toISOString(),
                });
                break;
            }
        }
    }
    // 4. Decision gaps — too many events without decisions
    const eventCount = db.prepare(`SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND created_at >= ?`).get(project, since7d);
    const decisionCount = db.prepare(`SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'decision' AND created_at >= ?`).get(project, since7d);
    if (eventCount.c > 20 && decisionCount.c < 3) {
        recs.push({
            id: 'decision-gap',
            category: 'improve',
            priority: 'medium',
            title: 'Log more decisions',
            description: `${eventCount.c} events but only ${decisionCount.c} decisions in 7 days. Decisions help AI understand your reasoning.`,
            rationale: `Decision memory is critical for context continuity and AI recommendations.`,
            confidence: 0.65,
            relatedFiles: [],
            relatedTopics: ['memory-system'],
            createdAt: new Date().toISOString(),
        });
    }
    // 5. Handoff staleness — suggest update
    const lastHandoff = db.prepare(`
    SELECT created_at FROM memory_events
    WHERE project = ? AND type = 'handoff' ORDER BY created_at DESC LIMIT 1
  `).get(project);
    if (lastHandoff) {
        const daysSince = (Date.now() - new Date(lastHandoff.created_at).getTime()) / 86400000;
        if (daysSince > 5) {
            recs.push({
                id: 'stale-handoff',
                category: 'action',
                priority: 'medium',
                title: 'Update handoff context',
                description: `Last handoff was ${Math.round(daysSince)} days ago. Context may be stale.`,
                rationale: `Fresh handoff context helps AI understand current project state.`,
                confidence: 0.7,
                relatedFiles: [],
                relatedTopics: ['handoff'],
                createdAt: new Date().toISOString(),
            });
        }
    }
    // 6. Error patterns — suggest systematic fix
    const errorPatterns = db.prepare(`
    SELECT topic, COUNT(*) as c FROM memory_events
    WHERE project = ? AND type = 'error' AND topic IS NOT NULL AND created_at >= ?
    GROUP BY topic HAVING c >= 3 ORDER BY c DESC LIMIT 3
  `).all(project, since30d);
    for (const ep of errorPatterns) {
        recs.push({
            id: `pattern-${hashStr(ep.topic)}`,
            category: 'prevent',
            priority: ep.c > 5 ? 'high' : 'medium',
            title: `Systematic fix for "${ep.topic}" errors`,
            description: `${ep.c} errors in the "${ep.topic}" area suggest a systemic issue.`,
            rationale: `Addressing root cause prevents repeated fixes on the same problem.`,
            confidence: 0.75,
            relatedFiles: [],
            relatedTopics: [ep.topic],
            createdAt: new Date().toISOString(),
        });
    }
    // 7. Learning suggestions — based on patterns you use
    const typeCounts = db.prepare(`
    SELECT type, COUNT(*) as c FROM memory_events
    WHERE project = ? AND created_at >= ?
    GROUP BY type ORDER BY c DESC
  `).all(project, since30d);
    const typeMap = {};
    for (const t of typeCounts)
        typeMap[t.type] = t.c;
    if ((typeMap.fix || 0) > (typeMap.verification || 0) * 3) {
        recs.push({
            id: 'learn-testing',
            category: 'learn',
            priority: 'medium',
            title: 'Improve verification coverage',
            description: 'You fix errors 3x more often than you verify. Consider adding more test runs.',
            rationale: 'Balanced fix/verification ratio leads to more stable code.',
            confidence: 0.6,
            relatedFiles: [],
            relatedTopics: ['testing', 'verification'],
            createdAt: new Date().toISOString(),
        });
    }
    return recs.sort((a, b) => {
        const prioOrder = { high: 0, medium: 1, low: 2 };
        return prioOrder[a.priority] - prioOrder[b.priority];
    });
}
function getRecommendationSummary(project) {
    const recs = generateSmartRecommendations(project);
    const byCategory = {};
    for (const r of recs)
        byCategory[r.category] = (byCategory[r.category] || 0) + 1;
    return {
        total: recs.length,
        high: recs.filter(r => r.priority === 'high').length,
        medium: recs.filter(r => r.priority === 'medium').length,
        low: recs.filter(r => r.priority === 'low').length,
        byCategory,
        top3: recs.slice(0, 3),
    };
}
function parseFiles(filesJson) {
    if (!filesJson)
        return [];
    try {
        const parsed = JSON.parse(filesJson);
        return Array.isArray(parsed) ? parsed : [];
    }
    catch {
        return [];
    }
}
function formatAge(dateStr) {
    const ms = Date.now() - new Date(dateStr).getTime();
    const hours = Math.round(ms / 3600000);
    if (hours < 1)
        return 'just now';
    if (hours < 24)
        return `${hours}h`;
    const days = Math.round(hours / 24);
    return `${days}d`;
}
function hashStr(s) {
    let hash = 0;
    for (let i = 0; i < s.length; i++) {
        hash = ((hash << 5) - hash + s.charCodeAt(i)) | 0;
    }
    return Math.abs(hash).toString(36);
}
//# sourceMappingURL=smart-recommendations.js.map