import {
  generateText,
  streamText,
  stepCountIs,
  type ModelMessage,
  type Tool as AITool,
  type LanguageModel,
} from 'ai';
import type { Tool, ToolResult, Message, AgentConfig, UserInput, ContentBlock, ChatResult } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
import { ToolRegistry } from '../tools/registry.js';
import { SessionManager } from '../session/index.js';
import {
  CompressionManager,
  CompressionStatus,
  type TokenUsage,
  type CompressionConfig,
} from '../context/index.js';
import type { AgentInfo, ImageData } from '../agent/types.js';
import { agentRegistry, AgentExecutor, checkBashPermission } from '../agent/index.js';
import { loadVisionConfig } from '../utils/config.js';
import { getProviderRegistry, resolveApiKey } from '../provider/index.js';
import { getHookManager } from '../hooks/index.js';
import { getGitManager } from '../git/index.js';
import {
  createDoomLoopDetector,
  type DoomLoopDetector,
  DOOM_LOOP_WARNING,
} from './doom-loop.js';
import { todoManager } from '../tools/todo/todo-manager.js';
import { initTaskContext } from '../tools/task/index.js';

/**
 * 工具调用开始事件信息
 */
export interface ToolStartInfo {
  id: string;
  toolName: string;
  args: Record<string, unknown>;
}

/**
 * 工具调用结束事件信息
 */
export interface ToolEndInfo {
  id: string;
  status: 'completed' | 'error';
  result?: unknown;
  error?: string;
  duration?: number;
}

/**
 * Doom Loop 检测事件信息
 */
export interface DoomLoopInfo {
  toolName: string;
  count: number;
}

/**
 * Agent.chat() 选项
 */
export interface AgentChatOptions {
  onStream?: (text: string) => void;
  /** 工具开始执行回调 */
  onToolStart?: (info: ToolStartInfo) => void;
  /** 工具执行完成回调 */
  onToolEnd?: (info: ToolEndInfo) => void;
  /** Doom Loop 检测回调 */
  onDoomLoop?: (info: DoomLoopInfo) => void;
  abortSignal?: AbortSignal;
}

export class Agent {
  private getModel: (model: string) => LanguageModel;
  private config: AgentConfig;
  private conversationHistory: ModelMessage[] = [];

  // 工具注册表
  private registry: ToolRegistry | null = null;

  // 已发现的工具（通过 tool_search 发现的）
  private discoveredTools: Set<string> = new Set();

  // 会话管理器（可选）
  private sessionManager: SessionManager | null = null;

  // 压缩管理器
  private compressionManager: CompressionManager;

  // Doom Loop 检测器
  private doomLoopDetector: DoomLoopDetector = createDoomLoopDetector();

  // 当前 Agent 模式（null 表示默认模式）
  private currentAgentMode: AgentInfo | null = null;

  // 原始 system prompt（用于切换回 default 时恢复）
  private originalSystemPrompt: string;

  constructor(config: AgentConfig, compressionConfig?: Partial<CompressionConfig>) {
    this.config = config;
    this.originalSystemPrompt = config.systemPrompt;

    // 使用 ProviderRegistry 获取模型工厂
    const providerRegistry = getProviderRegistry();
    this.getModel = providerRegistry.getModelFactory(config.provider, {
      apiKey: config.apiKey,
      baseUrl: config.baseUrl,
    });

    // 构建压缩配置，使用模型的 contextWindow（如果有）
    const finalCompressionConfig: Partial<CompressionConfig> = {
      ...compressionConfig,
    };
    if (config.contextWindow) {
      finalCompressionConfig.contextLimit = config.contextWindow;
    }

    // 初始化压缩管理器
    this.compressionManager = new CompressionManager(finalCompressionConfig);
    // 设置主模型（作为摘要模型的后备）
    this.compressionManager.setModel(this.getModel(config.model));

    // 从 Agent Registry 加载 Summary Agent 配置
    this.initSummaryModel(config, providerRegistry);
  }

