import { ConfigManager } from "../../../core/config/config-manager.js";
import { TraceDetector } from "../../../core/trace/trace-detector.js";
import { logger } from "../../../core/monitoring/logger.js";
import { v4 as uuidv4 } from "uuid";
class ToolScoringMiddleware {
  configManager;
  traceDetector;
  metrics = [];
  profileStats = /* @__PURE__ */ new Map();
  db;
  constructor(configManager, traceDetector, db) {
    this.configManager = configManager || new ConfigManager();
    this.traceDetector = traceDetector || new TraceDetector();
    this.db = db;
    this.initializeDatabase();
    this.loadMetrics();
  }
  /**
   * Initialize database tables for metrics
   */
  initializeDatabase() {
    if (!this.db) return;
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS tool_scoring_metrics (
        id TEXT PRIMARY KEY,
        profile_name TEXT NOT NULL,
        tool_name TEXT NOT NULL,
        score REAL NOT NULL,
        files_affected INTEGER DEFAULT 0,
        is_permanent BOOLEAN DEFAULT FALSE,
        reference_count INTEGER DEFAULT 0,
        timestamp INTEGER NOT NULL,
        created_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `);
    this.db.exec(`
      CREATE TABLE IF NOT EXISTS profile_usage_stats (
        profile_name TEXT PRIMARY KEY,
        usage_count INTEGER DEFAULT 0,
        total_score REAL DEFAULT 0,
        avg_score REAL DEFAULT 0,
        high_score_tools TEXT,
        last_used INTEGER,
        updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
      )
    `);
    this.db.exec(`
      CREATE INDEX IF NOT EXISTS idx_metrics_profile ON tool_scoring_metrics(profile_name);
      CREATE INDEX IF NOT EXISTS idx_metrics_tool ON tool_scoring_metrics(tool_name);
      CREATE INDEX IF NOT EXISTS idx_metrics_timestamp ON tool_scoring_metrics(timestamp);
    `);
  }
  /**
   * Load existing metrics from database
   */
  loadMetrics() {
    if (!this.db) return;
    try {
      const cutoff = Date.now() - 7 * 24 * 60 * 60 * 1e3;
      const stmt = this.db.prepare(`
        SELECT * FROM tool_scoring_metrics 
        WHERE timestamp > ? 
        ORDER BY timestamp DESC
      `);
      const rows = stmt.all(cutoff);
      this.metrics = rows.map((row) => ({
        profileName: row.profile_name,
        toolName: row.tool_name,
        score: row.score,
        factors: {
          filesAffected: row.files_affected,
          isPermanent: row.is_permanent === 1,
          referenceCount: row.reference_count
        },
        timestamp: row.timestamp
      }));
      const statsStmt = this.db.prepare(`
        SELECT * FROM profile_usage_stats
      `);
      const statsRows = statsStmt.all();
      statsRows.forEach((row) => {
        this.profileStats.set(row.profile_name, {
          profileName: row.profile_name,
          usageCount: row.usage_count,
          totalScore: row.total_score,
          avgScore: row.avg_score,
          highScoreTools: row.high_score_tools ? JSON.parse(row.high_score_tools) : [],
          lastUsed: row.last_used
        });
      });
      logger.info("Loaded tool scoring metrics", {
        metricsCount: this.metrics.length,
        profilesCount: this.profileStats.size
      });
    } catch (error) {
      logger.error("Failed to load metrics", error);
    }
  }
  /**
   * Score a tool call and track it
   */
  async scoreToolCall(toolName, args, result, error) {
    const factors = this.extractScoringFactors(toolName, args, result);
    const score = this.configManager.calculateScore(toolName, factors);
    const config = this.configManager.getConfig();
    const profileName = config.profile || "default";
    const metric = {
      profileName,
      toolName,
      score,
      factors,
      timestamp: Date.now()
    };
    this.metrics.push(metric);
    this.updateProfileStats(profileName, toolName, score);
    this.saveMetric(metric);
    if (score > 0.3) {
      const toolCall = {
        id: uuidv4(),
        tool: toolName,
        arguments: args,
        timestamp: Date.now(),
        result,
        error,
        filesAffected: factors.filesAffected > 0 ? this.getFilesFromArgs(args) : void 0
      };
      this.traceDetector.addToolCall(toolCall);
    }
    if (score > 0.8) {
      logger.warn("High-importance tool call", {
        tool: toolName,
        score,
        profile: profileName,
        factors
      });
    }
    return score;
  }
  /**
   * Extract scoring factors from tool arguments and results
   */
  extractScoringFactors(toolName, args, result) {
    let filesAffected = 0;
    let isPermanent = false;
    let referenceCount = 0;
    if (args.file || args.files || args.path || args.paths) {
      filesAffected = 1;
      if (args.files || args.paths) {
        filesAffected = Array.isArray(args.files || args.paths) ? (args.files || args.paths).length : 1;
      }
    }
    const permanentTools = [
      "write",
      "edit",
      "create",
      "delete",
      "update",
      "add_decision",
      "create_task",
      "linear_update_task"
    ];
    if (permanentTools.some((t) => toolName.includes(t))) {
      isPermanent = true;
    }
    if (result?.referenceCount !== void 0) {
      referenceCount = result.referenceCount;
    } else if (result?.references?.length) {
      referenceCount = result.references.length;
    }
    return { filesAffected, isPermanent, referenceCount };
  }
  /**
   * Get file paths from arguments
   */
  getFilesFromArgs(args) {
    const files = [];
    if (args.file) files.push(args.file);
    if (args.path) files.push(args.path);
    if (args.files && Array.isArray(args.files)) files.push(...args.files);
    if (args.paths && Array.isArray(args.paths)) files.push(...args.paths);
    return files;
  }
  /**
   * Update profile usage statistics
   */
  updateProfileStats(profileName, toolName, score) {
    let stats = this.profileStats.get(profileName);
    if (!stats) {
      stats = {
        profileName,
        usageCount: 0,
        totalScore: 0,
        avgScore: 0,
        highScoreTools: [],
        lastUsed: Date.now()
      };
      this.profileStats.set(profileName, stats);
    }
    stats.usageCount++;
    stats.totalScore += score;
    stats.avgScore = stats.totalScore / stats.usageCount;
    stats.lastUsed = Date.now();
    if (score > 0.7 && !stats.highScoreTools.includes(toolName)) {
      stats.highScoreTools.push(toolName);
      if (stats.highScoreTools.length > 10) {
        stats.highScoreTools.shift();
      }
    }
    this.saveProfileStats(stats);
  }
  /**
   * Save metric to database
   */
  saveMetric(metric) {
    if (!this.db) return;
    try {
      const stmt = this.db.prepare(`
        INSERT INTO tool_scoring_metrics (
          id, profile_name, tool_name, score,
          files_affected, is_permanent, reference_count,
          timestamp
        ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
      `);
      stmt.run(
        uuidv4(),
        metric.profileName,
        metric.toolName,
        metric.score,
        metric.factors.filesAffected,
        metric.factors.isPermanent ? 1 : 0,
        metric.factors.referenceCount,
        metric.timestamp
      );
    } catch (error) {
      logger.error("Failed to save metric", error);
    }
  }
  /**
   * Save profile stats to database
   */
  saveProfileStats(stats) {
    if (!this.db) return;
    try {
      const stmt = this.db.prepare(`
        INSERT OR REPLACE INTO profile_usage_stats (
          profile_name, usage_count, total_score, avg_score,
          high_score_tools, last_used
        ) VALUES (?, ?, ?, ?, ?, ?)
      `);
      stmt.run(
        stats.profileName,
        stats.usageCount,
        stats.totalScore,
        stats.avgScore,
        JSON.stringify(stats.highScoreTools),
        stats.lastUsed
      );
    } catch (error) {
      logger.error("Failed to save profile stats", error);
    }
  }
  /**
   * Get profile effectiveness report
   */
  getProfileReport(profileName) {
    if (profileName) {
      const stats = this.profileStats.get(profileName);
      if (!stats) {
        return { error: `Profile '${profileName}' not found or not used yet` };
      }
      return {
        profile: profileName,
        usage: stats.usageCount,
        avgScore: stats.avgScore.toFixed(3),
        highScoreTools: stats.highScoreTools,
        lastUsed: new Date(stats.lastUsed).toISOString()
      };
    }
    const profiles = Array.from(this.profileStats.values()).sort((a, b) => b.avgScore - a.avgScore);
    return {
      profileCount: profiles.length,
      mostEffective: profiles[0]?.profileName || "none",
      profiles: profiles.map((p) => ({
        name: p.profileName,
        usage: p.usageCount,
        avgScore: p.avgScore.toFixed(3)
      }))
    };
  }
  /**
   * Get tool scoring trends
   */
  getToolTrends(toolName, hours = 24) {
    const cutoff = Date.now() - hours * 60 * 60 * 1e3;
    const relevantMetrics = this.metrics.filter(
      (m) => m.toolName === toolName && m.timestamp > cutoff
    );
    if (relevantMetrics.length === 0) {
      return { tool: toolName, message: "No recent data" };
    }
    const scores = relevantMetrics.map((m) => m.score);
    const avgScore = scores.reduce((a, b) => a + b, 0) / scores.length;
    const maxScore = Math.max(...scores);
    const minScore = Math.min(...scores);
    return {
      tool: toolName,
      period: `${hours}h`,
      count: relevantMetrics.length,
      avgScore: avgScore.toFixed(3),
      maxScore: maxScore.toFixed(3),
      minScore: minScore.toFixed(3),
      trend: this.calculateTrend(relevantMetrics)
    };
  }
  /**
   * Calculate score trend
   */
  calculateTrend(metrics) {
    if (metrics.length < 2) return "stable";
    const firstHalf = metrics.slice(0, Math.floor(metrics.length / 2));
    const secondHalf = metrics.slice(Math.floor(metrics.length / 2));
    const firstAvg = firstHalf.reduce((a, m) => a + m.score, 0) / firstHalf.length;
    const secondAvg = secondHalf.reduce((a, m) => a + m.score, 0) / secondHalf.length;
    const diff = secondAvg - firstAvg;
    if (diff > 0.1) return "increasing";
    if (diff < -0.1) return "decreasing";
    return "stable";
  }
  /**
   * Clean old metrics
   */
  cleanOldMetrics(daysToKeep = 30) {
    const cutoff = Date.now() - daysToKeep * 24 * 60 * 60 * 1e3;
    const oldCount = this.metrics.length;
    this.metrics = this.metrics.filter((m) => m.timestamp > cutoff);
    if (this.db) {
      try {
        const stmt = this.db.prepare(`
          DELETE FROM tool_scoring_metrics WHERE timestamp < ?
        `);
        stmt.run(cutoff);
      } catch (error) {
        logger.error("Failed to clean old metrics", error);
      }
    }
    return oldCount - this.metrics.length;
  }
}
export {
  ToolScoringMiddleware
};
//# sourceMappingURL=tool-scoring.js.map
