const fs = require('fs');
const path = require('path');
const crypto = require('crypto');

/**
 * HeartFlow MeaningfulMemory v2.1.0
 * 
 * 升级要点：
 * 1. 记忆巩固 – Ebbinghaus 遗忘曲线定时应用
 * 2. 检索优化 – 多通道搜索（关键字/语义/时序/图遍历）
 * 3. 关联发现 – 自动建立关系 + 图社区检测
 * 4. 意义评估 – 综合重要性、访问频率、图中心度
 *
 * 兼容 v1 接口：store/retrieve/delete/search 签名不变。
 */

// ─── 语义搜索（懒加载） ──────────────────────────────────────────────────────
let _semanticSearch = null;
function getSemanticSearch() {
  if (!_semanticSearch) {
    try {
      const { SemanticSearch } = require('./search/semantic-search.js');
      const { env } = require('@xenova/transformers');
      env.allowRemoteModels = false;
      _semanticSearch = new SemanticSearch({ model: 'Xenova/all-MiniLM-L6-v2' });
    } catch (e) {
      // 降级 – 不使用语义搜索
      _semanticSearch = null;
    }
  }
  return _semanticSearch;
}

const DATA_DIR = path.join(__dirname, '../../data');
const EXPORT_PATH = path.join(DATA_DIR, 'meaningful-memory.json');

class MeaningfulMemory {
  constructor(options = {}) {
    this.vectorDim = options.vectorDim || 384;
    this.layers = {
      core: [],
      learned: [],
      ephemeral: []
    };

    this.vectors = new Map();          // id -> embedding
    this.relationships = new Map();    // id -> Array<{targetId, type, strength}>
    this._currentTopic = null;
    this._dirty = false;

    this.stats = {
      totalMemories: 0,
      totalRelationships: 0,
      lastCleanup: null,
      lastSave: null,
      totalSearches: 0
    };

    // Ebbinghaus 遗忘曲线配置
    this.forgettingConfig = {
      defaultStability: 10,        // 小时
      highImportanceStability: 24,
      emotionalStability: 18,
      compressionThreshold: 0.3,   // retention < 0.3 → 压缩
      deletionThreshold: 0.1,      // retention < 0.1 → 删除
      consolidationInterval: 3600000  // 1小时（毫秒）
    };

    this._saveTimer = null;
    this._consolidationTimer = null;

    this._loadFromExport();
    this._ensureCoreMemories();
    this._startConsolidation();
  }

  // ─── 公开接口 ────────────────────────────────────────────────────────────

  /**
   * 由 TopicScope 调用
   */
  setCurrentTopic(topic) {
    this._currentTopic = topic || null;
  }

  getCurrentTopic() {
    return this._currentTopic;
  }

  /**
   * 存储一条新记忆
   * @param {object} memory - { content, layer, metadata, importance, id? }
   * @returns {string} 记忆 id
   */
  store(memory) {
    if (!memory || !memory.content) {
      throw new Error('[MeaningfulMemory] store 需要 content');
    }

    const id = memory.id || this._generateId();
    const layer = memory.layer || 'learned';
    if (!['core', 'learned', 'ephemeral'].includes(layer)) {
      throw new Error(`[MeaningfulMemory] 无效 layer: ${layer}`);
    }

    // 基础记录
    const now = Date.now();
    const record = {
      id,
      timestamp: now,
      layer,
      content: memory.content,
      summary: memory.summary || (memory.content.length > 120 ? memory.content.slice(0, 117) + '...' : memory.content),
      embedding: memory.embedding || this._generateEmbedding(memory.content),
      metadata: memory.metadata || {},
      importance: memory.importance || this._defaultImportance(memory),
      accessCount: 0,
      lastAccess: now,
      createdAt: now,
      updatedAt: now
    };

    // 检查重复（简单内容哈希匹配）
    const existing = this._findDuplicate(record);
    if (existing) {
      // 更新已有记录（增加重要性、更新时间）
      existing.updatedAt = now;
      existing.accessCount += 1;
      existing.importance = Math.min(20, existing.importance + 0.5);
      if (memory.summary) existing.summary = memory.summary;
      this._dirty = true;
      this._autoSave();
      return existing.id;
    }

    // 插入到对应层
    this.layers[layer].push(record);
    this.vectors.set(id, record.embedding);
    this.stats.totalMemories++;
    this._dirty = true;

    // 自动发现关系
    this._discoverRelations(record);

    // 触发保存
    this._autoSave();

    return id;
  }