  /**
   * 从 Agent Registry 初始化 Summary 模型
   */
  private initSummaryModel(
    config: AgentConfig,
    providerRegistry: ReturnType<typeof getProviderRegistry>
  ): void {
    // 获取 Summary Agent（internal 模式）
    const summaryAgentInfo = agentRegistry.getInternal('summary');
    if (!summaryAgentInfo?.model) {
      return;
    }

    const modelConfig = summaryAgentInfo.model;
    // 确定 provider（默认使用主配置的 provider）
    const provider = modelConfig.provider || config.provider;

    // 从 ProviderRegistry 获取 API Key
    const providerConfig = providerRegistry.getConfig(provider);
    const apiKey = resolveApiKey(providerConfig) || config.apiKey;

    if (!apiKey) {
      return;
    }

    // 设置 Summary 模型
    const baseUrl = providerConfig?.baseUrl;
    this.compressionManager.setSummaryModelFromAgentConfig(modelConfig, apiKey, baseUrl);
  }

  /**
   * 设置工具注册表（新模式：支持动态工具发现）
   */
  setRegistry(registry: ToolRegistry): void {
    this.registry = registry;
  }

  /**
   * 设置会话管理器（启用会话持久化）
   */
  setSessionManager(manager: SessionManager): void {
    this.sessionManager = manager;
    // 初始化 todoManager，使其能够访问会话数据
    todoManager.setSessionManager(manager);
    // 初始化 Task 工具上下文（使子 Agent 能够正常工作）
    initTaskContext(this.config, manager);
    // 从会话恢复状态
    const session = manager.getSession();
    if (session) {
      this.conversationHistory = [...session.messages];
      this.discoveredTools = new Set(session.discoveredTools);
    }
  }

  /**
   * 获取会话管理器
   */
  getSessionManager(): SessionManager | null {
    return this.sessionManager;
  }

  /**
   * 获取当前可用的工具
   * 返回核心工具 + 已发现的工具，如果当前有 Agent 模式，应用工具过滤
   */
  private getAvailableTools(): Tool[] {
    if (!this.registry) {
      throw new Error('工具注册表未初始化，请先调用 setRegistry()');
    }

    // 核心工具 + 已发现的工具
    const coreTools = this.registry.getCoreTools();
    const discoveredTools = this.registry.getTools([...this.discoveredTools]);
    let tools = [...coreTools, ...discoveredTools];

    // 应用 Agent 模式的工具过滤
    if (this.currentAgentMode?.tools) {
      tools = this.filterToolsByAgentConfig(tools);
    }

    return tools;
  }

  /**
   * 根据 Agent 配置过滤工具
   */
  private filterToolsByAgentConfig(tools: Tool[]): Tool[] {
    const toolConfig = this.currentAgentMode?.tools;
    if (!toolConfig) return tools;

    let filteredTools = tools;

    // 如果设置了 enabled 列表，只保留这些工具
    if (toolConfig.enabled && toolConfig.enabled.length > 0) {
      const enabledSet = new Set(toolConfig.enabled);
      filteredTools = filteredTools.filter((t) => enabledSet.has(t.name));
    }

    // 如果设置了 disabled 列表，排除这些工具
    if (toolConfig.disabled && toolConfig.disabled.length > 0) {
      const disabledSet = new Set(toolConfig.disabled);
      filteredTools = filteredTools.filter((t) => !disabledSet.has(t.name));
    }

    // 如果禁止嵌套 Task，移除 task 工具
    if (toolConfig.noTask) {
      filteredTools = filteredTools.filter((t) => t.name !== 'task');
    }

    return filteredTools;
  }

