import {
  generateText,
  streamText,
  stepCountIs,
  type ModelMessage,
  type Tool as AITool,
  type LanguageModel,
} from 'ai';
import type { Tool, ToolResult, AgentConfig, ContentBlock } from '../types/index.js';
import { buildZodSchema } from '../types/index.js';
import { ToolRegistry } from '../tools/registry.js';
import type {
  AgentInfo,
  AgentExecutionContext,
  AgentExecutionResult,
  ImageData,
} from './types.js';
import { checkBashPermission } from './permission-merger.js';
import { getProviderRegistry } from '../provider/index.js';

/**
 * Agent 执行器
 * 根据 Agent 配置执行任务，支持工具过滤和权限控制
 */
export class AgentExecutor {
  private agentInfo: AgentInfo;
  private baseConfig: AgentConfig;
  private toolRegistry: ToolRegistry;
  private getModel: (model: string) => LanguageModel;

  constructor(
    agentInfo: AgentInfo,
    baseConfig: AgentConfig,
    toolRegistry: ToolRegistry
  ) {
    this.agentInfo = agentInfo;
    this.baseConfig = baseConfig;
    this.toolRegistry = toolRegistry;

    // 使用 ProviderRegistry 获取模型工厂
    const provider = agentInfo.model?.provider ?? baseConfig.provider;
    const registry = getProviderRegistry();
    this.getModel = registry.getModelFactory(provider, {
      apiKey: baseConfig.apiKey,
      baseUrl: baseConfig.baseUrl,
    });
  }

  /**
   * 执行任务
   */
  async execute(
    prompt: string,
    context: AgentExecutionContext
  ): Promise<AgentExecutionResult> {
    const { onStream, onToolCall, onToolResult, images } = context;

    // 获取过滤后的工具
    const tools = this.getFilteredTools();
    const vercelTools = this.buildVercelTools(tools);

    // 构建系统提示词
    const systemPrompt = this.buildSystemPrompt();

    // 获取模型配置
    const modelName = this.agentInfo.model?.model ?? this.baseConfig.model;
    const maxSteps = this.agentInfo.maxSteps ?? 10;
    const maxTokens = this.agentInfo.model?.maxTokens ?? this.baseConfig.maxTokens;

    // 构建消息内容（支持图片）
    const messageContent = this.buildMessageContent(prompt, images);

    // 构建初始消息
    const messages: ModelMessage[] = [
      {
        role: 'user',
        content: messageContent,
      },
    ];

    let fullResponse = '';
    let steps = 0;

    try {
      if (onStream) {
        // 流式模式
        const result = streamText({
          model: this.getModel(modelName),
          system: systemPrompt,
          messages,
          tools: vercelTools,
          maxOutputTokens: maxTokens,
          stopWhen: stepCountIs(maxSteps),
          onChunk: ({ chunk }) => {
            if (chunk.type === 'tool-call') {
              steps++;
              const toolArgs = 'input' in chunk ? chunk.input : {};
              onToolCall?.(chunk.toolName, toolArgs as Record<string, unknown>);
              onStream(`\n[调用工具: ${chunk.toolName}]\n`);
            } else if (chunk.type === 'tool-result') {
              const output = (chunk as { output?: ToolResult }).output;
              onToolResult?.(
                (chunk as { toolName?: string }).toolName ?? 'unknown',
                output
              );
              if (output && typeof output === 'object') {
                if (output.success) {
                  const displayOutput =
                    output.output.length > 500
                      ? output.output.substring(0, 500) + '...(截断)'
                      : output.output;
                  onStream(`[结果: ${displayOutput}]\n`);
                } else {
                  onStream(`[错误: ${output.error}]\n`);
                }
              }
            }
          },
        });

        for await (const chunk of result.textStream) {
          fullResponse += chunk;
          onStream(chunk);
        }

        await result.response;
      } else {
        // 非流式模式
        const result = await generateText({
          model: this.getModel(modelName),
          system: systemPrompt,
          messages,
          tools: vercelTools,
          maxOutputTokens: maxTokens,
          stopWhen: stepCountIs(maxSteps),
        });

        fullResponse = result.text;
        steps = result.steps.length;
      }

      return {
        success: true,
        text: fullResponse,
        steps,
        sessionId: context.parentSessionId ?? 'standalone',
      };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : String(error);
      return {
        success: false,
        text: '',
        steps,
        sessionId: context.parentSessionId ?? 'standalone',
        error: errorMessage,
      };
    }
  }