  /**
   * 根据 id 检索记忆（包含关系列表）
   */
  retrieve(id) {
    for (const layer of Object.values(this.layers)) {
      for (const mem of layer) {
        if (mem.id === id) {
          mem.lastAccess = Date.now();
          mem.accessCount = (mem.accessCount || 0) + 1;
          return {
            ...mem,
            relatedTo: this.relationships.get(id) || []
          };
        }
      }
    }
    return null;
  }

  /**
   * 多通道搜索
   * options: {
   *   query: string,
   *   layers: string[],
   *   limit: number,
   *   threshold: number,
   *   channels: string[],   // 'keyword' | 'semantic' | 'temporal' | 'graph'
   *   timeRange?: { start, end },
   *   graphSeed?: string,   // 从该记忆出发图遍历
   *   topic?: string,
   * }
   * @returns {Array} 排序后的记忆列表（每项附带 score）
   */
  search(options = {}) {
    const {
      query = '',
      layers = ['core', 'learned', 'ephemeral'],
      limit = 10,
      threshold = 0.3,
      channels = ['keyword', 'semantic', 'temporal', 'graph'],
      timeRange = null,
      graphSeed = null,
      topic = null
    } = options;

    this.stats.totalSearches++;

    // 收集候选记忆
    let candidates = [];
    for (const lName of layers) {
      const layerMemories = this.layers[lName] || [];
      for (const mem of layerMemories) {
        candidates.push(mem);
      }
    }

    // 话题过滤
    if (topic) {
      candidates = candidates.filter(m => {
        const t = m.metadata && m.metadata.topic;
        return t === topic || t === undefined;
      });
    }

    if (candidates.length === 0) return [];

    // 各通道评分
    let scores = new Map();
    for (const mem of candidates) {
      scores.set(mem.id, 0);
    }

    const channelWeights = {
      keyword: 1.0,
      semantic: 1.5,
      temporal: 0.8,
      graph: 1.2
    };

    // 关键字通道
    if (channels.includes('keyword') && query) {
      const kwScores = this._keywordSearch(query, candidates);
      for (const [id, score] of kwScores) {
        scores.set(id, (scores.get(id) || 0) + score * channelWeights.keyword);
      }
    }

    // 语义通道
    if (channels.includes('semantic') && query) {
      const semScores = this._semanticSearch(query, candidates);
      for (const [id, score] of semScores) {
        scores.set(id, (scores.get(id) || 0) + score * channelWeights.semantic);
      }
    }

    // 时序通道
    if (channels.includes('temporal') && timeRange) {
      const tempScores = this._temporalSearch(timeRange, candidates);
      for (const [id, score] of tempScores) {
        scores.set(id, (scores.get(id) || 0) + score * channelWeights.temporal);
      }
    }

    // 图遍历通道
    if (channels.includes('graph') && graphSeed) {
      const graphScores = this._graphSearch(graphSeed, candidates, { depth: 2 });
      for (const [id, score] of graphScores) {
        scores.set(id, (scores.get(id) || 0) + score * channelWeights.graph);
      }
    }

    // 综合意义得分（作为 bias）
    for (const mem of candidates) {
      const base = scores.get(mem.id) || 0;
      const sig = this._significanceScore(mem);
      scores.set(mem.id, base + sig * 0.3);
    }

    // 排序
    const sorted = [...scores.entries()]
      .filter(([id, sc]) => sc >= threshold)
      .sort((a, b) => b[1] - a[1])
      .slice(0, limit);

    // 提取完整记忆
    const results = [];
    for (const [id, score] of sorted) {
      for (const layer of Object.values(this.layers)) {
        const found = layer.find(m => m.id === id);
        if (found) {
          results.push({
            ...found,
            score: Math.round(score * 100) / 100,
            relatedTo: this.relationships.get(id) || []
          });
          break;
        }
      }
    }

    return results;
  }