  /**
   * 将工具转换为 Vercel AI SDK 的工具格式
   */
  private getVercelTools(): Record<string, AITool> {
    const vercelTools: Record<string, AITool> = {};
    const availableTools = this.getAvailableTools();
    const hookManager = getHookManager();

    for (const tool of availableTools) {
      const schema = buildZodSchema(tool.parameters);

      vercelTools[tool.name] = {
        description: tool.description,
        inputSchema: schema,
        execute: async (params) => {
          const args = params as Record<string, unknown>;
          const callId = `${tool.name}-${Date.now()}`;
          const sessionId = this.sessionManager?.getSession()?.id || 'default';

          // 触发工具执行前 hook
          let finalArgs = args;
          if (hookManager) {
            const beforeOutput = await hookManager.triggerToolExecuteBefore({
              tool: tool.name,
              sessionId,
              callId,
              args,
            });

            // 如果 hook 指定跳过，直接返回
            if (beforeOutput.skip && beforeOutput.skipResult) {
              return beforeOutput.skipResult;
            }

            finalArgs = beforeOutput.args;
          }

          // Agent 级别的权限检查（在全局权限检查之前）
          if (tool.name === 'bash' && this.currentAgentMode?.permission?.bash) {
            const command = finalArgs.command as string;
            if (command) {
              const action = checkBashPermission(command, this.currentAgentMode.permission.bash);
              if (action === 'deny') {
                return {
                  success: false,
                  output: '',
                  error: `[Agent 权限拒绝] 当前模式 (${this.currentAgentMode.name}) 禁止执行此命令: ${command}`,
                };
              }
            }
          }

          // 执行工具
          const startTime = Date.now();
          let result = await tool.execute(finalArgs);
          const duration = Date.now() - startTime;

          // 触发工具执行后 hook
          if (hookManager) {
            const afterOutput = await hookManager.triggerToolExecuteAfter(
              {
                tool: tool.name,
                sessionId,
                callId,
                args: finalArgs,
                duration,
              },
              result
            );
            result = afterOutput.result;

            // 对于文件操作工具，触发相应的文件 hook 和 Git 自动提交
            if (result.success) {
              const filePath = finalArgs.path as string | undefined;
              if (filePath) {
                const gitManager = getGitManager();

                if (tool.name === 'write_file') {
                  await hookManager.triggerFileCreated({
                    path: filePath,
                    tool: tool.name,
                    sessionId,
                  });
                  // Git 自动提交
                  if (gitManager) {
                    await gitManager.onFileChanged(filePath, 'create');
                  }
                } else if (tool.name === 'edit_file') {
                  await hookManager.triggerFileEdited({
                    path: filePath,
                    tool: tool.name,
                    sessionId,
                  });
                  // Git 自动提交
                  if (gitManager) {
                    await gitManager.onFileChanged(filePath, 'modify');
                  }
                } else if (tool.name === 'delete_file') {
                  await hookManager.triggerFileDeleted({
                    path: filePath,
                    tool: tool.name,
                    sessionId,
                  });
                  // Git 自动提交
                  if (gitManager) {
                    await gitManager.onFileChanged(filePath, 'delete');
                  }
                }
              }
            }
          }

          // 如果是 tool_search 调用，解析结果并注入发现的工具
          if (tool.name === 'tool_search' && result.success) {
            this.handleToolSearchResult(result.output);
          }

          return result;
        },
      } as AITool;
    }

    return vercelTools;
  }

  /**
   * 处理 tool_search 的结果，将发现的工具添加到可用列表
   */
  private handleToolSearchResult(output: string): void {
    // 解析输出，提取工具名称
    // 格式: "- tool_name: description [category]"
    const matches = output.matchAll(/^- (\w+):/gm);
    for (const match of matches) {
      const toolName = match[1];
      if (this.registry?.has(toolName)) {
        this.discoveredTools.add(toolName);
      }
    }
  }

