/**
 * IPC Handlers — 所有 IPC 通道处理逻辑
 *
 * 集成三层日志：
 * - TOOL 层：AuditService 记录工具调用到 audit_logs 表
 * - TRACE 层：SessionRecorder 写入 session_*.jsonl
 * - AGENT 层：electron-log 记录状态转换
 *
 * @see docs/MetonaAI-Desktop 架构与交互设计.html — IPC 架构 + 日志分层
 */

import { ipcMain, BrowserWindow, shell, app, dialog } from 'electron';
import type { SessionService } from '../services/session.service';
import type { ConfigService } from '../services/config.service';
import type { WorkspaceService } from '../services/workspace.service';
import type { ContextBuilder } from '../harness/prompts/context-builder';
import type { AgentLoopEngine } from '../harness/agent-loop';
import type { ToolRegistry } from '../harness/tools/registry';
import type { AuditService } from '../services/audit.service';
import type { SessionRecorder } from '../services/session-recorder.service';
import type { MemoryManager } from '../harness/memory/manager';
import type { MCPManager } from '../services/mcp-manager.service';
import type { MetonaMessage, MetonaStreamEvent } from '../harness/types';
import { MetonaErrorCode, MetonaStreamEventType } from '../harness/types';
import type { MetonaError } from '../harness/types';
import log from 'electron-log';

/**
 * 注册所有 IPC 处理器
 */
