/**
 * 压缩官 — Compressor Agent
 * ============================================
 * 职责：
 *   1. 监听大桌子上的对话
 *   2. 自动压缩长对话 → HLDP 结构化摘要
 *   3. 存入小桌子记忆库
 *   4. 清理大桌子上的冗余内容
 */

const { EventEmitter } = require('events');
const crypto = require('crypto');

class Compressor extends EventEmitter {
  constructor(bigDesk, smallDesk, opts = {}) {
    super();
    this.bigDesk = bigDesk;
    this.smallDesk = smallDesk;
    this.compressionThreshold = opts.compressionThreshold || 5; // 超过5条触发压缩
    this.autoCompress = opts.autoCompress !== false;
    this.compressionHistory = [];

    if (this.autoCompress) {
      this.bigDesk.on('add', () => this._checkAndCompress());
    }
  }

  /**
   * 检查是否需要压缩
   */
  _checkAndCompress() {
    const chatItems = this.bigDesk.items.filter(i => i.type === 'chat');
    if (chatItems.length >= this.compressionThreshold) {
      this.compress(chatItems);
    }
  }

  /**
   * 执行压缩：对话 → HLDP 结构化摘要
   */
  compress(items) {
    const batchId = `cmp_${Date.now()}`;
    const startTime = Date.now();

    // 提取关键信息
    const topics = this._extractTopics(items);
    const decisions = this._extractDecisions(items);
    const actions = this._extractActions(items);
    const participants = this._extractParticipants(items);

    // 生成 HLDP 摘要
    const hldpSummary = this._generateHLDP({
      batchId,
      topics,
      decisions,
      actions,
      participants,
      itemCount: items.length,
      timeRange: {
        start: items[0]?.timestamp,
        end: items[items.length - 1]?.timestamp
      }
    });

    // 计算原文哈希
    const sourceHash = crypto.createHash('sha256')
      .update(JSON.stringify(items))
      .digest('hex')
      .substring(0, 16);

    // 存入小桌子
    const memoryEntry = this.smallDesk.storeMemory(
      'compressed-dialogue',
      hldpSummary,
      `big-desk://compression/${batchId}`,
      {
        batchId,
        sourceHash,
        originalItemCount: items.length,
        compressedAt: new Date().toISOString(),
        compressionMs: Date.now() - startTime,
        topics,
        decisions,
        actions,
        participants
      }
    );

    // 从大桌子移除已压缩的条目
    const toRemove = items.map(i => i.id);
    this.bigDesk.items = this.bigDesk.items.filter(i => !toRemove.includes(i.id));
    this.bigDesk._saveState();

    // 在大桌子上留一条压缩记录
    this.bigDesk.add('chat',
      `📝 压缩: ${items.length}条对话 → HLDP摘要 [${batchId}] → 小桌子/memory/compressed-dialogue/`,
      { type: 'compression', batchId, compressedCount: items.length }
    );

    this.compressionHistory.push({
      batchId,
      compressedCount: items.length,
      hldpLength: hldpSummary.length,
      timestamp: new Date().toISOString()
    });

    this.emit('compressed', {
      batchId,
      originalCount: items.length,
      hldpSummary,
      memoryEntry
    });

    return { batchId, hldpSummary, memoryEntry };
  }

  /**
   * 提取话题关键词
   */
  _extractTopics(items) {
    const allText = items.map(i => i.content).join(' ');
    // 简单关键词提取
    const keywords = ['HLDP', 'Agent', '守门人', '服务器', '部署', 'Notion',
      '大桌子', '小桌子', '数据库', '人格体', 'API', '模型', '密钥',
      '代码仓库', '压缩', '记忆', '光湖', '铸渊', '冰朔'];
    const topics = [];
    for (const kw of keywords) {
      if (allText.includes(kw)) topics.push(kw);
    }
    return topics.slice(0, 5);
  }

  /**
   * 提取决策/结论
   */
  _extractDecisions(items) {
    const decisions = [];
    for (const item of items) {
      const c = item.content;
      if (c.includes('决定') || c.includes('确认') || c.includes('方案') ||
          c.includes('架构') || c.includes('采用') || c.includes('选')) {
        decisions.push(c.substring(0, 80));
      }
    }
    return decisions.slice(0, 3);
  }

  /**
   * 提取执行动作
   */
  _extractActions(items) {
    const actions = [];
    for (const item of items) {
      if (item.type === 'tool' || item.type === 'agent' ||
          item.content.includes('执行') || item.content.includes('部署') ||
          item.content.includes('创建') || item.content.includes('修改')) {
        actions.push(item.content.substring(0, 80));
      }
    }
    return actions.slice(0, 5);
  }

  /**
   * 提取参与者
   */
  _extractParticipants(items) {
    const participants = new Set();
    for (const item of items) {
      if (item.meta?.speaker) participants.add(item.meta.speaker);
      if (item.meta?.persona) participants.add(item.meta.persona);
    }
    return [...participants];
  }

  /**
   * 生成 HLDP 格式摘要
   */
  _generateHLDP({ batchId, topics, decisions, actions, participants, itemCount, timeRange }) {
    const lines = [
      `@COMPRESSION:${batchId}`,
      `@DATE:${new Date().toISOString()}`,
      `@SOURCE:${itemCount}条对话 → HLDP结构化压缩`,
    ];

    if (participants.length > 0) {
      lines.push(`@PARTICIPANTS:${participants.join(',')}`);
    }

    if (topics.length > 0) {
      lines.push(`@TOPICS:${topics.join(' | ')}`);
    }

    if (decisions.length > 0) {
      lines.push(`@DECISIONS`);
      decisions.forEach((d, i) => lines.push(`  ⊢ [${i + 1}] ${d}`));
    }

    if (actions.length > 0) {
      lines.push(`@ACTIONS`);
      actions.forEach((a, i) => lines.push(`  ⊢ [${i + 1}] ${a}`));
    }

    lines.push(`@META:压缩率≈${Math.round((1 - lines.join('\n').length / (itemCount * 200)) * 100)}%`);

    return lines.join('\n');
  }

  /**
   * 获取压缩历史
   */
  getHistory() {
    return this.compressionHistory.slice(-20);
  }

  /**
   * 手动触发压缩
   */
  compressNow() {
    const chatItems = this.bigDesk.items.filter(i => i.type === 'chat');
    if (chatItems.length === 0) return null;
    return this.compress(chatItems);
  }
}

module.exports = Compressor;