  /**
   * 发送消息并处理响应（流式）
   * @param userMessage 用户消息文本或包含图片的 UserInput
   * @param options 选项，包含 onStream 回调和 abortSignal
   * @returns ChatResult 包含最终文本和完整的响应消息链
   */
  async chat(userMessage: string | UserInput, options?: AgentChatOptions | ((text: string) => void)): Promise<ChatResult> {
    // 兼容旧的 onStream 参数
    const opts: AgentChatOptions = typeof options === 'function' ? { onStream: options } : (options || {});
    const { onStream, onToolStart, onToolEnd, onDoomLoop, abortSignal } = opts;

    // 重置 doom loop 检测器（每次对话开始时）
    this.doomLoopDetector.reset();

    // 工具调用时间跟踪
    const toolStartTimes = new Map<string, number>();
    // Doom loop 检测状态
    let doomLoopTriggered = false;
    // 处理带图片的消息
    let processedMessage = userMessage;

    if (typeof userMessage !== 'string' && userMessage.images && userMessage.images.length > 0) {
      // 检查当前模型是否支持 vision
      if (!this.supportsVision()) {
        // 不支持 vision，尝试使用 Vision Agent 处理图片
        const visionResult = await this.processImagesWithVisionAgent(
          userMessage.images,
          userMessage.text,
          onStream
        );

        if (visionResult) {
          // 成功，将图片分析结果转换为文本消息
          processedMessage = visionResult;
        } else {
          // 失败，返回错误信息
          const errorText = '无法处理图片：当前模型不支持图片理解，且 Vision 服务未配置或调用失败。';
          return { text: errorText, messages: [] };
        }
      }
    }

    // 构建消息内容
    let messageContent: string | ContentBlock[];

    if (typeof processedMessage === 'string') {
      // 纯文本消息
      messageContent = processedMessage;
    } else {
      // 带图片的消息
      const blocks: ContentBlock[] = [];

      // 添加图片
      if (processedMessage.images && processedMessage.images.length > 0) {
        for (const img of processedMessage.images) {
          blocks.push({
            type: 'image',
            image: img.data,
            mimeType: img.mimeType,
          });
        }
      }

      // 添加文本
      if (processedMessage.text) {
        blocks.push({
          type: 'text',
          text: processedMessage.text,
        });
      }

      messageContent = blocks.length === 1 && blocks[0].type === 'text'
        ? blocks[0].text
        : blocks;
    }

    // 添加用户消息到历史
    this.conversationHistory.push({
      role: 'user',
      content: messageContent,
    } as ModelMessage);

    const vercelTools = this.getVercelTools();
    let fullResponse = '';
    let responseMessages: ModelMessage[] = [];

    if (onStream) {
      // 流式模式
      // 获取当前 Agent 的 maxSteps 配置（默认 50）
      const maxSteps = this.currentAgentMode?.maxSteps ?? 50;

      const result = streamText({
        model: this.getModel(this.config.model),
        system: this.config.systemPrompt,
        messages: this.conversationHistory,
        tools: doomLoopTriggered ? {} : vercelTools, // doom loop 时禁用工具
        maxOutputTokens: this.config.maxTokens,
        stopWhen: stepCountIs(maxSteps),
        abortSignal, // 支持取消
        onChunk: ({ chunk }) => {
          if (chunk.type === 'tool-call') {
            // AI SDK 中工具参数字段名为 input
            const toolCallChunk = chunk as { toolCallId: string; toolName: string; input: unknown };
            const toolCallId = toolCallChunk.toolCallId || `tool-${Date.now()}`;

            // Doom Loop 检测：记录工具调用
            this.doomLoopDetector.record(
              toolCallChunk.toolName,
              toolCallChunk.input
            );

            // 检查是否触发 doom loop
            if (this.doomLoopDetector.isTriggered() && !doomLoopTriggered) {
              doomLoopTriggered = true;
              const toolName = this.doomLoopDetector.getLastToolName() || toolCallChunk.toolName;

              // 通知回调
              onDoomLoop?.({ toolName, count: 3 });

              // 输出警告
              onStream?.(`\n[警告: 检测到 Doom Loop - ${toolName} 被重复调用]\n`);
              onStream?.(DOOM_LOOP_WARNING);
            }

            // 记录开始时间
            toolStartTimes.set(toolCallId, Date.now());

            // 调用 onToolStart 回调
            if (onToolStart) {
              onToolStart({
                id: toolCallId,
                toolName: toolCallChunk.toolName,
                args: (toolCallChunk.input as Record<string, unknown>) || {},
              });
            } else {
              // 仅在没有 onToolStart 回调时输出文本（向后兼容 CLI）
              onStream?.(`\n[调用工具: ${toolCallChunk.toolName}]\n`);
            }
          } else if (chunk.type === 'tool-result') {
            const toolResultChunk = chunk as { toolCallId: string; output?: ToolResult };
            const toolCallId = toolResultChunk.toolCallId || '';
            const output = toolResultChunk.output;

            // 计算执行时长
            const startTime = toolStartTimes.get(toolCallId);
            const duration = startTime ? Date.now() - startTime : undefined;
            toolStartTimes.delete(toolCallId);

            if (output && typeof output === 'object') {
              // 调用 onToolEnd 回调
              if (onToolEnd) {
                onToolEnd({
                  id: toolCallId,
                  status: output.success ? 'completed' : 'error',
                  result: output.success ? output.output : undefined,
                  error: output.success ? undefined : output.error,
                  duration,
                });
              } else {
                // 仅在没有 onToolEnd 回调时输出文本（向后兼容 CLI）
                if (output.success) {
                  const displayOutput =
                    output.output.length > 500
                      ? output.output.substring(0, 500) + '...(截断)'
                      : output.output;
                  onStream?.(`[结果: ${displayOutput}]\n`);
                } else {
                  onStream?.(`[错误: ${output.error}]\n`);
                }
              }
            }
          }
        },
      });

      // 流式输出文本
      let aborted = false;
      try {
        for await (const chunk of result.textStream) {
          // 检查是否已中止
          if (abortSignal?.aborted) {
            aborted = true;
            break;
          }
          fullResponse += chunk;
          onStream(chunk);
        }

        // 如果是手动中止（通过 break 退出），保存已收到的内容
        if (aborted) {
          onStream?.('\n[已取消]\n');
          if (fullResponse) {
            this.conversationHistory.push({
              role: 'assistant',
              content: fullResponse + '\n[已取消]',
            } as ModelMessage);
            await this.persistSession();
          }
          return { text: fullResponse, messages: [] };
        }

        // 等待完成并获取完整的响应消息（包括工具调用和结果）
        const response = await result.response;
        responseMessages = response.messages as ModelMessage[];
      } catch (error) {
        // 如果是中止错误（AbortController.abort() 抛出），优雅处理
        if (error instanceof Error && (error.name === 'AbortError' || abortSignal?.aborted)) {
          onStream?.('\n[已取消]\n');
          // 取消时也要保存已收到的内容
          if (fullResponse) {
            this.conversationHistory.push({
              role: 'assistant',
              content: fullResponse + '\n[已取消]',
            } as ModelMessage);
            await this.persistSession();
          }
          return { text: fullResponse, messages: [] };
        }
        throw error;
      }
    } else {
      // 非流式模式
      // 获取当前 Agent 的 maxSteps 配置（默认 50）
      const maxSteps = this.currentAgentMode?.maxSteps ?? 50;

      const result = await generateText({
        model: this.getModel(this.config.model),
        system: this.config.systemPrompt,
        messages: this.conversationHistory,
        tools: vercelTools,
        maxOutputTokens: this.config.maxTokens,
        stopWhen: stepCountIs(maxSteps),
        abortSignal, // 支持取消
      });

      fullResponse = result.text;
      responseMessages = result.response.messages as ModelMessage[];
    }

    // 将完整的响应消息添加到历史（包括工具调用和结果）
    this.conversationHistory.push(...responseMessages);

    // 检查是否需要自动压缩
    if (this.compressionManager.shouldCompress(this.conversationHistory)) {
      const result = await this.compressionManager.compress(this.conversationHistory);

      if (result.status === CompressionStatus.SUCCESS && result.freedTokens > 0) {
        this.conversationHistory = result.messages;
        if (onStream) {
          const typeLabel = result.type === 'both' ? 'prune+摘要' : result.type === 'compaction' ? '摘要' : 'prune';
          onStream(`\n[自动压缩(${typeLabel}): 释放了 ${(result.freedTokens / 1000).toFixed(1)}k tokens]\n`);
        }
      } else if (result.status === CompressionStatus.FAILED_EMPTY_SUMMARY) {
        if (onStream) {
          onStream('\n[压缩失败: 摘要生成为空，已跳过]\n');
        }
      } else if (result.status === CompressionStatus.FAILED_TOKEN_INFLATED) {
        if (onStream) {
          onStream('\n[压缩失败: 摘要反而增加了 token，已跳过]\n');
        }
      } else if (result.status === CompressionStatus.FAILED_ERROR) {
        if (onStream) {
          onStream(`\n[压缩失败: ${result.error || '未知错误'}]\n`);
        }
      }
    }

    // 持久化会话
    await this.persistSession();

    return {
      text: fullResponse,
      messages: responseMessages,
    };
  }