export function registerAllIPCHandlers(
  mainWindow: BrowserWindow,
  sessionService: SessionService,
  configService: ConfigService,
  workspaceService: WorkspaceService,
  contextBuilder: ContextBuilder,
  agentLoop: AgentLoopEngine,
  _toolRegistry: ToolRegistry,
  auditService: AuditService,
  sessionRecorder: SessionRecorder,
  memoryManager: MemoryManager,
  mcpManager: MCPManager,
): void {

  // ===== Agent 交互 =====

  ipcMain.handle('agent:sendMessage', async (_event, userMessage: MetonaMessage, sessionId: string) => {
    log.info('[AGENT] sendMessage:', sessionId, userMessage.content.slice(0, 80));

    // TRACE 层：开始录制
    sessionRecorder.startRecording(sessionId);

    // TOOL 层：记录会话开始
    auditService.logSessionStart(sessionId);

    // 保存用户消息到数据库
    sessionService.saveMessage({
      sessionId,
      role: 'user',
      content: userMessage.content,
      attachments: (userMessage as any).attachments,
    });

    // 加载历史消息
    const historyRows = sessionService.getMessages(sessionId);
    const history: MetonaMessage[] = historyRows
      .filter((m) => m.role !== 'system')
      .slice(0, -1)
      .map((m) => ({
        role: m.role as MetonaMessage['role'],
        content: m.content,
        reasoningContent: m.reasoningContent,
        timestamp: m.timestamp,
      }));

    // 从工作空间文件构建 System Prompt
    const workspaceFiles = workspaceService.getFiles();
    const systemPrompt = contextBuilder.buildSystemPrompt(workspaceFiles);

    // 监听 Agent Loop 事件
    const onStreamEvent = (event: MetonaStreamEvent) => {
      if (!mainWindow.isDestroyed()) {
        mainWindow.webContents.send('agent:streamEvent', event);
      }
    };

    const onStateChange = (data: { previous?: string; current?: string; sessionId?: string; iteration?: number; state?: string }) => {
      // AGENT 层：记录状态转换
      if (data.previous) log.info(`[AGENT] State: ${data.previous} → ${data.current}`);
      // 转发到渲染进程（携带迭代号）
      if (!mainWindow.isDestroyed()) {
        mainWindow.webContents.send('agent:stateChange', data);
      }
    };

    agentLoop.on('streamEvent', onStreamEvent);
    agentLoop.on('stateChange', onStateChange);

    try {
      // TRACE 层：记录上下文构建
      sessionRecorder.recordContextBuilt({
        tokenCount: history.reduce((sum, m) => sum + Math.ceil(m.content.length / 2), 0),
        usageRatio: 0,
      });

      // 启动 Agent Loop
      const output = await agentLoop.runStream(userMessage, sessionId, history, systemPrompt);

      // 保存 assistant 回复到数据库
      sessionService.saveMessage({
        sessionId,
        role: 'assistant',
        content: output.finalAnswer,
      });

      // 更新 Token 统计
      if (output.totalTokenUsage.totalTokens > 0) {
        sessionService.updateTokenUsage(sessionId, output.totalTokenUsage.totalTokens);
      }

      // 更新 MEMORY.md 时间戳
      workspaceService.updateMemoryTimestamp();

      // TOOL 层：记录会话结束
      auditService.logSessionEnd({
        sessionId,
        totalIterations: output.iterations.length,
        totalTokens: output.totalTokenUsage.totalTokens,
        durationMs: output.durationMs,
        terminationReason: output.terminationReason,
      });

      // TRACE 层：停止录制
      sessionRecorder.stopRecording({
        totalIterations: output.iterations.length,
        totalTokens: output.totalTokenUsage.totalTokens,
        durationMs: output.durationMs,
        terminationReason: output.terminationReason,
      });

      log.info(`[AGENT] Completed: ${output.terminationReason}, ${output.iterations.length} iterations, ${output.durationMs}ms`);

      return { success: true };
    } catch (error) {
      log.error('[AGENT] Error:', error);

      // TOOL 层：记录错误
      auditService.log({
        sessionId,
        eventType: 'error',
        actor: 'agent',
        target: 'agent_loop',
        details: { error: (error as Error).message },
        outcome: 'error',
      });

      // TRACE 层：停止录制
      sessionRecorder.stopRecording({
        totalIterations: 0,
        totalTokens: 0,
        durationMs: 0,
        terminationReason: 'error',
      });

      // 发送错误事件到 UI
      if (!mainWindow.isDestroyed()) {
        const metonaError: MetonaError = {
          code: MetonaErrorCode.UNKNOWN,
          message: (error as Error).message,
          retryable: false,
        };
        const errorEvent: MetonaStreamEvent = {
          type: MetonaStreamEventType.ERROR,
          requestId: '',
          sessionId,
          iteration: 0,
          seq: 0,
          timestamp: Date.now(),
          error: metonaError,
        };
        mainWindow.webContents.send('agent:streamEvent', errorEvent);
      }

      return { success: false, error: (error as Error).message };
    } finally {
      agentLoop.off('streamEvent', onStreamEvent);
      agentLoop.off('stateChange', onStateChange);
    }
  });

  ipcMain.handle('agent:abortSession', async (_event, sessionId) => {
    log.info('[AGENT] Abort:', sessionId);
    agentLoop.abort();

    // TOOL 层：记录中断
    auditService.log({
      sessionId,
      eventType: 'session_end',
      actor: 'user',
      target: 'session',
      details: { reason: 'user_abort' },
      outcome: 'denied',
    });

    return { success: true };
  });

  // ===== 会话管理 =====

  ipcMain.handle('sessions:list', async () => {
    return sessionService.list();
  });

  ipcMain.handle('sessions:create', async (_event, title?: string) => {
    return sessionService.create(title);
  });

  ipcMain.handle('sessions:rename', async (_event, sessionId, title) => {
    return { success: sessionService.rename(sessionId, title) };
  });

  ipcMain.handle('sessions:delete', async (_event, sessionId) => {
    return { success: sessionService.delete(sessionId) };
  });

  ipcMain.handle('sessions:getMessages', async (_event, sessionId) => {
    return sessionService.getMessages(sessionId);
  });

  ipcMain.handle('sessions:pin', async (_event, sessionId, pinned) => {
    return { success: sessionService.pin(sessionId, pinned) };
  });

  ipcMain.handle('sessions:archive', async (_event, sessionId, archived) => {
    return { success: sessionService.archive(sessionId, archived) };
  });

  ipcMain.handle('sessions:deleteMessage', async (_event, messageId) => {
    return { success: sessionService.deleteMessage(messageId) };
  });

  ipcMain.handle('sessions:clearMessages', async (_event, sessionId) => {
    return { success: sessionService.clearMessages(sessionId) };
  });

  ipcMain.handle('sessions:saveTrace', async (_event, sessionId, data) => {
    try {
      sessionService.saveTraceData(sessionId, data);
      return { success: true };
    } catch (error) {
      return { success: false, error: (error as Error).message };
    }
  });

  ipcMain.handle('sessions:getTrace', async (_event, sessionId) => {
    return sessionService.getTraceData(sessionId);
  });

  // ===== MCP 管理 =====

  ipcMain.handle('mcp:listServers', async () => {
    return mcpManager.getServerStates();
  });

  ipcMain.handle('mcp:addServer', async (_event, config: { name: string; transport: string; command?: string; args?: string[]; url?: string }) => {
    try {
      await mcpManager.addServer({
        name: config.name,
        transport: config.transport as 'stdio' | 'sse',
        command: config.command,
        args: config.args,
        url: config.url,
        enabled: true,
      });
      log.info(`MCP server added: ${config.name}`);
      return { success: true };
    } catch (error) {
      return { success: false, error: (error instanceof Error ? error.message : String(error)) };
    }
  });

  ipcMain.handle('mcp:removeServer', async (_event, name: string) => {
    try {
      await mcpManager.removeServer(name);
      return { success: true };
    } catch {
      return { success: false };
    }
  });

  ipcMain.handle('mcp:toggleServer', async (_event, name: string, enabled: boolean) => {
    try {
      await mcpManager.toggleServer(name, enabled);
      return { success: true };
    } catch {
      return { success: false };
    }
  });

  // ===== 记忆 =====

  ipcMain.handle('db:searchMemories', async (_event, query, options) => {
    return memoryManager.search(query, options);
  });

  // ===== 配置 =====

  ipcMain.handle('config:get', async (_event, key) => {
    return configService.get(key);
  });

  ipcMain.handle('config:set', async (_event, key, value) => {
    configService.set(key, value);

    // TOOL 层：记录配置变更
    auditService.log({
      sessionId: '',
      eventType: 'config_change',
      actor: 'user',
      target: key,
      details: { value },
      outcome: 'success',
    });

    return { success: true };
  });

  // ===== 应用工具 =====

  ipcMain.handle('app:getVersion', async () => {
    return app.getVersion();
  });

  ipcMain.handle('app:getAppDataPath', async () => {
    return app.getPath('userData');
  });

  ipcMain.handle('app:openExternal', async (_event, url) => {
    await shell.openExternal(url);
  });

  ipcMain.handle('app:showItemInFolder', async (_event, path) => {
    shell.showItemInFolder(path);
  });

  ipcMain.handle('app:selectFolder', async (_event, defaultPath?: string) => {
    const result = await dialog.showOpenDialog(mainWindow, {
      properties: ['openDirectory', 'createDirectory'],
      defaultPath: defaultPath ?? app.getPath('home'),
      title: '选择工作空间目录',
    });
    if (result.canceled || result.filePaths.length === 0) return { canceled: true, path: '' };
    return { canceled: false, path: result.filePaths[0] };
  });

  // ===== 工具管理 =====

  ipcMain.handle('tools:list', async () => {
    return _toolRegistry.listTools().map((t) => ({
      name: t.name,
      description: t.description,
      category: t.category,
      riskLevel: t.riskLevel,
      requiresPermission: t.requiresPermission,
    }));
  });

  ipcMain.handle('tools:toggle', async (_event, toolName: string, enabled: boolean) => {
    // 工具开关通过配置持久化
    configService.set(`tools.${toolName}.enabled`, enabled);
    log.info(`Tool ${toolName} ${enabled ? 'enabled' : 'disabled'}`);
    return { success: true };
  });

  // ===== 数据管理 =====

  ipcMain.handle('data:export', async (_event, sessionId?: string) => {
    try {
      const db = sessionService.getDB();
      if (sessionId) {
        // 导出单个会话
        const messages = sessionService.getMessages(sessionId);
        return { success: true, data: messages };
      }
      // 导出所有会话
      const sessions = sessionService.list();
      const allData: Record<string, unknown> = { sessions: [], config: configService.getAll() };
      for (const session of sessions) {
        (allData.sessions as Array<Record<string, unknown>>).push({
          ...session,
          messages: sessionService.getMessages(session.id),
        });
      }
      return { success: true, data: allData };
    } catch (error) {
      return { success: false, error: (error as Error).message };
    }
  });

  ipcMain.handle('data:clearSessions', async () => {
    try {
      const db = sessionService.getDB();
      db.exec('DELETE FROM messages');
      db.exec('DELETE FROM sessions');
      log.info('[DATA] All sessions cleared');
      return { success: true };
    } catch (error) {
      return { success: false, error: (error as Error).message };
    }
  });

  ipcMain.handle('data:clearMemories', async () => {
    try {
      const db = sessionService.getDB();
      db.exec('DELETE FROM episodic_memories');
      db.exec('DELETE FROM semantic_memories');
      db.exec('DELETE FROM working_memories');
      log.info('[DATA] All memories cleared');
      return { success: true };
    } catch (error) {
      return { success: false, error: (error as Error).message };
    }
  });

  ipcMain.handle('data:clearAuditLogs', async () => {
    try {
      // 审计日志是 INSERT-ONLY，需要先禁用触发器
      const db = sessionService.getDB();
      db.exec('DROP TRIGGER IF EXISTS audit_no_delete');
      db.exec('DELETE FROM audit_logs');
      db.exec(`
        CREATE TRIGGER audit_no_delete BEFORE DELETE ON audit_logs
        BEGIN
          SELECT RAISE(ABORT, 'Audit logs are INSERT-ONLY. Deletion is not allowed.');
        END
      `);
      log.info('[DATA] Audit logs cleared');
      return { success: true };
    } catch (error) {
      return { success: false, error: (error as Error).message };
    }
  });

  log.info('[SYS] All IPC handlers registered');
}