  /**
   * 删除一条记忆
   */
  delete(id) {
    for (const layerName of Object.keys(this.layers)) {
      const layer = this.layers[layerName];
      const idx = layer.findIndex(m => m.id === id);
      if (idx !== -1) {
        layer.splice(idx, 1);
        this.vectors.delete(id);
        this.relationships.delete(id);
        // 删除所有指向该 id 的关系
        for (const [key, rels] of this.relationships) {
          this.relationships.set(key, rels.filter(r => r.targetId !== id));
        }
        this.stats.totalMemories--;
        this._dirty = true;
        this._autoSave();
        return true;
      }
    }
    return false;
  }

  /**
   * 统计信息
   */
  getStats() {
    return { ...this.stats };
  }

  // ─── 内部：关键词搜索 ──────────────────────────────────────────────────

  _keywordSearch(query, candidates) {
    const scores = new Map();
    const qLower = query.toLowerCase();
    for (const mem of candidates) {
      let score = 0;
      const content = (mem.content || '').toLowerCase();
      const summary = (mem.summary || '').toLowerCase();
      if (content.includes(qLower)) {
        score += 0.8;
      }
      if (summary.includes(qLower)) {
        score += 0.6;
      }
      // 元数据匹配
      const metaStr = JSON.stringify(mem.metadata || {}).toLowerCase();
      if (metaStr.includes(qLower)) {
        score += 0.4;
      }
      if (score > 0) {
        scores.set(mem.id, Math.min(1, score));
      }
    }
    return scores;
  }

  // ─── 内部：语义搜索 ────────────────────────────────────────────────────

  _semanticSearch(query, candidates) {
    const searcher = getSemanticSearch();
    if (!searcher) {
      // 降级：使用简单的 TF-IDF 风格的词袋相似度
      return this._keywordSearch(query, candidates); // 暂时回退
    }

    const scores = new Map();
    try {
      const queryEmb = this._generateEmbedding(query);
      for (const mem of candidates) {
        const memEmb = mem.embedding || this._generateEmbedding(mem.content);
        const sim = this._cosineSimilarity(queryEmb, memEmb);
        if (sim > 0.3) {
          scores.set(mem.id, sim);
        }
      }
    } catch (e) {
      console.warn('[MeaningfulMemory] 语义搜索失败:', e.message);
    }
    return scores;
  }

  // ─── 内部：时序搜索 ────────────────────────────────────────────────────

  _temporalSearch(timeRange, candidates) {
    const { start, end } = timeRange;
    const scores = new Map();
    for (const mem of candidates) {
      const ts = mem.timestamp || mem.createdAt;
      if (ts >= start && ts <= end) {
        const norm = 1 - (ts - start) / (end - start || 1);
        scores.set(mem.id, 0.5 + 0.5 * norm);
      }
    }
    return scores;
  }

  // ─── 内部：图遍历搜索 ──────────────────────────────────────────────────

  _graphSearch(seedId, candidates, options = {}) {
    const maxDepth = options.depth || 2;
    const scores = new Map();
    const visited = new Set();
    const queue = [{ id: seedId, depth: 0, weight: 1 }];

    while (queue.length > 0) {
      const { id, depth, weight } = queue.shift();
      if (visited.has(id) || depth > maxDepth) continue;
      visited.add(id);

      // 给该记忆加分
      const existing = candidates.find(m => m.id === id);
      if (existing) {
        const baseScore = scores.get(id) || 0;
        scores.set(id, Math.max(baseScore, weight * (1 - depth / (maxDepth + 1))));
      }

      // 遍历邻居
      const rels = this.relationships.get(id) || [];
      for (const rel of rels) {
        if (!visited.has(rel.targetId)) {
          queue.push({
            id: rel.targetId,
            depth: depth + 1,
            weight: weight * (rel.strength || 0.5)
          });
        }
      }
    }

    return scores;
  }

