"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.logDecisionOutcome = logDecisionOutcome;
exports.getDecisionOutcomes = getDecisionOutcomes;
exports.getDecisionPatterns = getDecisionPatterns;
exports.detectRepeatMistakes = detectRepeatMistakes;
exports.getAIInteractionStats = getAIInteractionStats;
exports.logProductivitySignal = logProductivitySignal;
exports.getProductivitySignals = getProductivitySignals;
exports.getSkillProgression = getSkillProgression;
exports.getBurnoutSignals = getBurnoutSignals;
exports.getUsageDashboard = getUsageDashboard;
const database_1 = require("../database/database");
// ─── Decision History with Outcomes (6.2) ─────────────────────────────────
function logDecisionOutcome(params) {
    const db = (0, database_1.getDb)();
    const result = db.prepare(`
    INSERT INTO decision_outcomes (project, technology, reason, outcome, was_right, confidence, context)
    VALUES (?, ?, ?, ?, ?, ?, ?)
  `).run(params.project, params.technology, params.reason || '', params.outcome || '', params.wasRight ? 1 : 0, params.confidence || 50, params.context || '');
    return { id: Number(result.lastInsertRowid) };
}
function getDecisionOutcomes(project, limit = 50) {
    const db = (0, database_1.getDb)();
    const rows = db.prepare(`
    SELECT id, project, technology, reason, outcome, was_right, confidence, context, created_at
    FROM decision_outcomes WHERE project = ? ORDER BY created_at DESC LIMIT ?
  `).all(project, limit);
    return rows.map(r => ({
        id: Number(r.id),
        project: String(r.project || ''),
        technology: String(r.technology || ''),
        reason: String(r.reason || ''),
        outcome: String(r.outcome || ''),
        wasRight: r.was_right === 1,
        confidence: Number(r.confidence || 50),
        context: String(r.context || ''),
        createdAt: String(r.created_at || ''),
    }));
}
function getDecisionPatterns(project) {
    const db = (0, database_1.getDb)();
    const rows = db.prepare(`
    SELECT technology, COUNT(*) as total,
           SUM(CASE WHEN was_right = 1 THEN 1 ELSE 0 END) as right_count,
           SUM(CASE WHEN was_right = 0 THEN 1 ELSE 0 END) as wrong_count
    FROM decision_outcomes WHERE project = ?
    GROUP BY technology
    HAVING total >= 2
    ORDER BY total DESC
  `).all(project);
    return rows.map(r => {
        const regretRate = r.total > 0 ? r.wrong_count / r.total : 0;
        let advice;
        if (regretRate >= 0.7) {
            advice = `🚨 STOP picking ${r.technology} — ${Math.round(regretRate * 100)}% regret rate (${r.wrong_count}/${r.total})`;
        }
        else if (regretRate >= 0.5) {
            advice = `⚠ Be careful with ${r.technology} — ${Math.round(regretRate * 100)}% regret rate`;
        }
        else if (regretRate <= 0.2 && r.total >= 3) {
            advice = `✓ ${r.technology} is a great choice — ${Math.round((r.right_count / r.total) * 100)}% success rate`;
        }
        else {
            advice = `${r.technology} has mixed results — review specific cases`;
        }
        return {
            technology: r.technology,
            timesChosen: r.total,
            timesRight: r.right_count,
            timesWrong: r.wrong_count,
            regretRate,
            advice,
        };
    });
}
// ─── Repeat Mistakes Map (6.3) ────────────────────────────────────────────
function detectRepeatMistakes(project) {
    const db = (0, database_1.getDb)();
    // Mine error_log
    const errorRows = db.prepare(`
    SELECT error_type, file_path, COUNT(*) as count, MAX(occurred_at) as last_seen
    FROM error_log
    WHERE project = ?
    GROUP BY error_type, file_path
    HAVING count >= 2
    ORDER BY count DESC
  `).all(project);
    const mistakes = errorRows.map(r => {
        const severity = r.count >= 5 ? 'critical' : r.count >= 3 ? 'warning' : 'info';
        const filePattern = r.file_path ? r.file_path.replace(/\d+/g, '*').replace(/\/[^/]+$/, '/*') : 'unknown';
        return {
            errorType: r.error_type,
            filePattern,
            count: r.count,
            lastSeen: r.last_seen,
            severity,
            suggestion: getSuggestionForError(r.error_type, r.count),
        };
    });
    // Also save to alerts table for tracking dismissal
    for (const m of mistakes) {
        const existing = db.prepare(`
      SELECT id FROM repeat_mistake_alerts
      WHERE project = ? AND error_type = ? AND file_pattern = ?
    `).get(project, m.errorType, m.filePattern);
        if (existing) {
            db.prepare(`
        UPDATE repeat_mistake_alerts SET occurrence_count = ?, last_seen = ?
        WHERE id = ?
      `).run(m.count, m.lastSeen, existing.id);
        }
        else {
            db.prepare(`
        INSERT INTO repeat_mistake_alerts (project, error_type, file_pattern, occurrence_count, last_seen)
        VALUES (?, ?, ?, ?, ?)
      `).run(project, m.errorType, m.filePattern, m.count, m.lastSeen);
        }
    }
    return mistakes;
}
function getSuggestionForError(errorType, count) {
    const tips = {
        null_check: 'Add a guard at function entry or use optional chaining everywhere',
        validation: 'Add Zod/Joi schema for this input type',
        n_plus_1: 'Use eager loading or batch query — check EXPLAIN plan',
        async_error: 'Wrap awaits in try/catch — never let rejections slip',
        sql_injection: 'Use parameterized queries — never concatenate user input',
        off_by_one: 'Walk through loop boundaries on paper; add boundary tests',
        type_error: 'Add TypeScript strict mode + explicit return types',
        import_error: 'Check path resolution; use explicit .ts extensions',
    };
    return tips[errorType] || `Review pattern — seen ${count}x`;
}
// ─── AI Interaction Pattern Tracking (6.5) ────────────────────────────────
function getAIInteractionStats(project) {
    const db = (0, database_1.getDb)();
    // Aggregate model_profiles (global) + model_interactions (per project if present)
    const profiles = db.prepare(`
    SELECT model_name, acceptance_rate, rejection_rate, avg_time_ms, best_use_cases, worst_use_cases
    FROM model_profiles
  `).all();
    // Try to get per-project interaction count from model_interactions
    const interactions = db.prepare(`
    SELECT model_name,
           COUNT(*) as total,
           SUM(CASE WHEN accepted = 1 THEN 1 ELSE 0 END) as accepted,
           SUM(CASE WHEN accepted = 0 THEN 1 ELSE 0 END) as rejected,
           AVG(time_to_accept_ms) as avg_time
    FROM model_interactions
    WHERE project = ? OR project IS NULL
    GROUP BY model_name
  `).all(project);
    const interactionMap = new Map(interactions.map(i => [i.model_name, i]));
    return profiles.map(p => {
        const ints = interactionMap.get(p.model_name);
        const accepted = ints?.accepted || 0;
        const rejected = ints?.rejected || 0;
        const total = ints?.total || 0;
        const acceptanceRate = total > 0 ? accepted / total : Number(p.acceptance_rate || 0);
        let recommendation;
        if (acceptanceRate >= 0.8)
            recommendation = `Strong match for this project — keep using ${p.model_name}`;
        else if (acceptanceRate >= 0.5)
            recommendation = `Decent — review rejections to find better task types`;
        else if (total > 0)
            recommendation = `Low acceptance — consider switching for this task type`;
        else
            recommendation = `No data yet — track interactions to get personalized recommendations`;
        return {
            modelName: p.model_name,
            totalInteractions: total,
            accepted,
            rejected,
            acceptanceRate,
            avgIterations: Number(ints?.avg_time || p.avg_time_ms || 0) / 1000,
            bestUseCases: safeJsonArr(p.best_use_cases),
            worstUseCases: safeJsonArr(p.worst_use_cases),
            recommendation,
        };
    });
}
function safeJsonArr(s) {
    if (typeof s !== 'string' || !s)
        return [];
    try {
        return JSON.parse(s);
    }
    catch {
        return [];
    }
}
// ─── Productivity Intelligence (6.4) ──────────────────────────────────────
function logProductivitySignal(params) {
    const db = (0, database_1.getDb)();
    // Heuristics:
    //   flow: many files, low switches, long duration
    //   friction: many switches, few files
    //   context_switch: many switches regardless
    //   long_session: very long duration
    const flowScore = Math.min(100, Math.round((params.filesTouched * 5)
        + (params.durationMinutes / 2)
        - (params.contextSwitches * 3)));
    const frictionScore = Math.min(100, Math.round((params.contextSwitches * 8)
        - (params.filesTouched * 2)));
    const isFlow = flowScore > 50 ? 1 : 0;
    const result = db.prepare(`
    INSERT INTO productivity_signals
      (project, signal_type, duration_minutes, files_touched, context_switches, flow_state, friction_score)
    VALUES (?, ?, ?, ?, ?, ?, ?)
  `).run(params.project, params.signalType, params.durationMinutes, params.filesTouched, params.contextSwitches, isFlow, frictionScore);
    return { id: Number(result.lastInsertRowid), flowScore, frictionScore };
}
function getProductivitySignals(project, days = 30) {
    const db = (0, database_1.getDb)();
    const rows = db.prepare(`
    SELECT signal_type, duration_minutes, files_touched, context_switches, flow_state, friction_score, created_at
    FROM productivity_signals
    WHERE project = ? AND created_at >= datetime('now', ?)
    ORDER BY created_at DESC
  `).all(project, `-${days} days`);
    return rows.map(r => {
        const friction = Number(r.friction_score || 0);
        const files = Number(r.files_touched || 0);
        const switches = Number(r.context_switches || 0);
        const dur = Number(r.duration_minutes || 0);
        // Recompute flow score from raw values (flow_state is just 0/1 boolean)
        const flow = Math.min(100, Math.round((files * 5) + (dur / 2) - (switches * 3)));
        let recommendation;
        if (flow > 50)
            recommendation = `Strong flow — keep doing what you were doing`;
        else if (friction > 60)
            recommendation = `High friction — reduce context switches or batch tasks`;
        else if (switches > 10)
            recommendation = `Many context switches — consider time-boxing`;
        else
            recommendation = `Normal productivity`;
        return {
            signalType: String(r.signal_type || 'flow'),
            durationMinutes: dur,
            filesTouched: files,
            contextSwitches: switches,
            flowScore: flow,
            frictionScore: friction,
            recommendation,
            createdAt: String(r.created_at || ''),
        };
    });
}
// ─── Skill Progression (6.6) ─────────────────────────────────────────────
function getSkillProgression(project) {
    const db = (0, database_1.getDb)();
    const techs = db.prepare(`
    SELECT technology, signals_count, proficiency_score
    FROM tech_proficiency WHERE project = ?
  `).all(project);
    // Get error counts per tech (rough: file_path contains tech name)
    return techs.map(t => {
        const tech = t.technology;
        const errors30 = db.prepare(`
      SELECT COUNT(*) as c FROM error_log
      WHERE project = ? AND occurred_at >= datetime('now', '-30 days')
    `).get(project).c;
        const errors90 = db.prepare(`
      SELECT COUNT(*) as c FROM error_log
      WHERE project = ? AND occurred_at >= datetime('now', '-90 days')
    `).get(project).c;
        const errorsLast60 = errors90 - errors30;
        // Trend: compare last 30 days to previous 30 days
        let trend = 'stable';
        if (errors30 < errorsLast60 * 0.7)
            trend = 'improving';
        else if (errors30 > errorsLast60 * 1.3)
            trend = 'regressing';
        const proficiency = t.proficiency_score;
        const plateau = trend === 'stable' && proficiency >= 50 && proficiency < 80 && t.signals_count > 20;
        let advice;
        if (trend === 'improving')
            advice = `Making fewer errors with ${tech} — keep learning`;
        else if (trend === 'regressing')
            advice = `More errors in ${tech} recently — review fundamentals`;
        else if (plateau)
            advice = `${tech} plateau detected — try a stretch project`;
        else
            advice = `Steady with ${tech} — explore advanced patterns`;
        return {
            technology: tech,
            errorsLast30d: errors30,
            errorsLast90d: errors90,
            trend,
            proficiency,
            plateau,
            advice,
        };
    });
}
// ─── Burnout Detection (6.4 supplement) ──────────────────────────────────
function getBurnoutSignals(project) {
    const db = (0, database_1.getDb)();
    // Look at sessions + productivity signals
    const signals = [];
    const sessionStats = db.prepare(`
    SELECT
      AVG(CASE WHEN end_time IS NOT NULL AND start_time IS NOT NULL
          THEN (julianday(end_time) - julianday(start_time)) * 24 * 60
          ELSE NULL END) as avg_duration_min,
      COUNT(*) as total,
      SUM(CASE WHEN start_time >= datetime('now', '-7 days') THEN 1 ELSE 0 END) as week_count
    FROM sessions WHERE project = ?
  `).get(project);
    const prodSignals = db.prepare(`
    SELECT AVG(context_switches) as avg_switches, AVG(friction_score) as avg_friction
    FROM productivity_signals
    WHERE project = ? AND created_at >= datetime('now', '-7 days')
  `).get(project);
    const avgSession = Math.round(Number(sessionStats.avg_duration_min || 0));
    const weekCount = sessionStats.week_count || 0;
    const avgSwitches = Number(prodSignals.avg_switches || 0);
    const avgFriction = Number(prodSignals.avg_friction || 0);
    // Risk calculation
    let riskScore = 0;
    if (avgSession > 180) {
        riskScore += 2;
        signals.push(`Long sessions (avg ${avgSession} min)`);
    }
    if (weekCount > 30) {
        riskScore += 2;
        signals.push(`High session frequency (${weekCount} in 7 days)`);
    }
    if (avgSwitches > 8) {
        riskScore += 1;
        signals.push(`Many context switches (avg ${avgSwitches.toFixed(1)})`);
    }
    if (avgFriction > 50) {
        riskScore += 2;
        signals.push(`High friction (${avgFriction.toFixed(0)})`);
    }
    const risk = riskScore >= 5 ? 'high' : riskScore >= 3 ? 'medium' : 'low';
    let advice;
    if (risk === 'high')
        advice = 'Take a break — high burnout risk detected';
    else if (risk === 'medium')
        advice = 'Monitor workload — some warning signs';
    else
        advice = 'Healthy work pattern — keep it up';
    return {
        risk,
        signals,
        avgSessionLength: avgSession,
        sessionFrequency: weekCount,
        contextSwitchRate: avgSwitches,
        advice,
    };
}
// ─── Combined Dashboard ──────────────────────────────────────────────────
function getUsageDashboard(project) {
    const decisions = getDecisionOutcomes(project, 200);
    const patterns = getDecisionPatterns(project);
    const mistakes = detectRepeatMistakes(project);
    const ai = getAIInteractionStats(project);
    const prod = getProductivitySignals(project, 30);
    const skills = getSkillProgression(project);
    const burnout = getBurnoutSignals(project);
    const flowScore = prod.length > 0
        ? Math.round(prod.reduce((s, p) => s + p.flowScore, 0) / prod.length)
        : 0;
    const frictionScore = prod.length > 0
        ? Math.round(prod.reduce((s, p) => s + p.frictionScore, 0) / prod.length)
        : 0;
    return {
        decisions: {
            total: decisions.length,
            right: decisions.filter(d => d.wasRight).length,
            wrong: decisions.filter(d => !d.wasRight).length,
            topPatterns: patterns.slice(0, 5),
        },
        mistakes: {
            total: mistakes.length,
            critical: mistakes.filter(m => m.severity === 'critical').length,
            top: mistakes.slice(0, 5),
        },
        ai: {
            modelsUsed: ai.length,
            avgAcceptance: ai.length > 0
                ? Math.round(ai.reduce((s, a) => s + a.acceptanceRate * 100, 0) / ai.length)
                : 0,
            topModel: ai.length > 0
                ? ai.sort((a, b) => b.acceptanceRate - a.acceptanceRate)[0].modelName
                : 'none',
        },
        productivity: {
            flowScore,
            frictionScore,
            sessionsToday: 0,
        },
        skills: {
            improving: skills.filter(s => s.trend === 'improving').length,
            plateau: skills.filter(s => s.plateau).length,
            regressing: skills.filter(s => s.trend === 'regressing').length,
        },
        burnout,
        generatedAt: new Date().toISOString(),
    };
}
//# sourceMappingURL=usage-intelligence-store.js.map