  /**
   * 持久化当前会话状态
   */
  private async persistSession(): Promise<void> {
    if (!this.sessionManager) return;

    await this.sessionManager.setMessages(this.conversationHistory);
    await this.sessionManager.setDiscoveredTools([...this.discoveredTools]);
  }

  /**
   * 清空对话历史和发现的工具
   */
  async clearHistory(): Promise<void> {
    this.conversationHistory = [];
    this.discoveredTools.clear();

    // 如果有会话管理器，创建新会话
    if (this.sessionManager) {
      await this.sessionManager.newSession();
    }
  }

  /**
   * 获取对话历史
   */
  getHistory(): Message[] {
    return this.conversationHistory
      .filter(
        (msg): msg is ModelMessage & { role: 'user' | 'assistant' } =>
          msg.role === 'user' || msg.role === 'assistant'
      )
      .map((msg) => ({
        role: msg.role,
        content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
      }));
  }

  /**
   * 获取当前可用工具的数量
   */
  getToolCount(): { core: number; discovered: number; total: number } {
    if (!this.registry) {
      return { core: 0, discovered: 0, total: 0 };
    }
    const coreCount = this.registry.getCoreTools().length;
    const discoveredCount = this.discoveredTools.size;
    return {
      core: coreCount,
      discovered: discoveredCount,
      total: coreCount + discoveredCount,
    };
  }

