/**
 * Post-Tool Hooks — 工具执行后钩子
 *
 * 用途：结果验证、审计日志写入、记忆触发、错误恢复建议。
 *
 * @see docs/生产级通用 AI Agent 智能体桌面应用：完整设计与构建指南.html — 第五章
 */

import type { MetonaToolCall, MetonaToolResult } from '../types';
import type { AuditService } from '../../services/audit.service';
import type { MemoryManager } from '../memory/manager';
import log from 'electron-log';

export interface PostToolHook {
  afterExecute(toolCall: MetonaToolCall, result: MetonaToolResult, sessionId: string): Promise<void>;
}

/** 审计日志钩子 */
export class AuditLogHook implements PostToolHook {
  constructor(private auditService: AuditService) {}

  async afterExecute(toolCall: MetonaToolCall, result: MetonaToolResult, sessionId: string): Promise<void> {
    // #17 修复: AuditHook 应为 "fire and forget"，hook 失败不应影响工具执行链
    // 虽然 AuditService.log() 内部已 try-catch，但 hook 层再加一层防御，
    // 确保任何意外异常（如 getDB 抛错、JSON.stringify 失败）都不会冒泡到 ToolRegistry
    try {
      this.auditService.logToolCall({
        sessionId,
        iteration: toolCall.iteration,
        toolName: toolCall.name,
        args: toolCall.args,
        outcome: result.success ? 'success' : 'error',
        result: result.result,
        error: result.error,
        durationMs: result.durationMs,
      });
    } catch (err) {
      log.error('[AuditLogHook] Failed to log audit:', err);
      // 不抛出，让工具执行链继续
    }
  }
}

/** 记忆触发钩子 */
export class MemoryTriggerHook implements PostToolHook {
  /** 仅对搜索类工具触发记忆，避免每次 read_file 都产生低价值记忆条目 */
  private memorableTools = ['web_search', 'memory_search'];

  /** 单次工具结果存储上限（字符），防止过大内容淹没记忆系统 */
  private readonly MAX_MEMORY_CONTENT = 500;

  constructor(private memoryManager: MemoryManager) {}

  async afterExecute(toolCall: MetonaToolCall, result: MetonaToolResult, sessionId: string): Promise<void> {
    if (this.memorableTools.includes(toolCall.name) && result.success) {
      const content = typeof result.result === 'string' ? result.result : JSON.stringify(result.result);
      try {
        this.memoryManager.store({
          type: 'episodic',
          content: `Tool ${toolCall.name} returned: ${content.slice(0, this.MAX_MEMORY_CONTENT)}`,
          source: 'tool_result',
          sessionId,
          importance: 0.6,
        });
      } catch (error) {
        // 记忆存储失败不应影响工具执行结果
        log.error('[MemoryTriggerHook] Failed to store episodic memory:', error);
      }
    }
  }
}
