/**
 * Analytics Repository
 *
 * Repository for analytics, tool statistics, and repair learning.
 */
import { getDatabaseManager } from '../database-manager.js';
// ============================================================================
// Analytics Repository
// ============================================================================
export class AnalyticsRepository {
    db;
    constructor(db) {
        this.db = db || getDatabaseManager().getDatabase();
    }
    // ============================================================================
    // Analytics Methods
    // ============================================================================
    /**
     * Record daily analytics
     */
    recordAnalytics(data) {
        const stmt = this.db.prepare(`
      INSERT INTO analytics (date, project_id, model, tokens_in, tokens_out, cost, requests, tool_calls, errors, avg_response_time_ms, cache_hit_rate, session_count)
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      ON CONFLICT(date, project_id, model) DO UPDATE SET
        tokens_in = analytics.tokens_in + excluded.tokens_in,
        tokens_out = analytics.tokens_out + excluded.tokens_out,
        cost = analytics.cost + excluded.cost,
        requests = analytics.requests + excluded.requests,
        tool_calls = analytics.tool_calls + excluded.tool_calls,
        errors = analytics.errors + excluded.errors,
        avg_response_time_ms = (analytics.avg_response_time_ms * analytics.requests + excluded.avg_response_time_ms * excluded.requests) / (analytics.requests + excluded.requests),
        cache_hit_rate = (analytics.cache_hit_rate * analytics.requests + excluded.cache_hit_rate * excluded.requests) / (analytics.requests + excluded.requests),
        session_count = analytics.session_count + excluded.session_count
    `);
        stmt.run(data.date, data.project_id || null, data.model || null, data.tokens_in, data.tokens_out, data.cost, data.requests, data.tool_calls, data.errors, data.avg_response_time_ms, data.cache_hit_rate, data.session_count);
    }
    /**
     * Get analytics by filter
     */
    getAnalytics(filter = {}) {
        let sql = 'SELECT * FROM analytics WHERE 1=1';
        const params = [];
        if (filter.startDate) {
            sql += ' AND date >= ?';
            params.push(filter.startDate);
        }
        if (filter.endDate) {
            sql += ' AND date <= ?';
            params.push(filter.endDate);
        }
        if (filter.projectId) {
            sql += ' AND project_id = ?';
            params.push(filter.projectId);
        }
        if (filter.model) {
            sql += ' AND model = ?';
            params.push(filter.model);
        }
        sql += ' ORDER BY date DESC';
        const stmt = this.db.prepare(sql);
        return stmt.all(...params);
    }
    /**
     * Get daily summary
     */
    getDailySummary(days = 30) {
        const stmt = this.db.prepare(`
      SELECT
        date,
        SUM(cost) as totalCost,
        SUM(requests) as totalRequests,
        SUM(tokens_in + tokens_out) as totalTokens,
        AVG(avg_response_time_ms) as avgResponseTime
      FROM analytics
      WHERE date >= date('now', '-' || ? || ' days')
      GROUP BY date
      ORDER BY date DESC
    `);
        return stmt.all(days);
    }
    /**
     * Get total cost for period
     */
    getTotalCost(filter = {}) {
        let sql = 'SELECT COALESCE(SUM(cost), 0) as total FROM analytics WHERE 1=1';
        const params = [];
        if (filter.startDate) {
            sql += ' AND date >= ?';
            params.push(filter.startDate);
        }
        if (filter.endDate) {
            sql += ' AND date <= ?';
            params.push(filter.endDate);
        }
        if (filter.projectId) {
            sql += ' AND project_id = ?';
            params.push(filter.projectId);
        }
        const stmt = this.db.prepare(sql);
        const result = stmt.get(...params);
        return result.total;
    }
    // ============================================================================
    // Tool Statistics Methods
    // ============================================================================
    /**
     * Record tool usage
     */
    recordToolUsage(toolName, success, timeMs, cacheHit, projectId) {
        const stmt = this.db.prepare(`
      INSERT INTO tool_stats (tool_name, project_id, success_count, failure_count, total_time_ms, cache_hits, cache_misses)
      VALUES (?, ?, ?, ?, ?, ?, ?)
      ON CONFLICT(tool_name, project_id) DO UPDATE SET
        success_count = tool_stats.success_count + excluded.success_count,
        failure_count = tool_stats.failure_count + excluded.failure_count,
        total_time_ms = tool_stats.total_time_ms + excluded.total_time_ms,
        cache_hits = tool_stats.cache_hits + excluded.cache_hits,
        cache_misses = tool_stats.cache_misses + excluded.cache_misses,
        last_used = CURRENT_TIMESTAMP,
        updated_at = CURRENT_TIMESTAMP
    `);
        stmt.run(toolName, projectId || null, success ? 1 : 0, success ? 0 : 1, timeMs, cacheHit ? 1 : 0, cacheHit ? 0 : 1);
    }
    /**
     * Get tool statistics
     */
    getToolStats(projectId) {
        let sql = 'SELECT * FROM tool_stats';
        const params = [];
        if (projectId) {
            sql += ' WHERE project_id = ?';
            params.push(projectId);
        }
        sql += ' ORDER BY (success_count + failure_count) DESC';
        const stmt = this.db.prepare(sql);
        return stmt.all(...params);
    }
    /**
     * Get top tools by usage
     */
    getTopTools(limit = 10) {
        const stmt = this.db.prepare(`
      SELECT
        tool_name,
        SUM(success_count + failure_count) as usage,
        SUM(success_count) * 1.0 / SUM(success_count + failure_count) as success_rate,
        SUM(total_time_ms) * 1.0 / SUM(success_count + failure_count) as avg_time_ms
      FROM tool_stats
      GROUP BY tool_name
      ORDER BY usage DESC
      LIMIT ?
    `);
        return stmt.all(limit);
    }
    // ============================================================================
    // Repair Learning Methods
    // ============================================================================
    /**
     * Record repair attempt
     */
    recordRepairAttempt(errorPattern, errorType, strategy, success, attempts, options = {}) {
        // First, try to get existing record
        const existing = this.db.prepare(`
      SELECT id, examples FROM repair_learning
      WHERE error_pattern = ? AND strategy = ? AND (context_hash = ? OR context_hash IS NULL)
    `).get(errorPattern, strategy, options.contextHash || null);
        if (existing) {
            // Update existing record
            const stmt = this.db.prepare(`
        UPDATE repair_learning SET
          success_count = success_count + ?,
          failure_count = failure_count + ?,
          avg_attempts = (avg_attempts * (success_count + failure_count) + ?) / (success_count + failure_count + 1),
          last_used = CURRENT_TIMESTAMP,
          examples = ?
        WHERE id = ?
      `);
            let examples = existing.examples ? JSON.parse(existing.examples) : [];
            if (success && options.example) {
                examples = [...examples.slice(-4), options.example]; // Keep last 5 examples
            }
            stmt.run(success ? 1 : 0, success ? 0 : 1, attempts, JSON.stringify(examples), existing.id);
        }
        else {
            // Insert new record
            const stmt = this.db.prepare(`
        INSERT INTO repair_learning (error_pattern, error_type, strategy, context_hash, language, framework, success_count, failure_count, avg_attempts, examples)
        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
      `);
            const examples = success && options.example ? [options.example] : [];
            stmt.run(errorPattern, errorType, strategy, options.contextHash || null, options.language || null, options.framework || null, success ? 1 : 0, success ? 0 : 1, attempts, JSON.stringify(examples));
        }
    }
    /**
     * Get best repair strategies for error pattern
     */
    getBestStrategies(errorPattern, filter = {}, limit = 5) {
        let sql = `
      SELECT * FROM repair_learning
      WHERE error_pattern LIKE ?
    `;
        const params = [`%${errorPattern}%`];
        if (filter.errorType) {
            sql += ' AND error_type = ?';
            params.push(filter.errorType);
        }
        if (filter.language) {
            sql += ' AND language = ?';
            params.push(filter.language);
        }
        if (filter.framework) {
            sql += ' AND framework = ?';
            params.push(filter.framework);
        }
        if (filter.minSuccessRate !== undefined) {
            sql += ' AND success_rate >= ?';
            params.push(filter.minSuccessRate);
        }
        sql += ' ORDER BY success_rate DESC, success_count DESC LIMIT ?';
        params.push(limit);
        const stmt = this.db.prepare(sql);
        const results = stmt.all(...params);
        return results.map(r => ({
            ...r,
            examples: r.examples ? JSON.parse(r.examples) : undefined,
        }));
    }
    /**
     * Get repair learning statistics
     */
    getRepairStats() {
        const totalPatterns = this.db.prepare('SELECT COUNT(DISTINCT error_pattern) as count FROM repair_learning').get().count;
        const avgSuccessRate = this.db.prepare('SELECT AVG(success_rate) as avg FROM repair_learning').get().avg || 0;
        const byTypeRows = this.db.prepare(`
      SELECT error_type, COUNT(*) as count, AVG(success_rate) as avgSuccessRate
      FROM repair_learning
      GROUP BY error_type
    `).all();
        const byErrorType = {};
        for (const row of byTypeRows) {
            byErrorType[row.error_type] = { count: row.count, avgSuccessRate: row.avgSuccessRate };
        }
        return { totalPatterns, avgSuccessRate, byErrorType };
    }
    // ============================================================================
    // Cleanup Methods
    // ============================================================================
    /**
     * Delete old analytics data
     */
    deleteOldAnalytics(daysToKeep = 90) {
        const stmt = this.db.prepare(`
      DELETE FROM analytics WHERE date < date('now', '-' || ? || ' days')
    `);
        const result = stmt.run(daysToKeep);
        return result.changes;
    }
    /**
     * Reset all statistics
     */
    resetStats() {
        this.db.exec('DELETE FROM analytics');
        this.db.exec('DELETE FROM tool_stats');
    }
}
// ============================================================================
// Singleton Instance
// ============================================================================
let instance = null;
export function getAnalyticsRepository() {
    if (!instance) {
        instance = new AnalyticsRepository();
    }
    return instance;
}
export function resetAnalyticsRepository() {
    instance = null;
}
//# sourceMappingURL=analytics-repository.js.map