/**
 * Memory Manager — 记忆管理器
 *
 * 基于 SQLite（better-sqlite3）的三层记忆系统。
 * 表结构由 DatabaseService 统一创建，此处不再重复。
 *
 * @see docs/生产级通用 AI Agent 智能体桌面应用：完整设计与构建指南.html — 第六章
 * @see standard/开发规范.md — 使用 better-sqlite3（禁止自写数据库层）
 */

import { nanoid } from 'nanoid';
import type Database from 'better-sqlite3';
import log from 'electron-log';

export type MemoryType = 'episodic' | 'semantic' | 'working';
export type MemorySource = 'user_input' | 'tool_result' | 'agent_thought' | 'imported';

export interface MemoryItem {
  id: string;
  type: MemoryType;
  content: string;
  summary?: string;
  source: MemorySource;
  importance: number;
  sessionId?: string;
  createdAt: number;
  expiresAt?: number;
}

export interface SearchResult extends MemoryItem {
  score: number;
}

interface MemorySearchOptions {
  topK?: number;
  sessionId?: string;
  type?: MemoryType;
  minImportance?: number;
}

/**
 * 记忆管理器
 */
export class MemoryManager {
  constructor(private getDB: () => Database.Database) {}

  /**
   * 初始化（表结构由 DatabaseService 创建）
   */
  initialize(): void {
    log.info('MemoryManager initialized');
  }

  /**
   * 存储记忆
   */
  store(item: Omit<MemoryItem, 'id' | 'createdAt'>): string {
    const db = this.getDB();
    const id = `mem_${nanoid(12)}`;
    const now = Date.now();
    const importance = item.importance ?? this.calculateImportance(item);

    switch (item.type) {
      case 'episodic':
        db.prepare(`
          INSERT INTO episodic_memories (id, session_id, content, summary, source, importance, created_at)
          VALUES (?, ?, ?, ?, ?, ?, ?)
        `).run(id, item.sessionId ?? null, item.content, item.summary ?? null, item.source, importance, now);
        break;
      case 'semantic':
        db.prepare(`
          INSERT OR REPLACE INTO semantic_memories (id, key, value, category, confidence, source_session, created_at, updated_at, access_count)
          VALUES (?, ?, ?, ?, ?, ?, ?, ?, 0)
        `).run(id, id, item.content, 'general', importance, item.sessionId ?? null, now, now);
        break;
      case 'working':
        db.prepare(`
          INSERT OR REPLACE INTO working_memories (id, session_id, task_id, key, value, updated_at)
          VALUES (?, ?, ?, ?, ?, ?)
        `).run(id, item.sessionId ?? 'default', 'default', 'default', item.content, now);
        break;
    }

    log.debug(`Memory stored: ${id} (${item.type})`);
    return id;
  }

  /**
   * 检索记忆（关键词搜索）
   */
  search(query: string, options: MemorySearchOptions = {}): SearchResult[] {
    const db = this.getDB();
    const { topK = 5, type, minImportance = 0 } = options;
    if (!query) return [];

    const pattern = `%${query}%`;
    const results: SearchResult[] = [];

    // 搜索情节记忆
    if (!type || type === 'episodic') {
      const rows = db.prepare(`
        SELECT * FROM episodic_memories
        WHERE (content LIKE ? OR summary LIKE ?) AND importance >= ?
        ORDER BY importance DESC, created_at DESC LIMIT ?
      `).all(pattern, pattern, minImportance, topK) as Array<{
        id: string; session_id: string | null; content: string; summary: string | null;
        source: string; importance: number; created_at: number; expires_at: number | null;
      }>;
      for (const row of rows) {
        results.push({
          id: row.id, type: 'episodic', content: row.content,
          summary: row.summary ?? undefined, source: row.source as MemorySource,
          importance: row.importance, sessionId: row.session_id ?? undefined,
          createdAt: row.created_at, expiresAt: row.expires_at ?? undefined,
          score: row.importance,
        });
      }
    }

    // 搜索语义记忆
    if (!type || type === 'semantic') {
      const rows = db.prepare(`
        SELECT * FROM semantic_memories
        WHERE (key LIKE ? OR value LIKE ?) AND confidence >= ?
        ORDER BY confidence DESC, access_count DESC LIMIT ?
      `).all(pattern, pattern, minImportance, Math.ceil(topK / 2)) as Array<{
        id: string; key: string; value: string; category: string | null;
        confidence: number; source_session: string | null; created_at: number;
      }>;
      for (const row of rows) {
        results.push({
          id: row.id, type: 'semantic', content: row.value,
          source: 'imported', importance: row.confidence,
          sessionId: row.source_session ?? undefined,
          createdAt: row.created_at, score: row.confidence,
        });
      }
    }

    // 搜索工作记忆
    if (type === 'working') {
      const rows = db.prepare(`
        SELECT * FROM working_memories
        WHERE (key LIKE ? OR value LIKE ?)
        ORDER BY updated_at DESC LIMIT ?
      `).all(pattern, pattern, topK) as Array<{
        id: string; session_id: string; task_id: string;
        key: string; value: string; updated_at: number;
      }>;
      for (const row of rows) {
        results.push({
          id: row.id, type: 'working', content: row.value,
          source: 'agent_thought', importance: 0.5,
          sessionId: row.session_id, createdAt: row.updated_at,
          score: 0.3, // 工作记忆权重较低
        });
      }
    }

    return results.sort((a, b) => b.score - a.score).slice(0, topK);
  }

  /**
   * 获取工作记忆
   */
  getWorkingMemory(sessionId: string, taskId: string = 'default'): Map<string, string> {
    const db = this.getDB();
    const rows = db.prepare(`
      SELECT key, value FROM working_memories WHERE session_id = ? AND task_id = ?
    `).all(sessionId, taskId) as Array<{ key: string; value: string }>;
    return new Map(rows.map((r) => [r.key, r.value]));
  }

  /**
   * 更新工作记忆
   */
  setWorkingMemory(sessionId: string, taskId: string, key: string, value: string): void {
    const db = this.getDB();
    db.prepare(`
      INSERT OR REPLACE INTO working_memories (id, session_id, task_id, key, value, updated_at)
      VALUES (?, ?, ?, ?, ?, ?)
    `).run(`wm_${nanoid(8)}`, sessionId, taskId, key, value, Date.now());
  }

  /**
   * 清除工作记忆
   */
  clearWorkingMemory(sessionId: string, taskId?: string): void {
    const db = this.getDB();
    if (taskId) {
      db.prepare('DELETE FROM working_memories WHERE session_id = ? AND task_id = ?').run(sessionId, taskId);
    } else {
      db.prepare('DELETE FROM working_memories WHERE session_id = ?').run(sessionId);
    }
  }

  /**
   * 清理过期记忆
   */
  cleanupExpired(): number {
    const db = this.getDB();
    const result = db.prepare('DELETE FROM episodic_memories WHERE expires_at IS NOT NULL AND expires_at < ?').run(Date.now());
    return result.changes;
  }

  private calculateImportance(item: Omit<MemoryItem, 'id' | 'createdAt'>): number {
    let score = 0.5;
    if (item.source === 'user_input') score += 0.2;
    if (item.source === 'tool_result') score += 0.1;
    if (item.content.length > 200) score += 0.1;
    return Math.min(1, Math.max(0, score));
  }
}
