/**
 * Model Analytics
 *
 * Tracks per-model, per-task-type performance metrics in SQLite.
 * Used by the dashboard to show model usage, cost, and success rates.
 */
import Database from 'better-sqlite3';
import { existsSync, mkdirSync } from 'fs';
import { join } from 'path';
export class ModelAnalytics {
    db;
    constructor(dbPath) {
        const resolvedPath = dbPath || join(process.cwd(), 'agents', 'data', 'memory', 'model_analytics.db');
        const dir = join(resolvedPath, '..');
        if (!existsSync(dir)) {
            mkdirSync(dir, { recursive: true });
        }
        this.db = new Database(resolvedPath);
        this.db.pragma('journal_mode = WAL');
        this.initialize();
    }
    initialize() {
        this.db.exec(`
      CREATE TABLE IF NOT EXISTS task_outcomes (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        modelId TEXT NOT NULL,
        taskType TEXT NOT NULL,
        complexity TEXT NOT NULL,
        success INTEGER NOT NULL,
        durationMs INTEGER NOT NULL,
        tokensIn INTEGER NOT NULL DEFAULT 0,
        tokensOut INTEGER NOT NULL DEFAULT 0,
        cost REAL NOT NULL DEFAULT 0,
        taskId TEXT,
        timestamp TEXT NOT NULL
      );

      CREATE INDEX IF NOT EXISTS idx_outcomes_model ON task_outcomes(modelId);
      CREATE INDEX IF NOT EXISTS idx_outcomes_type ON task_outcomes(taskType);
      CREATE INDEX IF NOT EXISTS idx_outcomes_time ON task_outcomes(timestamp);
      CREATE INDEX IF NOT EXISTS idx_outcomes_task ON task_outcomes(taskId);
    `);
    }
    /**
     * Record a task outcome
     */
    recordOutcome(outcome) {
        const sql = `INSERT INTO task_outcomes (modelId, taskType, complexity, success, durationMs, tokensIn, tokensOut, cost, taskId, timestamp) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`;
        this.db
            .prepare(sql)
            .run(outcome.modelId, outcome.taskType, outcome.complexity, outcome.success ? 1 : 0, outcome.durationMs, outcome.tokensUsed.input, outcome.tokensUsed.output, outcome.cost, outcome.taskId || null, outcome.timestamp || new Date().toISOString());
    }
    /**
     * Get success rate for a model, optionally filtered by task type
     */
    getSuccessRate(modelId, taskType) {
        let sql = 'SELECT COUNT(*) as total, SUM(success) as successes FROM task_outcomes WHERE modelId = ?';
        const params = [modelId];
        if (taskType) {
            sql += ' AND taskType = ?';
            params.push(taskType);
        }
        const row = this.db.prepare(sql).get(...params);
        if (!row || row.total === 0)
            return 0;
        return row.successes / row.total;
    }
    /**
     * Get average latency for a model
     */
    getAvgLatency(modelId, taskType) {
        let sql = 'SELECT AVG(durationMs) as avg FROM task_outcomes WHERE modelId = ?';
        const params = [modelId];
        if (taskType) {
            sql += ' AND taskType = ?';
            params.push(taskType);
        }
        const row = this.db.prepare(sql).get(...params);
        return row?.avg || 0;
    }
    /**
     * Get metrics grouped by model and task type
     */
    getMetrics(modelId) {
        let sql = `
      SELECT
        modelId,
        taskType,
        COUNT(*) as totalTasks,
        SUM(success) as successes,
        COUNT(*) - SUM(success) as failures,
        CAST(SUM(success) AS REAL) / COUNT(*) as successRate,
        AVG(durationMs) as avgDurationMs,
        SUM(tokensIn) as totalTokensIn,
        SUM(tokensOut) as totalTokensOut,
        SUM(cost) as totalCost
      FROM task_outcomes
    `;
        const params = [];
        if (modelId) {
            sql += ' WHERE modelId = ?';
            params.push(modelId);
        }
        sql += ' GROUP BY modelId, taskType ORDER BY modelId, totalTasks DESC';
        return this.db.prepare(sql).all(...params);
    }
    /**
     * Get cost breakdown per model
     */
    getCostBreakdown(since) {
        let sql = `
      SELECT
        modelId,
        SUM(cost) as totalCost,
        COUNT(*) as taskCount,
        AVG(cost) as avgCostPerTask,
        SUM(tokensIn) as totalTokensIn,
        SUM(tokensOut) as totalTokensOut
      FROM task_outcomes
    `;
        const params = [];
        if (since) {
            sql += ' WHERE timestamp >= ?';
            params.push(since.toISOString());
        }
        sql += ' GROUP BY modelId ORDER BY totalCost DESC';
        return this.db.prepare(sql).all(...params);
    }
    /**
     * Get session model usage (all outcomes in current session)
     */
    getSessionUsage() {
        const sql = `
      SELECT
        modelId,
        COUNT(*) as taskCount,
        SUM(tokensIn) as totalTokensIn,
        SUM(tokensOut) as totalTokensOut,
        SUM(cost) as totalCost,
        CAST(SUM(success) AS REAL) / COUNT(*) as successRate
      FROM task_outcomes
      GROUP BY modelId
      ORDER BY taskCount DESC
    `;
        return this.db.prepare(sql).all();
    }
    /**
     * Get outcomes for a specific task
     */
    getTaskOutcomes(taskId) {
        const rows = this.db
            .prepare('SELECT * FROM task_outcomes WHERE taskId = ? ORDER BY timestamp')
            .all(taskId);
        return rows.map((r) => ({
            modelId: r.modelId ?? '',
            taskType: r.taskType ?? '',
            complexity: r.complexity ?? 'low',
            success: r.success === 1,
            durationMs: r.durationMs ?? 0,
            tokensUsed: { input: r.tokensIn ?? 0, output: r.tokensOut ?? 0 },
            cost: r.cost ?? 0,
            taskId: r.taskId ?? '',
            timestamp: r.timestamp ?? new Date().toISOString(),
        }));
    }
    /**
     * Get optimal routing suggestion based on historical data
     */
    getOptimalRouting() {
        const sql = `
      SELECT taskType, modelId, CAST(SUM(success) AS REAL) / COUNT(*) as rate, COUNT(*) as cnt
      FROM task_outcomes
      GROUP BY taskType, modelId
      HAVING cnt >= 3
      ORDER BY taskType, rate DESC
    `;
        const rows = this.db.prepare(sql).all();
        const result = {};
        for (const row of rows) {
            if (!result[row.taskType]) {
                result[row.taskType] = row.modelId;
            }
        }
        return result;
    }
    /**
     * Get total session cost
     */
    getTotalCost() {
        const row = this.db.prepare('SELECT SUM(cost) as total FROM task_outcomes').get();
        return row?.total || 0;
    }
    close() {
        this.db.close();
    }
}
// Lazy singleton
let _instance = null;
export function getModelAnalytics() {
    if (!_instance) {
        _instance = new ModelAnalytics();
    }
    return _instance;
}
//# sourceMappingURL=analytics.js.map