  /**
   * 获取当前上下文使用情况
   */
  getContextUsage(): TokenUsage {
    return this.compressionManager.calculateUsage(this.conversationHistory);
  }

  /**
   * 获取格式化的上下文使用情况（用于 CLI 显示）
   */
  getContextUsageFormatted(): string {
    return this.compressionManager.formatUsage(this.conversationHistory);
  }

  /**
   * 获取压缩管理器
   */
  getCompressionManager(): CompressionManager {
    return this.compressionManager;
  }

  /**
   * 手动压缩对话历史（用于 /compact 命令）
   */
  async compactHistory(): Promise<{ freedTokens: number; type: string }> {
    const result = await this.compressionManager.forceCompress(this.conversationHistory);
    if (result.freedTokens > 0) {
      this.conversationHistory = result.messages;
      await this.persistSession();
    }
    return {
      freedTokens: result.freedTokens,
      type: result.type,
    };
  }

  /**
   * 切换 Agent 模式
   * @param agent AgentInfo 对象或模式字符串 ('build'/'plan')
   */
  setAgentMode(agent: AgentInfo | 'build' | 'plan' | null): void {
    // 如果是字符串模式，从 registry 获取预设
    if (typeof agent === 'string') {
      const presetAgent = agentRegistry.get(agent);
      if (presetAgent) {
        this.currentAgentMode = presetAgent;
        // 使用 resolveSystemPrompt 获取提示词
        this.config = {
          ...this.config,
          systemPrompt: this.resolveSystemPrompt(presetAgent),
        };
      } else {
        // 如果找不到预设，回退到默认模式
        this.currentAgentMode = null;
        this.config = {
          ...this.config,
          systemPrompt: this.originalSystemPrompt,
        };
      }
      return;
    }

    this.currentAgentMode = agent;

    if (agent) {
      // 切换到指定 Agent，使用 resolveSystemPrompt 获取提示词
      this.config = {
        ...this.config,
        systemPrompt: this.resolveSystemPrompt(agent),
      };
    } else {
      // 切换回 default，恢复原始 prompt
      this.config = {
        ...this.config,
        systemPrompt: this.originalSystemPrompt,
      };
    }
  }

  /**
   * 解析系统提示词
   *
   * 直接使用 Agent 的 prompt 字段作为系统提示词
   */
  private resolveSystemPrompt(agent: AgentInfo): string {
    return agent.prompt || '';
  }

  /**
   * 切换 Agent 模式（保留对话历史）
   *
   * 与 setAgentMode 不同，switchMode 会保留对话历史，
   * 适用于会话中动态切换 Build ↔ Plan 模式。
   *
   * @param mode 目标模式
   * @param preserveHistory 是否保留对话历史（默认 true）
   */
  switchMode(mode: AgentInfo | 'build' | 'plan' | null, preserveHistory = true): void {
    // 保存当前对话历史
    const currentHistory = preserveHistory ? [...this.conversationHistory] : [];

    // 执行模式切换
    this.setAgentMode(mode);

    // 恢复对话历史
    if (preserveHistory) {
      this.conversationHistory = currentHistory;
    }

    // 重置 doom loop 检测器（新模式重新计数）
    this.doomLoopDetector.reset();
  }

  /**
   * 检查当前是否为只读模式
   *
   * 只读模式：file.write === 'deny' && file.edit === 'deny'
   */
  isReadOnlyMode(): boolean {
    const permission = this.currentAgentMode?.permission;
    if (!permission) return false;

    return permission.file?.write === 'deny' && permission.file?.edit === 'deny';
  }