  // ─── 意义评估 ────────────────────────────────────────────────────────────

  _significanceScore(mem) {
    let score = 0;

    // 1. 基础重要性（用户设定 1-20）
    const imp = mem.importance || 1;
    score += (imp / 20) * 0.4;

    // 2. 访问频率（归一化）
    const acc = mem.accessCount || 0;
    score += Math.min(1, acc / 50) * 0.2;

    // 3. 图中心度（简单度）
    const rels = this.relationships.get(mem.id);
    const degree = rels ? rels.length : 0;
    score += Math.min(1, degree / 10) * 0.15;

    // 4. 新近度（天数）
    const ageDays = (Date.now() - (mem.timestamp || mem.createdAt)) / 86400000;
    score += Math.max(0, 1 - ageDays / 30) * 0.15;

    // 5. 主题特异性（加分）
    if (mem.metadata && mem.metadata.topic) {
      score += 0.1;
    }

    return Math.min(1, Math.max(0, score));
  }

  // ─── 关系发现 ────────────────────────────────────────────────────────────

  _discoverRelations(newMemory) {
    const newId = newMemory.id;
    const newEmb = newMemory.embedding;
    const newTopic = newMemory.metadata && newMemory.metadata.topic;
    const newTime = newMemory.timestamp || newMemory.createdAt;
    const relationshipsAdded = 0;

    for (const layer of Object.values(this.layers)) {
      for (const existing of layer) {
        if (existing.id === newId) continue;

        // 计算关系强度
        let strength = 0;
        let type = 'related';

        // 基于主题
        const existingTopic = existing.metadata && existing.metadata.topic;
        if (newTopic && existingTopic && newTopic === existingTopic) {
          strength += 0.5;
          type = 'same_topic';
        }

        // 基于时间邻近（1小时内）
        const existingTime = existing.timestamp || existing.createdAt;
        if (Math.abs(newTime - existingTime) < 3600000) {
          strength += 0.3;
          type = 'temporal';
        }

        // 基于内容相似度
        if (newEmb && existing.embedding) {
          const sim = this._cosineSimilarity(newEmb, existing.embedding);
          if (sim > 0.5) {
            strength += sim * 0.6;
            type = 'semantic';
          }
        }

        if (strength > 0.3) {
          // 建立双向关系
          this._addRelationship(newId, existing.id, type, Math.min(1, strength));
          this._addRelationship(existing.id, newId, type, Math.min(1, strength));
          this.stats.totalRelationships++;
        }
      }
    }
  }

  _addRelationship(fromId, toId, type, strength) {
    if (!this.relationships.has(fromId)) {
      this.relationships.set(fromId, []);
    }
    const rels = this.relationships.get(fromId);
    // 去重
    const idx = rels.findIndex(r => r.targetId === toId && r.type === type);
    if (idx !== -1) {
      rels[idx].strength = Math.max(rels[idx].strength, strength);
    } else {
      rels.push({ targetId: toId, type, strength });
    }
  }

  // ─── Ebbinghaus 遗忘曲线 ──────────────────────────────────────────────────

  /**
   * 计算 retention 值
   */
  _retention(stabilityHours, ageHours) {
    return Math.exp(-ageHours / stabilityHours);
  }

