"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.detectCodingRhythm = detectCodingRhythm;
exports.detectBurnout = detectBurnout;
exports.trackSkillProgression = trackSkillProgression;
exports.getTechMasteryMap = getTechMasteryMap;
exports.generatePersonalInsights = generatePersonalInsights;
exports.getCareerTrajectory = getCareerTrajectory;
exports.generateWeeklyDigest = generateWeeklyDigest;
const database_1 = require("../../06-memory/database/database");
// ─── Coding Rhythm Detector ──────────────────────────────────────────────────
function detectCodingRhythm() {
    (0, database_1.initializeDatabase)();
    const db = (0, database_1.getDb)();
    const sessions = db.prepare("SELECT start_time, end_time, files_touched FROM sessions WHERE end_time IS NOT NULL").all();
    const bugs = db.prepare("SELECT created_at FROM behavior_events WHERE event_type = 'bug_fix'").all();
    const hourStats = new Map();
    const dayStats = new Map();
    const days = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
    for (const s of sessions) {
        try {
            const start = new Date(s.start_time);
            const end = new Date(s.end_time);
            if (isNaN(start.getTime()) || isNaN(end.getTime()))
                continue;
            const mins = (end.getTime() - start.getTime()) / (1000 * 60);
            const hour = start.getHours();
            const day = days[start.getDay()];
            const hs = hourStats.get(hour) || { sessions: 0, bugs: 0, totalMins: 0 };
            hs.sessions++;
            hs.totalMins += mins;
            hourStats.set(hour, hs);
            const ds = dayStats.get(day) || { sessions: 0, bugs: 0, totalMins: 0 };
            ds.sessions++;
            ds.totalMins += mins;
            dayStats.set(day, ds);
        }
        catch { /* skip */ }
    }
    for (const b of bugs) {
        try {
            const d = new Date(b.created_at);
            if (isNaN(d.getTime()))
                continue;
            const hour = d.getHours();
            const day = days[d.getDay()];
            const hs = hourStats.get(hour);
            if (hs)
                hs.bugs++;
            const ds = dayStats.get(day);
            if (ds)
                ds.bugs++;
        }
        catch { /* skip */ }
    }
    const hourlyBreakdown = {};
    for (const [hour, stats] of hourStats) {
        const quality = stats.sessions > 0 ? Math.max(0, 100 - Math.round((stats.bugs / stats.sessions) * 100)) : 100;
        hourlyBreakdown[hour] = { sessions: stats.sessions, bugs: stats.bugs, quality };
    }
    const dayBreakdown = {};
    for (const [day, stats] of dayStats) {
        const quality = stats.sessions > 0 ? Math.max(0, 100 - Math.round((stats.bugs / stats.sessions) * 100)) : 100;
        dayBreakdown[day] = { commits: stats.sessions, bugs: stats.bugs, quality };
    }
    const sortedHours = [...hourStats.entries()].sort((a, b) => {
        const qA = a[1].sessions > 0 ? 1 - (a[1].bugs / a[1].sessions) : 1;
        const qB = b[1].sessions > 0 ? 1 - (b[1].bugs / b[1].sessions) : 1;
        return qB - qA;
    });
    const sortedDays = [...dayStats.entries()].sort((a, b) => {
        const qA = a[1].sessions > 0 ? 1 - (a[1].bugs / a[1].sessions) : 1;
        const qB = b[1].sessions > 0 ? 1 - (b[1].bugs / b[1].sessions) : 1;
        return qB - qA;
    });
    const bestHours = sortedHours.slice(0, 3).map(([h]) => `${h}:00-${h + 1}:00`);
    const worstHours = sortedHours.slice(-3).map(([h]) => `${h}:00-${h + 1}:00`);
    const bestDays = sortedDays.slice(0, 2).map(([d]) => d);
    const worstDays = sortedDays.slice(-2).map(([d]) => d);
    let totalMins = 0;
    let sessionCount = 0;
    for (const [, stats] of hourStats) {
        totalMins += stats.totalMins;
        sessionCount += stats.sessions;
    }
    const avgSessionMinutes = sessionCount > 0 ? Math.round(totalMins / sessionCount) : 45;
    const optimalSessionMinutes = Math.round(avgSessionMinutes * 1.2);
    return {
        bestHours,
        bestDays,
        worstHours,
        worstDays,
        avgSessionMinutes,
        optimalSessionMinutes,
        peakFlowWindow: bestHours[0] || '10:00-11:00',
        dayBreakdown,
        hourlyBreakdown,
    };
}
// ─── Burnout Predictor ───────────────────────────────────────────────────────
function detectBurnout() {
    const db = (0, database_1.getDb)();
    const signals = [];
    const recentBugs = db.prepare("SELECT created_at FROM behavior_events WHERE event_type = 'bug_fix' AND created_at >= datetime('now', '-14 days')").all();
    const olderBugs = db.prepare("SELECT created_at FROM behavior_events WHERE event_type = 'bug_fix' AND created_at >= datetime('now', '-28 days') AND created_at < datetime('now', '-14 days')").all();
    const recentErrorRate = recentBugs.length / 14;
    const olderErrorRate = olderBugs.length / 14 || 0.01;
    const errorTrend = recentErrorRate > olderErrorRate * 1.5 ? 'increasing' : recentErrorRate < olderErrorRate * 0.7 ? 'decreasing' : 'stable';
    if (errorTrend === 'increasing') {
        signals.push(`Error rate increased ${Math.round((recentErrorRate / olderErrorRate) * 100)}% in last 2 weeks`);
    }
    const recentSessions = db.prepare("SELECT start_time, end_time FROM sessions WHERE start_time >= datetime('now', '-14 days') AND end_time IS NOT NULL").all();
    const olderSessions = db.prepare("SELECT start_time, end_time FROM sessions WHERE start_time >= datetime('now', '-28 days') AND start_time < datetime('now', '-14 days') AND end_time IS NOT NULL").all();
    const avgRecentDuration = recentSessions.length > 0
        ? recentSessions.reduce((sum, s) => sum + (new Date(s.end_time).getTime() - new Date(s.start_time).getTime()) / 60000, 0) / recentSessions.length
        : 0;
    const avgOlderDuration = olderSessions.length > 0
        ? olderSessions.reduce((sum, s) => sum + (new Date(s.end_time).getTime() - new Date(s.start_time).getTime()) / 60000, 0) / olderSessions.length
        : 0;
    const sessionTrend = avgRecentDuration < avgOlderDuration * 0.7 ? 'decreasing' : avgRecentDuration > avgOlderDuration * 1.3 ? 'increasing' : 'stable';
    if (sessionTrend === 'decreasing') {
        signals.push(`Average session length dropped from ${Math.round(avgOlderDuration)}min to ${Math.round(avgRecentDuration)}min`);
    }
    const recentReverts = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE description LIKE '%revert%' AND created_at >= datetime('now', '-14 days')").get();
    if (recentReverts.cnt > 2) {
        signals.push(`${recentReverts.cnt} reverts in last 2 weeks — possible fatigue`);
    }
    const recentCommits = recentSessions.length;
    const olderCommits = olderSessions.length;
    const commitTrend = recentCommits < olderCommits * 0.6 ? 'decreasing' : 'stable';
    if (commitTrend === 'decreasing') {
        signals.push(`Commit frequency dropped from ${olderCommits} to ${recentCommits} sessions`);
    }
    let severity = 'none';
    if (signals.length >= 3)
        severity = 'severe';
    else if (signals.length === 2)
        severity = 'moderate';
    else if (signals.length === 1)
        severity = 'mild';
    let suggestion = '';
    if (severity === 'severe')
        suggestion = 'Strong burnout signals detected. Take a 2-3 day break. Your error rate is 2x normal and session lengths have halved.';
    else if (severity === 'moderate')
        suggestion = 'Moderate burnout risk. Consider a lighter schedule this week. Your metrics are trending downward.';
    else if (severity === 'mild')
        suggestion = 'Minor fatigue detected. Take a longer break between sessions today.';
    else
        suggestion = 'No burnout signals. Keep up the healthy rhythm!';
    return {
        detected: severity !== 'none',
        severity,
        signals,
        metrics: {
            errorRateTrend: `${Math.round(recentErrorRate * 100)}/day (was ${Math.round(olderErrorRate * 100)}/day)`,
            sessionLengthTrend: `${Math.round(avgRecentDuration)}min avg (was ${Math.round(avgOlderDuration)}min)`,
            revertRate: `${recentReverts.cnt} reverts in 2 weeks`,
            commitFrequencyTrend: `${recentCommits} sessions (was ${olderCommits})`,
        },
        suggestion,
        confidence: Math.min(0.9, 0.4 + signals.length * 0.15),
    };
}
// ─── Skill Progression Tracker ───────────────────────────────────────────────
function trackSkillProgression() {
    const db = (0, database_1.getDb)();
    const skills = db.prepare('SELECT * FROM skills ORDER BY file_count DESC').all();
    const progressions = [];
    for (const skill of skills) {
        const lang = String(skill.language || '');
        if (!lang || lang.length < 2)
            continue;
        const firstSeen = String(skill.first_seen || '');
        const lastActive = String(skill.last_active || '');
        const monthsActive = firstSeen ? Math.max(1, Math.round((Date.now() - new Date(firstSeen).getTime()) / (30 * 24 * 60 * 60 * 1000))) : 0;
        const bugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND file_path LIKE ?").get(`%${lang.toLowerCase()}%`);
        const totalFiles = Number(skill.file_count || 0);
        const errorRate = totalFiles > 0 ? bugs.cnt / totalFiles : 0;
        const recentBugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND file_path LIKE ? AND created_at >= datetime('now', '-30 days')").get(`%${lang.toLowerCase()}%`);
        const olderBugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND file_path LIKE ? AND created_at >= datetime('now', '-60 days') AND created_at < datetime('now', '-30 days')").get(`%${lang.toLowerCase()}%`);
        const errorTrend = recentBugs.cnt < olderBugs.cnt * 0.7 ? 'improving' : recentBugs.cnt > olderBugs.cnt * 1.3 ? 'worsening' : 'stable';
        let stage = 'learning';
        let stageNumber = 1;
        if (monthsActive >= 6 && errorTrend !== 'worsening' && totalFiles > 20) {
            stage = 'mastery';
            stageNumber = 3;
        }
        else if (monthsActive >= 2 && errorTrend !== 'worsening') {
            stage = 'pattern_formation';
            stageNumber = 2;
        }
        const milestones = [];
        if (totalFiles > 10)
            milestones.push(`${totalFiles} files written`);
        if (monthsActive >= 1)
            milestones.push(`${monthsActive} months active`);
        if (errorTrend === 'improving')
            milestones.push('Error rate improving');
        if (stageNumber >= 2)
            milestones.push('Pattern formation detected');
        if (stageNumber >= 3)
            milestones.push('Mastery achieved');
        progressions.push({
            language: lang,
            stage,
            stageNumber,
            firstSeen,
            lastActive,
            monthsActive,
            totalFiles,
            totalLines: Number(skill.line_count || 0),
            errorRate: Math.round(errorRate * 100) / 100,
            errorTrend,
            milestones,
            evidence: [`Stage ${stageNumber}: ${stage}`, `${monthsActive} months active`, `${totalFiles} files, ${bugs.cnt} bugs`],
        });
    }
    return progressions.sort((a, b) => b.stageNumber - a.stageNumber || b.monthsActive - a.monthsActive);
}
// ─── Technology Mastery Map ──────────────────────────────────────────────────
function getTechMasteryMap() {
    const db = (0, database_1.getDb)();
    const skills = db.prepare('SELECT * FROM skills ORDER BY file_count DESC').all();
    const mastery = [];
    for (const skill of skills) {
        const lang = String(skill.language || '');
        if (!lang || lang.length < 2)
            continue;
        const monthsActive = String(skill.first_seen || '')
            ? Math.max(1, Math.round((Date.now() - new Date(String(skill.first_seen)).getTime()) / (30 * 24 * 60 * 60 * 1000)))
            : 0;
        const fileCount = Number(skill.file_count || 0);
        const lineCount = Number(skill.line_count || 0);
        const projects = db.prepare("SELECT COUNT(DISTINCT project) as cnt FROM behavior_events WHERE file_path LIKE ?").get(`%${lang.toLowerCase()}%`);
        const recentBugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND file_path LIKE ? AND created_at >= datetime('now', '-30 days')").get(`%${lang.toLowerCase()}%`);
        const olderBugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND file_path LIKE ? AND created_at >= datetime('now', '-90 days') AND created_at < datetime('now', '-30 days')").get(`%${lang.toLowerCase()}%`);
        const recentErrorRate = fileCount > 0 ? recentBugs.cnt / fileCount : 0;
        const historicalErrorRate = fileCount > 0 ? olderBugs.cnt / fileCount : 0;
        let stage = 'learning';
        let confidence = 30;
        if (monthsActive >= 8 && recentErrorRate < 0.05 && fileCount > 30) {
            stage = 'mastered';
            confidence = 95;
        }
        else if (monthsActive >= 4 && recentErrorRate < 0.1 && fileCount > 15) {
            stage = 'advanced';
            confidence = 80;
        }
        else if (monthsActive >= 2 && fileCount > 5) {
            stage = 'proficient';
            confidence = 60;
        }
        const actualPerformance = Math.max(0, Math.min(100, 100 - Math.round(recentErrorRate * 200)));
        const confidenceGap = Math.abs(confidence - actualPerformance);
        const descriptions = {
            mastered: `${lang}: ${monthsActive} months, ${fileCount} files, near-zero errors. Mastery achieved.`,
            advanced: `${lang}: ${monthsActive} months, ${fileCount} files, low error rate. Advanced level.`,
            proficient: `${lang}: ${monthsActive} months, ${fileCount} files. Proficient — building patterns.`,
            learning: `${lang}: ${monthsActive || '<1'} month, ${fileCount} files. Still learning — expect errors.`,
        };
        mastery.push({
            language: lang,
            stage,
            confidence,
            actualPerformance,
            confidenceGap,
            monthsActive,
            projectCount: projects.cnt,
            fileCount,
            lineCount,
            recentErrorRate: Math.round(recentErrorRate * 100) / 100,
            historicalErrorRate: Math.round(historicalErrorRate * 100) / 100,
            description: descriptions[stage],
        });
    }
    return mastery.sort((a, b) => b.confidence - a.confidence);
}
// ─── Insight Generation Engine ───────────────────────────────────────────────
function generatePersonalInsights() {
    const db = (0, database_1.getDb)();
    const insights = [];
    const totalSessions = db.prepare('SELECT COUNT(*) as cnt FROM sessions').get().cnt;
    const totalBugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix'").get().cnt;
    const totalDecisions = db.prepare('SELECT COUNT(*) as cnt FROM decisions').get().cnt;
    const rightDecisions = db.prepare('SELECT COUNT(*) as cnt FROM decisions WHERE was_right = 1').get().cnt;
    const accuracy = totalDecisions > 0 ? Math.round((rightDecisions / totalDecisions) * 100) : 0;
    const patterns = db.prepare('SELECT COUNT(*) as cnt FROM patterns').get().cnt;
    const skills = db.prepare('SELECT COUNT(*) as cnt FROM skills WHERE level != ?').get('new');
    insights.push({
        type: '6month',
        title: '6-Month Intelligence Report',
        content: `In the last period: ${totalSessions} sessions, ${totalBugs} bugs fixed, ${totalDecisions} decisions (${accuracy}% accurate). ${patterns} patterns learned across ${skills.cnt} technologies.`,
        metrics: { sessions: totalSessions, bugs: totalBugs, decisions: totalDecisions, accuracy, patterns, technologies: skills.cnt },
        generatedAt: new Date().toISOString(),
    });
    const progression = trackSkillProgression();
    const mastered = progression.filter(p => p.stage === 'mastery');
    const learning = progression.filter(p => p.stage === 'learning');
    insights.push({
        type: '1year',
        title: 'Growth Trajectory',
        content: `Technologies mastered: ${mastered.length} (${mastered.map(m => m.language).join(', ') || 'none yet'}). Still learning: ${learning.length} (${learning.map(l => l.language).join(', ') || 'none'}).`,
        metrics: { mastered: mastered.length, learning: learning.length, total: progression.length },
        generatedAt: new Date().toISOString(),
    });
    const rhythm = detectCodingRhythm();
    insights.push({
        type: 'weekly',
        title: 'Weekly Digest',
        content: `Best hours: ${rhythm.bestHours.join(', ') || 'no data'}. Best days: ${rhythm.bestDays.join(', ') || 'no data'}. Optimal session: ${rhythm.optimalSessionMinutes}min.`,
        metrics: { bestHour: 0, avgSession: rhythm.avgSessionMinutes },
        generatedAt: new Date().toISOString(),
    });
    return insights;
}
// ─── Career Trajectory ───────────────────────────────────────────────────────
function getCareerTrajectory() {
    const db = (0, database_1.getDb)();
    const progression = trackSkillProgression();
    const mastery = getTechMasteryMap();
    const totalSessions = db.prepare('SELECT COUNT(*) as cnt FROM sessions').get().cnt;
    const totalDecisions = db.prepare('SELECT COUNT(*) as cnt FROM decisions').get().cnt;
    const rightDecisions = db.prepare('SELECT COUNT(*) as cnt FROM decisions WHERE was_right = 1').get().cnt;
    const accuracy = totalDecisions > 0 ? (rightDecisions / totalDecisions) * 100 : 0;
    const masteredCount = mastery.filter(m => m.stage === 'mastered').length;
    const advancedCount = mastery.filter(m => m.stage === 'advanced').length;
    const totalMonths = mastery.reduce((sum, m) => sum + m.monthsActive, 0);
    let level = 'junior';
    let levelConfidence = 50;
    if (masteredCount >= 3 && accuracy >= 80 && totalSessions > 50) {
        level = 'senior';
        levelConfidence = 85;
    }
    else if (masteredCount >= 1 && advancedCount >= 2 && accuracy >= 65) {
        level = 'mid';
        levelConfidence = 75;
    }
    else if (totalMonths >= 3) {
        level = 'mid';
        levelConfidence = 55;
    }
    const seniorReadiness = Math.min(100, Math.round((masteredCount * 25) + (advancedCount * 15) + (accuracy * 0.3) + (totalSessions > 30 ? 10 : 0)));
    const monthsToSenior = Math.max(0, Math.round((100 - seniorReadiness) / 5));
    const strongAreas = mastery.filter(m => m.stage === 'mastered' || m.stage === 'advanced').map(m => m.language);
    const weakAreas = progression.filter(p => p.stage === 'learning').map(p => p.language);
    const recommendations = [];
    if (weakAreas.length > 0)
        recommendations.push(`Level up: ${weakAreas.join(', ')}`);
    if (accuracy < 70)
        recommendations.push(`Improve decision accuracy (currently ${Math.round(accuracy)}%)`);
    if (masteredCount < 2)
        recommendations.push('Aim to master 2+ technologies before senior');
    if (totalSessions < 30)
        recommendations.push('Increase coding sessions for more evidence');
    return {
        currentLevel: level,
        levelConfidence: Math.round(levelConfidence),
        seniorReadiness,
        monthsToSenior,
        weakAreas,
        strongAreas,
        recommendations,
        evidence: [
            `${masteredCount} technologies mastered`,
            `${advancedCount} technologies advanced`,
            `${accuracy}% decision accuracy`,
            `${totalSessions} total sessions`,
            `${totalMonths} total months active`,
        ],
        growthRate: Math.round(seniorReadiness / Math.max(1, totalMonths)),
    };
}
// ─── Weekly Digest ───────────────────────────────────────────────────────────
function generateWeeklyDigest() {
    const db = (0, database_1.getDb)();
    const since = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000).toISOString();
    const sessions = db.prepare("SELECT COUNT(*) as cnt FROM sessions WHERE start_time >= ?").get(since).cnt;
    const bugs = db.prepare("SELECT COUNT(*) as cnt FROM behavior_events WHERE event_type = 'bug_fix' AND created_at >= ?").get(since).cnt;
    const decisions = db.prepare("SELECT COUNT(*) as cnt FROM decisions WHERE created_at >= ?").get(since).cnt;
    const patterns = db.prepare("SELECT COUNT(*) as cnt FROM patterns WHERE created_at >= ?").get(since).cnt;
    const topLangs = db.prepare("SELECT language, file_count FROM skills ORDER BY file_count DESC LIMIT 3").all();
    const highlights = [];
    if (sessions > 0)
        highlights.push(`${sessions} coding sessions`);
    if (decisions > 0)
        highlights.push(`${decisions} decisions tracked`);
    if (patterns > 0)
        highlights.push(`${patterns} new patterns`);
    const improvements = [];
    const rhythm = detectCodingRhythm();
    if (rhythm.bestHours.length > 0)
        improvements.push(`Peak hours identified: ${rhythm.bestHours[0]}`);
    const focus = [];
    if (bugs > 5)
        focus.push(`${bugs} bugs this week — review error patterns`);
    return {
        period: 'Last 7 days',
        totalSessions: sessions,
        totalBugs: bugs,
        totalDecisions: decisions,
        newPatterns: patterns,
        topLanguages: topLangs.map(l => l.language),
        highlights,
        improvements,
        areasToFocus: focus,
    };
}
//# sourceMappingURL=personal-intelligence.js.map