import {
  DEFAULT_RETRIEVAL_CONFIG
} from "./types.js";
import { logger } from "../monitoring/logger.js";
class CompressedSummaryGenerator {
  db;
  frameManager;
  traceDetector;
  projectId;
  config;
  cache = /* @__PURE__ */ new Map();
  constructor(db, frameManager, projectId, config = {}, traceDetector) {
    this.db = db;
    this.frameManager = frameManager;
    this.projectId = projectId;
    this.config = { ...DEFAULT_RETRIEVAL_CONFIG, ...config };
    this.traceDetector = traceDetector;
  }
  /**
   * Generate a compressed summary for LLM analysis
   */
  generateSummary(options = {}) {
    const cacheKey = `summary_${this.projectId}_${options.maxFrames || this.config.maxSummaryFrames}`;
    if (!options.forceRefresh) {
      const cached = this.cache.get(cacheKey);
      if (cached && cached.expiresAt > Date.now()) {
        logger.debug("Using cached summary", { projectId: this.projectId });
        return cached.summary;
      }
    }
    const startTime = Date.now();
    const maxFrames = options.maxFrames || this.config.maxSummaryFrames;
    const timeRangeHours = options.timeRangeHours || 24;
    const recentSession = this.generateRecentSessionSummary(
      maxFrames,
      timeRangeHours
    );
    const historicalPatterns = this.generateHistoricalPatterns();
    const queryableIndices = this.generateQueryableIndices();
    const stats = this.generateStats();
    const summary = {
      projectId: this.projectId,
      generatedAt: Date.now(),
      recentSession,
      historicalPatterns,
      queryableIndices,
      stats
    };
    this.cache.set(cacheKey, {
      summary,
      expiresAt: Date.now() + this.config.cacheTtlSeconds * 1e3
    });
    logger.info("Generated compressed summary", {
      projectId: this.projectId,
      frames: recentSession.frames.length,
      generationTimeMs: Date.now() - startTime
    });
    return summary;
  }
  /**
   * Generate recent session summary
   */
  generateRecentSessionSummary(maxFrames, timeRangeHours) {
    const cutoffTime = Math.floor(Date.now() / 1e3) - timeRangeHours * 3600;
    const frames = this.getRecentFrames(maxFrames, cutoffTime);
    const frameSummaries = frames.map((f) => this.summarizeFrame(f));
    const dominantOperations = this.getDominantOperations(cutoffTime);
    const filesTouched = this.getFilesTouched(cutoffTime);
    const errorsEncountered = this.getErrorsEncountered(cutoffTime);
    const timestamps = frames.map((f) => f.created_at).filter((t) => t);
    const start = timestamps.length > 0 ? Math.min(...timestamps) : cutoffTime;
    const end = timestamps.length > 0 ? Math.max(...timestamps) : Math.floor(Date.now() / 1e3);
    return {
      frames: frameSummaries,
      dominantOperations,
      filesTouched,
      errorsEncountered,
      timeRange: {
        start: start * 1e3,
        end: end * 1e3,
        durationMs: (end - start) * 1e3
      }
    };
  }
  /**
   * Generate historical patterns
   */
  generateHistoricalPatterns() {
    return {
      topicFrameCounts: this.getTopicFrameCounts(),
      keyDecisions: this.getKeyDecisions(),
      recurringIssues: this.getRecurringIssues(),
      commonToolSequences: this.getCommonToolSequences(),
      activityPatterns: this.getActivityPatterns()
    };
  }
  /**
   * Generate queryable indices
   */
  generateQueryableIndices() {
    return {
      byErrorType: this.indexByErrorType(),
      byTimeframe: this.indexByTimeframe(),
      byContributor: this.indexByContributor(),
      byTopic: this.indexByTopic(),
      byFile: this.indexByFile()
    };
  }
  /**
   * Generate summary statistics
   */
  generateStats() {
    try {
      const frameStats = this.db.prepare(
        `
        SELECT 
          COUNT(*) as totalFrames,
          MIN(created_at) as oldestFrame,
          MAX(created_at) as newestFrame,
          AVG(depth) as avgDepth
        FROM frames
        WHERE project_id = ?
      `
      ).get(this.projectId) || {};
      const eventCount = this.db.prepare(
        `
        SELECT COUNT(*) as count FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ?
      `
      ).get(this.projectId) || { count: 0 };
      const anchorCount = this.db.prepare(
        `
        SELECT COUNT(*) as count FROM anchors a
        JOIN frames f ON a.frame_id = f.frame_id
        WHERE f.project_id = ?
      `
      ).get(this.projectId) || { count: 0 };
      const decisionCount = this.db.prepare(
        `
        SELECT COUNT(*) as count FROM anchors a
        JOIN frames f ON a.frame_id = f.frame_id
        WHERE f.project_id = ? AND a.type = 'DECISION'
      `
      ).get(this.projectId) || { count: 0 };
      const totalFrames = frameStats.totalFrames || 0;
      return {
        totalFrames,
        totalEvents: eventCount.count || 0,
        totalAnchors: anchorCount.count || 0,
        totalDecisions: decisionCount.count || 0,
        oldestFrame: (frameStats.oldestFrame || 0) * 1e3,
        newestFrame: (frameStats.newestFrame || 0) * 1e3,
        avgFrameDepth: frameStats.avgDepth || 0,
        avgEventsPerFrame: totalFrames > 0 ? (eventCount.count || 0) / totalFrames : 0
      };
    } catch (error) {
      logger.warn("Error generating stats, using defaults", { error });
      return {
        totalFrames: 0,
        totalEvents: 0,
        totalAnchors: 0,
        totalDecisions: 0,
        oldestFrame: 0,
        newestFrame: 0,
        avgFrameDepth: 0,
        avgEventsPerFrame: 0
      };
    }
  }
  // Helper methods for recent session
  getRecentFrames(limit, cutoffTime) {
    try {
      const rows = this.db.prepare(
        `
        SELECT * FROM frames
        WHERE project_id = ? AND created_at >= ?
        ORDER BY created_at DESC
        LIMIT ?
      `
      ).all(this.projectId, cutoffTime, limit);
      return rows.map((row) => ({
        ...row,
        inputs: JSON.parse(row.inputs || "{}"),
        outputs: JSON.parse(row.outputs || "{}"),
        digest_json: JSON.parse(row.digest_json || "{}")
      }));
    } catch {
      return [];
    }
  }
  summarizeFrame(frame) {
    const eventCount = this.db.prepare(
      `
      SELECT COUNT(*) as count FROM events WHERE frame_id = ?
    `
    ).get(frame.frame_id) || { count: 0 };
    const anchorCount = this.db.prepare(
      `
      SELECT COUNT(*) as count FROM anchors WHERE frame_id = ?
    `
    ).get(frame.frame_id) || { count: 0 };
    const score = this.calculateFrameScore(
      frame,
      eventCount.count,
      anchorCount.count
    );
    return {
      frameId: frame.frame_id,
      name: frame.name,
      type: frame.type,
      depth: frame.depth,
      eventCount: eventCount.count,
      anchorCount: anchorCount.count,
      score,
      createdAt: frame.created_at * 1e3,
      closedAt: frame.closed_at ? frame.closed_at * 1e3 : void 0,
      digestPreview: frame.digest_text?.substring(0, 100)
    };
  }
  calculateFrameScore(frame, eventCount, anchorCount) {
    let score = 0.3;
    score += Math.min(eventCount / 50, 0.3);
    score += Math.min(anchorCount / 10, 0.2);
    const ageHours = (Date.now() / 1e3 - frame.created_at) / 3600;
    if (ageHours < 1) score += 0.2;
    else if (ageHours < 6) score += 0.1;
    if (frame.state === "active") score += 0.1;
    return Math.min(score, 1);
  }
  getDominantOperations(cutoffTime) {
    try {
      const rows = this.db.prepare(
        `
        SELECT 
          e.event_type as operation,
          COUNT(*) as count,
          MAX(e.ts) as lastOccurrence,
          SUM(CASE WHEN json_extract(e.payload, '$.success') = 1 THEN 1 ELSE 0 END) as successCount
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? AND e.ts >= ?
        GROUP BY e.event_type
        ORDER BY count DESC
        LIMIT 10
      `
      ).all(this.projectId, cutoffTime);
      return rows.map((row) => ({
        operation: row.operation,
        count: row.count,
        lastOccurrence: row.lastOccurrence * 1e3,
        successRate: row.count > 0 ? row.successCount / row.count : 0
      }));
    } catch {
      return [];
    }
  }
  getFilesTouched(cutoffTime) {
    try {
      const rows = this.db.prepare(
        `
        SELECT 
          json_extract(e.payload, '$.file_path') as path,
          e.event_type as operation,
          MAX(e.ts) as lastModified
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? 
          AND e.ts >= ?
          AND json_extract(e.payload, '$.file_path') IS NOT NULL
        GROUP BY json_extract(e.payload, '$.file_path'), e.event_type
      `
      ).all(this.projectId, cutoffTime);
      const fileMap = /* @__PURE__ */ new Map();
      for (const row of rows) {
        if (!row.path) continue;
        const existing = fileMap.get(row.path);
        if (existing) {
          existing.operationCount++;
          existing.operations.push(row.operation);
          existing.lastModified = Math.max(
            existing.lastModified,
            row.lastModified * 1e3
          );
        } else {
          fileMap.set(row.path, {
            path: row.path,
            operationCount: 1,
            lastModified: row.lastModified * 1e3,
            operations: [row.operation]
          });
        }
      }
      return Array.from(fileMap.values()).sort((a, b) => b.operationCount - a.operationCount).slice(0, 20);
    } catch {
      return [];
    }
  }
  getErrorsEncountered(cutoffTime) {
    try {
      const rows = this.db.prepare(
        `
        SELECT 
          json_extract(e.payload, '$.error_type') as errorType,
          json_extract(e.payload, '$.error') as message,
          COUNT(*) as count,
          MAX(e.ts) as lastOccurrence
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? 
          AND e.ts >= ?
          AND (json_extract(e.payload, '$.error') IS NOT NULL 
               OR json_extract(e.payload, '$.error_type') IS NOT NULL)
        GROUP BY json_extract(e.payload, '$.error_type'), json_extract(e.payload, '$.error')
        ORDER BY count DESC
        LIMIT 15
      `
      ).all(this.projectId, cutoffTime);
      return rows.map((row) => ({
        errorType: row.errorType || "unknown",
        message: row.message || "",
        count: row.count,
        lastOccurrence: row.lastOccurrence * 1e3,
        resolved: false
        // Would need more context to determine
      }));
    } catch {
      return [];
    }
  }
  // Helper methods for historical patterns
  getTopicFrameCounts() {
    try {
      const rows = this.db.prepare(
        `
        SELECT type, COUNT(*) as count
        FROM frames
        WHERE project_id = ?
        GROUP BY type
      `
      ).all(this.projectId);
      const counts = {};
      for (const row of rows) {
        counts[row.type] = row.count;
      }
      return counts;
    } catch {
      return {};
    }
  }
  getKeyDecisions() {
    try {
      const rows = this.db.prepare(
        `
        SELECT 
          a.anchor_id as id,
          a.text,
          a.frame_id as frameId,
          a.created_at as timestamp,
          a.priority
        FROM anchors a
        JOIN frames f ON a.frame_id = f.frame_id
        WHERE f.project_id = ? AND a.type = 'DECISION'
        ORDER BY a.priority DESC, a.created_at DESC
        LIMIT 20
      `
      ).all(this.projectId);
      return rows.map((row) => ({
        id: row.id,
        text: row.text,
        frameId: row.frameId,
        timestamp: row.timestamp * 1e3,
        impact: row.priority >= 7 ? "high" : row.priority >= 4 ? "medium" : "low"
      }));
    } catch {
      return [];
    }
  }
  getRecurringIssues() {
    try {
      const rows = this.db.prepare(
        `
        SELECT 
          json_extract(e.payload, '$.error_type') as issueType,
          COUNT(*) as occurrenceCount,
          MAX(e.ts) as lastSeen
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? 
          AND json_extract(e.payload, '$.error_type') IS NOT NULL
        GROUP BY json_extract(e.payload, '$.error_type')
        HAVING COUNT(*) > 1
        ORDER BY occurrenceCount DESC
        LIMIT 10
      `
      ).all(this.projectId);
      return rows.map((row) => ({
        issueType: row.issueType,
        occurrenceCount: row.occurrenceCount,
        lastSeen: row.lastSeen * 1e3,
        resolutionRate: 0.5
        // Would need resolution tracking
      }));
    } catch {
      return [];
    }
  }
  getCommonToolSequences() {
    if (this.traceDetector) {
      const stats = this.traceDetector.getStatistics();
      const sequences = [];
      for (const [type, count] of Object.entries(stats.tracesByType)) {
        sequences.push({
          pattern: type,
          frequency: count,
          avgDuration: 0,
          // Would need more data
          successRate: 0.8
          // Estimate
        });
      }
      return sequences;
    }
    return [];
  }
  getActivityPatterns() {
    try {
      const hourlyRows = this.db.prepare(
        `
        SELECT 
          strftime('%H', datetime(e.ts, 'unixepoch')) as hour,
          COUNT(*) as count
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ?
        GROUP BY hour
        ORDER BY count DESC
      `
      ).all(this.projectId);
      const peakHours = hourlyRows.slice(0, 3).map((r) => `${r.hour}:00`);
      const totalEvents = hourlyRows.reduce((sum, r) => sum + r.count, 0);
      return [
        {
          periodType: "hourly",
          peakPeriods: peakHours,
          avgEventsPerPeriod: totalEvents / 24
        }
      ];
    } catch {
      return [];
    }
  }
  // Helper methods for queryable indices
  indexByErrorType() {
    try {
      const rows = this.db.prepare(
        `
        SELECT DISTINCT
          json_extract(e.payload, '$.error_type') as errorType,
          f.frame_id
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? 
          AND json_extract(e.payload, '$.error_type') IS NOT NULL
      `
      ).all(this.projectId);
      const index = {};
      for (const row of rows) {
        if (!row.errorType) continue;
        if (!index[row.errorType]) index[row.errorType] = [];
        if (!index[row.errorType].includes(row.frame_id)) {
          index[row.errorType].push(row.frame_id);
        }
      }
      return index;
    } catch {
      return {};
    }
  }
  indexByTimeframe() {
    try {
      const now = Math.floor(Date.now() / 1e3);
      const timeframes = {
        last_hour: now - 3600,
        last_day: now - 86400,
        last_week: now - 604800,
        last_month: now - 2592e3
      };
      const index = {};
      for (const [label, cutoff] of Object.entries(timeframes)) {
        const rows = this.db.prepare(
          `
          SELECT frame_id FROM frames
          WHERE project_id = ? AND created_at >= ?
        `
        ).all(this.projectId, cutoff);
        index[label] = rows.map((r) => r.frame_id);
      }
      return index;
    } catch {
      return {};
    }
  }
  indexByContributor() {
    return {};
  }
  indexByTopic() {
    try {
      const rows = this.db.prepare(
        `
        SELECT frame_id, type, name FROM frames
        WHERE project_id = ?
      `
      ).all(this.projectId);
      const index = {};
      for (const row of rows) {
        if (!index[row.type]) index[row.type] = [];
        index[row.type].push(row.frame_id);
        const keywords = this.extractKeywords(row.name);
        for (const keyword of keywords) {
          if (!index[keyword]) index[keyword] = [];
          if (!index[keyword].includes(row.frame_id)) {
            index[keyword].push(row.frame_id);
          }
        }
      }
      return index;
    } catch {
      return {};
    }
  }
  indexByFile() {
    try {
      const rows = this.db.prepare(
        `
        SELECT DISTINCT
          json_extract(e.payload, '$.file_path') as filePath,
          f.frame_id
        FROM events e
        JOIN frames f ON e.frame_id = f.frame_id
        WHERE f.project_id = ? 
          AND json_extract(e.payload, '$.file_path') IS NOT NULL
      `
      ).all(this.projectId);
      const index = {};
      for (const row of rows) {
        if (!row.filePath) continue;
        if (!index[row.filePath]) index[row.filePath] = [];
        if (!index[row.filePath].includes(row.frame_id)) {
          index[row.filePath].push(row.frame_id);
        }
      }
      return index;
    } catch {
      return {};
    }
  }
  extractKeywords(text) {
    const stopWords = /* @__PURE__ */ new Set([
      "the",
      "a",
      "an",
      "and",
      "or",
      "but",
      "in",
      "on",
      "at",
      "to",
      "for"
    ]);
    return text.toLowerCase().split(/\W+/).filter((word) => word.length > 2 && !stopWords.has(word));
  }
  /**
   * Clear the cache
   */
  clearCache() {
    this.cache.clear();
    logger.debug("Summary cache cleared", { projectId: this.projectId });
  }
}
export {
  CompressedSummaryGenerator
};
//# sourceMappingURL=summary-generator.js.map