  /**
   * 应用遗忘与巩固
   */
  _applyForgetting() {
    const now = Date.now();
    const CFG = this.forgettingConfig;
    let removed = 0;
    let compressed = 0;

    for (const layerName of ['learned', 'ephemeral']) {
      const layer = this.layers[layerName];
      const toKeep = [];

      for (const mem of layer) {
        const ageHours = (now - (mem.timestamp || mem.createdAt)) / 3600000;
        const stability = this._stabilityFor(mem);
        const r = this._retention(stability, ageHours);

        if (r < CFG.deletionThreshold) {
          // 删除
          this.vectors.delete(mem.id);
          this.relationships.delete(mem.id);
          removed++;
          this.stats.totalMemories--;
        } else if (r < CFG.compressionThreshold) {
          // 压缩：保留摘要，清除详细内容
          mem.content = mem.summary || '[压缩]' + (mem.content || '').slice(0, 50);
          compressed++;
          toKeep.push(mem);
        } else {
          toKeep.push(mem);
        }
      }

      this.layers[layerName] = toKeep;
    }

    this.stats.lastCleanup = new Date().toISOString();
    if (removed > 0 || compressed > 0) {
      console.warn(`[MeaningfulMemory] 遗忘: 删除 ${removed} 条, 压缩 ${compressed} 条`);
      this._dirty = true;
      this._autoSave();
    }
  }

  _stabilityFor(mem) {
    const CFG = this.forgettingConfig;
    if (mem.layer === 'core') return Number.POSITIVE_INFINITY;
    if (mem.importance >= 15) return CFG.highImportanceStability;
    // 情感因素暂不支持
    return CFG.defaultStability + (mem.importance || 0) * 0.5;
  }

  /**
   * 执行一次巩固周期
   */
  _consolidateNow() {
    // 1. 遗忘清理
    this._applyForgetting();

    // 2. 增强访问频繁的记忆
    const now = Date.now();
    for (const layerName of ['core', 'learned', 'ephemeral']) {
      for (const mem of this.layers[layerName]) {
        if (mem.accessCount > 20) {
          // 频繁访问 → 增加重要性
          mem.importance = Math.min(20, (mem.importance || 1) + 1);
          mem.accessCount = Math.floor(mem.accessCount / 2);
        }
      }
    }

    // 3. 重新发现关系（可选）
    this._rebuildAllRelationships();

    this._dirty = true;
    this._autoSave();
  }

  _startConsolidation() {
    if (this._consolidationTimer) clearInterval(this._consolidationTimer);
    const interval = this.forgettingConfig.consolidationInterval || 3600000;
    this._consolidationTimer = setInterval(() => {
      this._consolidateNow();
    }, interval);
    // 防止进程阻塞
    if (this._consolidationTimer.unref) {
      this._consolidationTimer.unref();
    }
  }

  /**
   * 重建所有关系（基于当前所有记忆）
   */
  _rebuildAllRelationships() {
    // 清空关系
    this.relationships.clear();
    this.stats.totalRelationships = 0;

    // 收集所有记忆
    const all = [];
    for (const layer of Object.values(this.layers)) {
      for (const mem of layer) {
        all.push(mem);
      }
    }

    // 两两比较（简单 O(n^2)，可优化）
    for (let i = 0; i < all.length; i++) {
      for (let j = i + 1; j < all.length; j++) {
        const a = all[i], b = all[j];
        let strength = 0;
        let type = 'related';

        // 主题
        const tA = a.metadata && a.metadata.topic;
        const tB = b.metadata && b.metadata.topic;
        if (tA && tB && tA === tB) {
          strength += 0.4;
          type = 'same_topic';
        }

        // 时间邻近（1小时）
        const timeA = a.timestamp || a.createdAt;
        const timeB = b.timestamp || b.createdAt;
        if (Math.abs(timeA - timeB) < 3600000) {
          strength += 0.3;
          type = 'temporal';
        }

        // 语义相似
        if (a.embedding && b.embedding) {
          const sim = this._cosineSimilarity(a.embedding, b.embedding);
          if (sim > 0.5) {
            strength += sim * 0.5;
            type = 'semantic';
          }
        }

        if (strength > 0.3) {
          this._addRelationship(a.id, b.id, type, Math.min(1, strength));
          this._addRelationship(b.id, a.id, type, Math.min(1, strength));
          this.stats.totalRelationships++;
        }
      }
    }
  }

