"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeMemoryHealth = computeMemoryHealth;
exports.formatHealthReport = formatHealthReport;
const database_1 = require("../database/database");
function computeMemoryHealth(project) {
    const db = (0, database_1.getDb)();
    const suggestions = [];
    // Metrics
    const totalRow = db.prepare('SELECT COUNT(*) as c FROM memory_events WHERE project = ?').get(project);
    const since7d = new Date(Date.now() - 7 * 86400000).toISOString();
    const since30d = new Date(Date.now() - 30 * 86400000).toISOString();
    const recentRow = db.prepare('SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND created_at >= ?').get(project, since7d);
    const avgRow = db.prepare('SELECT AVG(importance) as a FROM memory_events WHERE project = ?').get(project);
    const decisionsRow = db.prepare("SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'decision'").get(project);
    const errorsRow = db.prepare("SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'error'").get(project);
    const fixesRow = db.prepare("SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'fix'").get(project);
    const verificationsRow = db.prepare("SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'verification'").get(project);
    const productRulesRow = db.prepare("SELECT COUNT(*) as c FROM memory_events WHERE project = ? AND type = 'product_rule'").get(project);
    const patternsRow = db.prepare('SELECT COUNT(*) as c FROM memory_patterns WHERE project = ?').get(project);
    const topicsRow = db.prepare('SELECT COUNT(DISTINCT topic) as c FROM memory_events WHERE project = ? AND topic IS NOT NULL').get(project);
    const oldestRow = db.prepare('SELECT MIN(created_at) as o FROM memory_events WHERE project = ?').get(project);
    const newestRow = db.prepare('SELECT MAX(created_at) as n FROM memory_events WHERE project = ?').get(project);
    const daysSinceFirst = oldestRow.o ? Math.round((Date.now() - new Date(oldestRow.o).getTime()) / 86400000) : 0;
    const daysSinceLast = newestRow.n ? Math.round((Date.now() - new Date(newestRow.n).getTime()) / 86400000) : 999;
    // Handoff check
    let handoffCurrent = false;
    try {
        const fs = require('fs');
        const path = require('path');
        const cellDir = path.join(process.cwd(), '.cell', 'handoff', 'current.md');
        handoffCurrent = fs.existsSync(cellDir);
    }
    catch { }
    // Style check
    let styleProfileExists = false;
    try {
        const styleRow = db.prepare('SELECT COUNT(*) as c FROM style_profiles WHERE project = ?').get(project);
        styleProfileExists = styleRow.c > 0;
    }
    catch { }
    const metrics = {
        totalEvents: totalRow.c,
        recentEvents7d: recentRow.c,
        avgImportance: Math.round((avgRow.a || 0) * 10) / 10,
        decisionsLogged: decisionsRow.c,
        errorsLogged: errorsRow.c,
        fixesLogged: fixesRow.c,
        verificationsLogged: verificationsRow.c,
        productRulesLogged: productRulesRow.c,
        patternsLearned: patternsRow.c,
        handoffCurrent,
        styleProfileExists,
        uniqueTopics: topicsRow.c,
        daysSinceFirstEvent: daysSinceFirst,
        daysSinceLastEvent: daysSinceLast,
    };
    // Completeness score (0-100): do you have all event types?
    let completeness = 0;
    if (metrics.totalEvents > 0)
        completeness += 10;
    if (metrics.decisionsLogged > 0)
        completeness += 15;
    if (metrics.errorsLogged > 0)
        completeness += 10;
    if (metrics.fixesLogged > 0)
        completeness += 10;
    if (metrics.verificationsLogged > 0)
        completeness += 10;
    if (metrics.productRulesLogged > 0)
        completeness += 15;
    if (metrics.patternsLearned > 0)
        completeness += 10;
    if (metrics.handoffCurrent)
        completeness += 10;
    if (metrics.styleProfileExists)
        completeness += 10;
    if (metrics.decisionsLogged === 0)
        suggestions.push('Log decisions with `cell memory record --type decision`');
    if (metrics.verificationsLogged === 0)
        suggestions.push('Log test runs with `cell memory record --type verification`');
    if (metrics.productRulesLogged === 0)
        suggestions.push('Record product rules with `cell memory record --type product_rule`');
    if (metrics.patternsLearned === 0)
        suggestions.push('Learn patterns with `cell memory record --type pattern`');
    // Freshness score (0-100): how recent is data?
    let freshness = 100;
    if (metrics.daysSinceLastEvent > 1)
        freshness -= 10;
    if (metrics.daysSinceLastEvent > 3)
        freshness -= 20;
    if (metrics.daysSinceLastEvent > 7)
        freshness -= 30;
    if (metrics.daysSinceLastEvent > 14)
        freshness -= 20;
    if (metrics.recentEvents7d === 0)
        freshness -= 20;
    if (metrics.daysSinceLastEvent > 7)
        suggestions.push('Update handoff context — it may be stale');
    // Quality score (0-100): avg importance + error ratio
    let quality = 50;
    if (metrics.avgImportance > 5)
        quality += 20;
    else if (metrics.avgImportance > 3)
        quality += 10;
    if (metrics.avgImportance > 7)
        quality += 10;
    const errorRate = metrics.totalEvents > 0 ? metrics.errorsLogged / metrics.totalEvents : 0;
    if (errorRate < 0.1)
        quality += 20;
    else if (errorRate < 0.2)
        quality += 10;
    else
        quality -= 10;
    if (metrics.fixesLogged > metrics.errorsLogged)
        quality += 10;
    // Balance score (0-100): ratio of different event types
    const typeCounts = {};
    const typeRows = db.prepare('SELECT type, COUNT(*) as c FROM memory_events WHERE project = ? GROUP BY type').all(project);
    for (const r of typeRows)
        typeCounts[r.type] = r.c;
    const types = Object.keys(typeCounts).length;
    let balance = Math.min(types * 12, 60);
    if (types >= 5)
        balance += 20;
    if (types >= 8)
        balance += 20;
    if (types < 3)
        suggestions.push('Record more diverse event types (errors, fixes, decisions)');
    // Engagement score (0-100): consistency of recording
    let engagement = 0;
    if (metrics.totalEvents > 5)
        engagement += 20;
    if (metrics.totalEvents > 20)
        engagement += 20;
    if (metrics.totalEvents > 50)
        engagement += 20;
    if (metrics.recentEvents7d > 0)
        engagement += 20;
    if (metrics.recentEvents7d > 5)
        engagement += 10;
    if (metrics.uniqueTopics > 3)
        engagement += 10;
    if (metrics.totalEvents < 10)
        suggestions.push('Record more events to build memory depth');
    // Overall score
    const overallScore = Math.round(completeness * 0.25 +
        freshness * 0.20 +
        quality * 0.20 +
        balance * 0.15 +
        engagement * 0.20);
    const grade = scoreToGrade(overallScore);
    if (overallScore < 50)
        suggestions.push('Memory system needs attention — run `cell memory health` regularly');
    if (!metrics.handoffCurrent)
        suggestions.push('Create a handoff with `cell handoff --log`');
    if (!metrics.styleProfileExists)
        suggestions.push('Set up your style profile with `cell style update`');
    return {
        project,
        overallScore,
        grade,
        breakdown: {
            completeness,
            freshness,
            quality,
            balance,
            engagement,
        },
        suggestions: [...new Set(suggestions)].slice(0, 8),
        metrics,
        computedAt: new Date().toISOString(),
    };
}
function scoreToGrade(score) {
    if (score >= 95)
        return 'A+';
    if (score >= 90)
        return 'A';
    if (score >= 85)
        return 'B+';
    if (score >= 75)
        return 'B';
    if (score >= 70)
        return 'C+';
    if (score >= 60)
        return 'C';
    if (score >= 40)
        return 'D';
    return 'F';
}
function formatHealthReport(health) {
    const lines = [];
    lines.push(`## Memory Health — ${health.project}`);
    lines.push(`**Score: ${health.overallScore}/100 (${health.grade})**\n`);
    lines.push('### Breakdown');
    lines.push(`| Dimension | Score |`);
    lines.push(`|-----------|-------|`);
    lines.push(`| Completeness | ${health.breakdown.completeness} |`);
    lines.push(`| Freshness | ${health.breakdown.freshness} |`);
    lines.push(`| Quality | ${health.breakdown.quality} |`);
    lines.push(`| Balance | ${health.breakdown.balance} |`);
    lines.push(`| Engagement | ${health.breakdown.engagement} |`);
    lines.push('');
    lines.push('### Metrics');
    lines.push(`| Metric | Value |`);
    lines.push(`|--------|-------|`);
    lines.push(`| Total events | ${health.metrics.totalEvents} |`);
    lines.push(`| Last 7d events | ${health.metrics.recentEvents7d} |`);
    lines.push(`| Avg importance | ${health.metrics.avgImportance} |`);
    lines.push(`| Decisions | ${health.metrics.decisionsLogged} |`);
    lines.push(`| Errors | ${health.metrics.errorsLogged} |`);
    lines.push(`| Fixes | ${health.metrics.fixesLogged} |`);
    lines.push(`| Verifications | ${health.metrics.verificationsLogged} |`);
    lines.push(`| Product rules | ${health.metrics.productRulesLogged} |`);
    lines.push(`| Patterns | ${health.metrics.patternsLearned} |`);
    lines.push(`| Unique topics | ${health.metrics.uniqueTopics} |`);
    lines.push(`| Handoff current | ${health.metrics.handoffCurrent ? 'yes' : 'no'} |`);
    lines.push(`| Style profile | ${health.metrics.styleProfileExists ? 'yes' : 'no'} |`);
    lines.push(`| Days tracked | ${health.metrics.daysSinceFirstEvent} |`);
    lines.push('');
    if (health.suggestions.length > 0) {
        lines.push('### Suggestions');
        for (const s of health.suggestions)
            lines.push(`- ${s}`);
        lines.push('');
    }
    return lines.join('\n');
}
//# sourceMappingURL=memory-health.js.map