  /**
   * 获取过滤后的工具列表
   */
  private getFilteredTools(): Tool[] {
    const allTools = this.toolRegistry.getAllTools();
    const toolConfig = this.agentInfo.tools;

    // 如果没有工具配置，返回所有工具
    if (!toolConfig) {
      return allTools;
    }

    let filteredTools = allTools;

    // 如果指定了 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 buildVercelTools(tools: Tool[]): Record<string, AITool> {
    const vercelTools: Record<string, AITool> = {};

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

      vercelTools[tool.name] = {
        description: tool.description,
        inputSchema: schema,
        execute: async (params) => {
          // 权限检查
          const permissionResult = await this.checkToolPermission(
            tool.name,
            params as Record<string, unknown>
          );
          if (!permissionResult.allowed) {
            return {
              success: false,
              output: '',
              error: `权限拒绝: ${permissionResult.reason}`,
            };
          }

          return tool.execute(params as Record<string, unknown>);
        },
      } as AITool;
    }

    return vercelTools;
  }

  /**
   * 检查工具调用权限
   */
  private async checkToolPermission(
    toolName: string,
    params: Record<string, unknown>
  ): Promise<{ allowed: boolean; reason?: string }> {
    const permission = this.agentInfo.permission;
    if (!permission) {
      return { allowed: true };
    }

    // Bash 权限检查
    if (toolName === 'bash' && permission.bash) {
      const command = params.command as string;
      if (!command) {
        return { allowed: true };
      }

      const action = checkBashPermission(command, permission.bash);
      if (action === 'deny') {
        return { allowed: false, reason: `命令被禁止: ${command}` };
      }
      // ask 在这里视为允许（实际的 ask 逻辑在权限管理器中处理）
    }

    // 文件写入权限检查
    if (['write_file', 'edit_file', 'delete_file'].includes(toolName)) {
      const filePermission = permission.file;
      if (filePermission) {
        const operation = toolName === 'write_file' ? 'write' :
                          toolName === 'edit_file' ? 'edit' : 'delete';
        const action = filePermission[operation];
        if (action === 'deny') {
          return { allowed: false, reason: `${operation} 操作被禁止` };
        }
      }
    }

    // Git 写操作权限检查
    const gitWriteTools = ['git_add', 'git_commit', 'git_push', 'git_checkout', 'git_stash'];
    if (gitWriteTools.includes(toolName) && permission.git?.write === 'deny') {
      return { allowed: false, reason: 'Git 写操作被禁止' };
    }

    return { allowed: true };
  }

  /**
   * 构建系统提示词
   */
  private buildSystemPrompt(): string {
    // 如果 Agent 有自定义 prompt，使用它
    if (this.agentInfo.prompt) {
      return this.agentInfo.prompt;
    }

    // 否则使用基础配置的 systemPrompt
    return this.baseConfig.systemPrompt;
  }

  /**
   * 构建消息内容（支持图片）
   */
  private buildMessageContent(
    prompt: string,
    images?: ImageData[]
  ): string | ContentBlock[] {
    // 如果没有图片，直接返回文本
    if (!images || images.length === 0) {
      return prompt;
    }

    // 构建多模态内容
    const blocks: ContentBlock[] = [];

    // 先添加图片
    for (const img of images) {
      blocks.push({
        type: 'image',
        image: img.data,
        mimeType: img.mimeType,
      });
    }

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

    return blocks;
  }
}