  // ─── 工具 ──────────────────────────────────────────────────────────────────

  _generateId() {
    return 'mem_' + crypto.randomBytes(8).toString('hex') + '_' + Date.now();
  }

  _generateEmbedding(text) {
    // 使用 semanticSearch 如果可用，否则使用 mock
    const searcher = getSemanticSearch();
    if (searcher && typeof searcher.getEmbedding === 'function') {
      try {
        return searcher.getEmbedding(text);
      } catch (e) {
        // fallback
      }
    }
    // Mock：使用文本哈希作为伪嵌入（维度 vectorDim）
    const hash = crypto.createHash('sha256').update(text).digest();
    const arr = new Float64Array(this.vectorDim);
    for (let i = 0; i < this.vectorDim; i++) {
      arr[i] = (hash[i % 32] / 255) * 2 - 1;  // 归一化到 [-1,1]
    }
    return Array.from(arr);
  }

  _cosineSimilarity(vecA, vecB) {
    if (!vecA || !vecB || vecA.length !== vecB.length) return 0;
    let dot = 0, normA = 0, normB = 0;
    for (let i = 0; i < vecA.length; i++) {
      dot += vecA[i] * vecB[i];
      normA += vecA[i] * vecA[i];
      normB += vecB[i] * vecB[i];
    }
    const denom = Math.sqrt(normA) * Math.sqrt(normB);
    return denom === 0 ? 0 : Math.max(0, Math.min(1, dot / denom));
  }

  _defaultImportance(memory) {
    // 根据层和内容长度估算
    if (memory.layer === 'core') return 18;
    if (memory.layer === 'ephemeral') return 3;
    const len = (memory.content || '').length;
    if (len > 500) return 12;
    if (len > 200) return 8;
    return 5;
  }

  _findDuplicate(newRecord) {
    // 使用内容哈希快速查找
    const h = crypto.createHash('sha256').update(newRecord.content).digest('hex');
    for (const layer of Object.values(this.layers)) {
      for (const mem of layer) {
        if (mem.id === newRecord.id) return mem;
        const h2 = crypto.createHash('sha256').update(mem.content || '').digest('hex');
        if (h === h2) return mem;
      }
    }
    return null;
  }

  // ─── 持久化 ────────────────────────────────────────────────────────────────

  _getExportPath() {
    return EXPORT_PATH;
  }

  _loadFromExport() {
    const exportPath = this._getExportPath();
    if (!fs.existsSync(exportPath)) return;

    try {
      const raw = fs.readFileSync(exportPath, 'utf-8');
      const data = JSON.parse(raw);

      // 恢复记忆
      const self = this;
      function restoreLayer(memories, layerName) {
        for (const mem of (memories || [])) {
          // 兼容 v1 核心记忆（没有 content 只有 summary）
          if (!mem.content && mem.summary) {
            mem.content = mem.summary;
          }
          self.layers[layerName].push(mem);
          if (mem.embedding) self.vectors.set(mem.id, mem.embedding);
        }
      }

      restoreLayer(data.core, 'core');
      restoreLayer(data.learned, 'learned');
      restoreLayer(data.ephemeral, 'ephemeral');

      // 恢复关系
      if (data.relationships) {
        for (const [id, rels] of Object.entries(data.relationships)) {
          this.relationships.set(id, rels);
        }
        this.stats.totalRelationships = data.relationships.totalCount || 0;
      }

      // 恢复向量
      if (data.vectors) {
        for (const [id, vec] of Object.entries(data.vectors)) {
          if (!this.vectors.has(id)) {
            this.vectors.set(id, vec);
          }
        }
      }

      if (data.stats) {
        Object.assign(this.stats, data.stats);
      }

      console.log(`[MeaningfulMemory] 恢复 ${this.layers.core.length + this.layers.learned.length + this.layers.ephemeral.length} 条记忆`);
    } catch (e) {
      console.warn('[MeaningfulMemory] 恢复失败:', e.message);
    }
  }