  // ============================================================================
  // Auto-approve 功能（用于前端 Build 模式的自动授权）
  // ============================================================================

  /** 临时自动授权配置 */
  private autoApproveConfig: { file?: { write?: 'allow'; edit?: 'allow' } } | null = null;

  /**
   * 设置自动授权配置
   * 仅影响 file write 和 file edit 操作（不包含 delete）
   */
  setAutoApprove(config: { file?: { write?: 'allow'; edit?: 'allow' } }): void {
    this.autoApproveConfig = config;
  }

  /**
   * 清除自动授权配置
   */
  clearAutoApprove(): void {
    this.autoApproveConfig = null;
  }

  /**
   * 获取当前自动授权配置
   */
  getAutoApproveConfig(): { file?: { write?: 'allow'; edit?: 'allow' } } | null {
    return this.autoApproveConfig;
  }

  /**
   * 获取当前 Agent 模式
   */
  getAgentMode(): AgentInfo | null {
    return this.currentAgentMode;
  }

  /**
   * 获取当前 Agent 名称
   */
  getAgentModeName(): string {
    return this.currentAgentMode?.name ?? 'default';
  }

  /**
   * 使用 Vision Agent 处理图片
   * 当主模型不支持 vision 时，委托给 Vision Agent 分析图片
   * @returns 包含图片分析结果的文本消息，或 null 表示失败
   */
  private async processImagesWithVisionAgent(
    images: ImageData[],
    userText?: string,
    onStream?: (text: string) => void
  ): Promise<string | null> {
    // 检查 Vision 配置是否可用
    const visionConfig = loadVisionConfig();
    if (!visionConfig) {
      onStream?.('\n⚠ Vision 服务未配置，无法处理图片\n');
      return null;
    }

    // 获取 Vision Agent
    const visionAgent = agentRegistry.get('vision');
    if (!visionAgent) {
      onStream?.('\n⚠ Vision Agent 未注册\n');
      return null;
    }

    // 确保有工具注册表
    if (!this.registry) {
      onStream?.('\n⚠ 工具注册表未初始化\n');
      return null;
    }

    onStream?.(`\n[委托 Vision Agent (${visionConfig.model}) 分析图片...]\n`);

    // 构建 Vision 配置
    const visionAgentConfig: AgentConfig = {
      ...this.config,
      provider: visionConfig.provider,
      apiKey: visionConfig.apiKey,
      model: visionConfig.model,
      baseUrl: visionConfig.baseUrl,
    };

    // 创建 Vision Agent 执行器
    const executor = new AgentExecutor(visionAgent, visionAgentConfig, this.registry);

    // 构建提示词
    const prompt = userText || '请详细描述这张图片的内容';

    // 执行 Vision 分析
    const result = await executor.execute(prompt, {
      workdir: process.cwd(),
      images,
      onStream: undefined, // Vision Agent 不使用流式输出
    });

    if (!result.success) {
      onStream?.(`\n⚠ Vision 分析失败: ${result.error}\n`);
      return null;
    }

    onStream?.('\n[Vision 分析完成]\n');

    // 构建带分析结果的文本消息
    const combinedText = `[图片分析结果 - 由 ${visionConfig.model} 提供]\n${result.text}\n\n用户问题: ${userText || '(无附加问题)'}`;

    return combinedText;
  }

  /**
   * 检查当前模型是否支持 vision（图片理解）
   */
  supportsVision(): boolean {
    const model = this.config.model.toLowerCase();

    // Anthropic Claude 模型支持 vision
    if (this.config.provider === 'anthropic') {
      // Claude 3 及以上版本支持 vision
      return model.includes('claude-3') || model.includes('claude-4');
    }

    // OpenAI GPT-4 系列支持 vision
    if (this.config.provider === 'openai') {
      // GPT-4o, GPT-4 Turbo, GPT-4 Vision 等支持
      return model.includes('gpt-4');
    }

    // DeepSeek 目前不支持 vision
    if (this.config.provider === 'deepseek') {
      return false;
    }

    return false;
  }

  /**
   * 获取当前配置
   */
  getConfig(): AgentConfig {
    return { ...this.config };
  }
}
