// engine/usage-tracker/stats.ts — Usage statistics calculation (pure functions, no I/O).
// ---------------------------------------------------------------------------
// Stats calculation
// ---------------------------------------------------------------------------
/**
 * Computes full UsageStats from a set of events and runtime context.
 * All parameters are passed in — no I/O performed here.
 */
export function calculateUsageStats(events, activeSpecs, activeProjects, currentTier, daysSinceFirstRun, isTrialActive, remainingDailyCalls) {
    const callsByTool = {};
    const callsByTier = {};
    for (const event of events) {
        callsByTool[event.toolName] = (callsByTool[event.toolName] ?? 0) + 1;
        callsByTier[event.tier] = (callsByTier[event.tier] ?? 0) + 1;
    }
    const topTools = buildTopTools(callsByTool, 10);
    const { breakdown: toolHealthBreakdown, deadTools } = buildToolHealthBreakdown(events);
    return {
        totalCalls: events.length,
        callsByTool,
        callsByTier,
        topTools,
        activeSpecs,
        activeProjects,
        currentTier,
        daysSinceFirstRun,
        isTrialActive,
        remainingDailyCalls,
        toolHealthBreakdown,
        deadTools,
    };
}
// ---------------------------------------------------------------------------
// Top tools helper
// ---------------------------------------------------------------------------
function buildTopTools(callsByTool, limit) {
    return Object.entries(callsByTool)
        .map(([name, count]) => ({ name, count }))
        .sort((a, b) => b.count - a.count)
        .slice(0, limit);
}
// ---------------------------------------------------------------------------
// Tool health breakdown helper
// ---------------------------------------------------------------------------
export function buildToolHealthBreakdown(events, allKnownTools) {
    const perTool = new Map();
    for (const event of events) {
        const existing = perTool.get(event.toolName) ?? { success: 0, error: 0 };
        if (event.success) {
            existing.success += 1;
        }
        else {
            existing.error += 1;
        }
        perTool.set(event.toolName, existing);
    }
    const breakdown = [];
    for (const [name, counts] of perTool.entries()) {
        const totalCalls = counts.success + counts.error;
        const successRate = totalCalls > 0 ? counts.success / totalCalls : 1;
        breakdown.push({
            name,
            totalCalls,
            successCount: counts.success,
            errorCount: counts.error,
            successRate,
        });
    }
    // Sort by successRate ascending (most broken first)
    breakdown.sort((a, b) => a.successRate - b.successRate);
    const calledTools = new Set(perTool.keys());
    const deadTools = allKnownTools !== undefined ? allKnownTools.filter((t) => !calledTools.has(t)) : [];
    return { breakdown, deadTools };
}
// ---------------------------------------------------------------------------
// Markdown formatting
// ---------------------------------------------------------------------------
/**
 * Formats a UsageStats object as a readable markdown report.
 */
export function formatStatsAsMarkdown(stats) {
    const lines = [];
    lines.push('## Usage Statistics');
    lines.push('');
    lines.push(`**Tier:** ${stats.currentTier}`);
    lines.push(`**Days since first run:** ${String(stats.daysSinceFirstRun)}`);
    lines.push(`**Trial active:** ${stats.isTrialActive ? 'Yes' : 'No'}`);
    lines.push(`**Total calls:** ${String(stats.totalCalls)}`);
    lines.push(`**Active specs:** ${String(stats.activeSpecs)}`);
    lines.push(`**Active projects:** ${String(stats.activeProjects)}`);
    if (stats.remainingDailyCalls >= 0) {
        lines.push(`**Remaining daily calls:** ${String(stats.remainingDailyCalls)}`);
    }
    lines.push('');
    lines.push('### Top Tools');
    lines.push('');
    lines.push('| Tool | Calls |');
    lines.push('|------|-------|');
    for (const tool of stats.topTools) {
        lines.push(`| ${tool.name} | ${String(tool.count)} |`);
    }
    if (stats.topTools.length === 0) {
        lines.push('| *(no calls yet)* | 0 |');
    }
    lines.push('');
    lines.push('### Tool Health');
    lines.push('');
    lines.push('| Tool | Calls | Success Rate | Errors |');
    lines.push('|------|-------|--------------|--------|');
    if (stats.toolHealthBreakdown.length === 0) {
        lines.push('| *(no calls yet)* | 0 | — | 0 |');
    }
    else {
        for (const entry of stats.toolHealthBreakdown) {
            const ratePercent = Math.round(entry.successRate * 100);
            const prefix = entry.successRate < 0.5 ? '⚠️ ' : '';
            lines.push(`| ${prefix}${entry.name} | ${String(entry.totalCalls)} | ${String(ratePercent)}% | ${String(entry.errorCount)} |`);
        }
    }
    if (stats.deadTools.length > 0) {
        lines.push('');
        lines.push('### Unused Tools');
        lines.push('');
        for (const tool of stats.deadTools) {
            lines.push(`- ${tool}`);
        }
    }
    lines.push('');
    lines.push('### Calls by Tier');
    lines.push('');
    lines.push('| Tier | Calls |');
    lines.push('|------|-------|');
    const tierEntries = Object.entries(stats.callsByTier);
    if (tierEntries.length === 0) {
        lines.push('| *(none)* | 0 |');
    }
    else {
        for (const [tier, count] of tierEntries) {
            lines.push(`| ${tier} | ${String(count)} |`);
        }
    }
    return lines.join('\n');
}
//# sourceMappingURL=stats.js.map