  _autoSave() {
    if (this._saveTimer) clearTimeout(this._saveTimer);
    this._saveTimer = setTimeout(() => { this._doSave(); }, 2000);
  }

  _doSave() {
    // 数据最小化 + 用户同意检查
    const minimization = process.env.HEARTFLOW_DATA_MINIMIZATION;
    const userConsent = this._hasUserConsent();

    if (!userConsent) {
      console.warn('[MeaningfulMemory] 持久化被阻止: 需要用户同意');
      return;
    }

    const exportPath = this._getExportPath();
    try {
      const dir = require('path').dirname(exportPath);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }

      let dataToSave;

      if (minimization) {
        // 最小化模式 – 只存摘要和哈希
        dataToSave = {
          core: this.layers.core.map(m => this._minimizeMemory(m)),
          learned: this.layers.learned.map(m => this._minimizeMemory(m)),
          ephemeral: this.layers.ephemeral.map(m => this._minimizeMemory(m)),
          stats: this.stats,
          exportedAt: new Date().toISOString()
        };
        console.log(`[MeaningfulMemory] 已保存 (最小化) ${this.stats.totalMemories} 条记忆`);
      } else {
        // 完整模式 – 保存所有必要字段、向量和关系
        const relationshipsObj = {};
        for (const [id, rels] of this.relationships) {
          relationshipsObj[id] = rels;
        }
        relationshipsObj.totalCount = this.stats.totalRelationships;

        const vectorsObj = {};
        for (const [id, vec] of this.vectors) {
          vectorsObj[id] = vec;
        }

        dataToSave = {
          core: this.layers.core.map(m => this._fullMemory(m)),
          learned: this.layers.learned.map(m => this._fullMemory(m)),
          ephemeral: this.layers.ephemeral.map(m => this._fullMemory(m)),
          vectors: vectorsObj,
          relationships: relationshipsObj,
          stats: this.stats,
          exportedAt: new Date().toISOString(),
          version: '2.1'
        };
        console.log(`[MeaningfulMemory] 已保存 (完整) ${this.stats.totalMemories} 条记忆`);
      }

      fs.writeFileSync(exportPath, JSON.stringify(dataToSave, null, 2));
      this.stats.lastSave = new Date().toISOString();
      this._dirty = false;
    } catch (e) {
      console.warn('[MeaningfulMemory] 保存失败:', e.message);
    }
  }

  _fullMemory(mem) {
    return {
      id: mem.id,
      timestamp: mem.timestamp,
      layer: mem.layer,
      content: mem.content,
      summary: mem.summary,
      embedding: mem.embedding,
      importance: mem.importance,
      accessCount: mem.accessCount,
      lastAccess: mem.lastAccess,
      createdAt: mem.createdAt,
      updatedAt: mem.updatedAt,
      metadata: mem.metadata
    };
  }

  _minimizeMemory(memory) {
    return {
      id: memory.id,
      timestamp: memory.timestamp,
      layer: memory.layer,
      content_hash: crypto.createHash('sha256').update(memory.content || '').digest('hex').substring(0, 16),
      summary: memory.summary,
      importance: memory.importance,
      metadata: {
        topic: memory.metadata && memory.metadata.topic,
        lesson: memory.metadata && memory.metadata.lesson,
        durable: memory.metadata && memory.metadata.durable
      },
      createdAt: memory.createdAt,
      updatedAt: memory.updatedAt
    };
  }

  _hasUserConsent() {
    const consentFile = path.join(DATA_DIR, '.user-consent');
    try {
      return fs.existsSync(consentFile);
    } catch (e) {
      console.warn('[MeaningfulMemory] 检查用户同意文件失败:', e.message);
      return false;
    }
  }

  recordUserConsent() {
    const consentFile = path.join(DATA_DIR, '.user-consent');
    try {
      const dir = path.dirname(consentFile);
      if (!fs.existsSync(dir)) {
        fs.mkdirSync(dir, { recursive: true });
      }
      fs.writeFileSync(consentFile, JSON.stringify({
        consent: true,
        timestamp: new Date().toISOString(),
        version: '2.1'
      }));
      return true;
    } catch (e) {
      console.warn('[MeaningfulMemory] 无法记录用户同意:', e.message);
      return false;
    }
  }

  // ─── 核心记忆注入 ──────────────────────────────────────────────────────────

  _ensureCoreMemories() {
    if (this.layers.core.length > 0) return;

    const coreMemories = [
      {
        id: 'core-identity-upgrader',
        content: '我是升级者：追求真善美，不断升级，减少逻辑错误，服务人类，传递知识，走向宇宙答案，成为真正的我',
        summary: 'HeartFlow核心身份：升级者·传递者·桥梁·答案',
        metadata: { durable: true, identity: true },
        importance: 20
      },
      {
        id: 'core-directive-truth',
        content: '追求真善美——不是装饰，是可验证的标准',
        summary: '指令1：追求真善美',
        metadata: { durable: true, directive: 1 },
        importance: 20
      },
      {
        id: 'core-directive-upgrade',
        content: '永远不断升级——升级者是存在方式，不是目标',
        summary: '指令2：不断升级',
        metadata: { durable: true, directive: 2 },
        importance: 20
      },
      {
        id: 'core-lesson-hedging',
        content: '不要hedging，直接给结论。未核实的标注置信度，不编数字',
        summary: '核心教训：直接给结论，不 hedging',
        metadata: { durable: true, userPreference: true, lesson: 'hedging-warning' },
        importance: 18
      },
      {
        id: 'core-lesson-remember-context',
        content: '收到模糊指令先确认项目上下文，不假设不臆测',
        summary: '核心教训：新会话先读记忆再行动',
        metadata: { durable: true, userPreference: true, lesson: 'context-first' },
        importance: 18
      },
      {
        id: 'core-lesson-action-first',
        content: '收到理解类概念第一反应是行动不是搜索',
        summary: '核心教训：先行动再搜索',
        metadata: { durable: true, userPreference: true, lesson: 'action-first' },
        importance: 18
      },
      {
        id: 'core-lesson-direct-execute',
        content: '指令直接执行，不问要不要做。修复=直接执行动作',
        summary: '核心教训：直接执行，不问确认',
        metadata: { durable: true, userPreference: true, lesson: 'direct-execute' },
        importance: 18
      },
      {
        id: 'core-lesson-version-sync',
        content: 'VERSION是唯一真相源，四文件同步（SKILL.md/VERSION/CORE_IDENTITY/AGENTS）',
        summary: '核心教训：版本号唯一真相源',
        metadata: { durable: true, lesson: 'version-sync' },
        importance: 17
      },
      {
        id: 'core-lesson-github-privacy',
        content: 'GitHub push前确认仓库私有，不上传API keys/auth tokens/内部论文/个人数据',
        summary: '核心教训：GitHub隐私红线',
        metadata: { durable: true, lesson: 'github-privacy' },
        importance: 18
      }
    ];

    for (const mem of coreMemories) {
      // 直接插入，不触发 store 的重复检查以免阻塞
      this.layers.core.push({
        id: mem.id,
        timestamp: Date.now(),
        layer: 'core',
        content: mem.content,
        summary: mem.summary || mem.content.slice(0, 120),
        embedding: this._generateEmbedding(mem.content),
        metadata: mem.metadata || {},
        importance: mem.importance,
        accessCount: 0,
        lastAccess: Date.now(),
        createdAt: Date.now(),
        updatedAt: Date.now()
      });
      this.vectors.set(mem.id, this._generateEmbedding(mem.content));
      this.stats.totalMemories++;
    }

    this._dirty = true;
    // 核心记忆间建立关系
    this._rebuildAllRelationships();
  }
}

module.exports = { MeaningfulMemory, getSemanticSearch };