// 多 Agent 协作系统 - 编排器（核心协调器）
import type { AgentType, AgentConfig, AgentTask, AgentResult, MultiAgentPlan } from './types';
import { BaseAgent } from './base-agent';
import { MessageBus } from './message-bus';
import { PlannerAgent } from './agents/planner-agent';
import { BrowserAgent, FileAgent, TerminalAgent, AIAnalysisAgent } from './agents/executor-agent';
import { CombinerAgent } from './agents/combiner-agent';
import { AIManager } from '../ai/manager';
import { generateId } from '../../utils/id';
import { createLogger } from '../../utils/logger';

const log = createLogger('AgentOrchestrator');

type ProgressCallback = (plan: MultiAgentPlan, currentStep?: string) => void;

export class AgentOrchestrator {
  private agents: Map<string, BaseAgent> = new Map();
  private messageBus: MessageBus;
  private ai: AIManager;
  private activePlans: Map<string, MultiAgentPlan> = new Map();

  constructor(ai: AIManager) {
    this.messageBus = new MessageBus();
    this.ai = ai;
    log.info('AgentOrchestrator initialized');
  }

  // 创建 Agent
  spawnAgent(type: AgentType, config: AgentConfig = {}): BaseAgent {
    let agent: BaseAgent;

    switch (type) {
      case 'planner':
        agent = new PlannerAgent(type, config, this.messageBus, this.ai);
        break;
      case 'browser':
        agent = new BrowserAgent(type, config, this.messageBus, this.ai);
        break;
      case 'file':
        agent = new FileAgent(type, config, this.messageBus, this.ai);
        break;
      case 'terminal':
        agent = new TerminalAgent(type, config, this.messageBus, this.ai);
        break;
      case 'combiner':
        agent = new CombinerAgent(type, config, this.messageBus, this.ai);
        break;
      case 'custom':
      default:
        agent = new AIAnalysisAgent(type, config, this.messageBus, this.ai);
        break;
    }

    this.agents.set(agent.id, agent);
    log.info(`Agent spawned: ${agent.id} (${type})`);
    return agent;
  }

  // 终止 Agent
  async terminateAgent(agentId: string): Promise<void> {
    const agent = this.agents.get(agentId);
    if (agent) {
      await agent.terminate();
      this.agents.delete(agentId);
    }
  }

  // 核心方法：执行多 Agent 协作任务
  async executeGoal(goal: string, context: Record<string, any> = {}, onProgress?: ProgressCallback): Promise<AgentResult> {
    const planId = generateId('plan');
    log.info(`Starting multi-agent execution: ${goal} (${planId})`);

    const plan: MultiAgentPlan = {
      id: planId,
      goal,
      steps: [],
      agentAssignments: new Map(),
      status: 'planning',
      results: [],
      createdAt: new Date(),
    };
    this.activePlans.set(planId, plan);

    try {
      // Phase 1: 规划 - 使用 Planner Agent 拆解任务
      plan.status = 'planning';
      onProgress?.(plan, '正在规划任务...');

      const planner = this.spawnAgent('planner', { name: 'task-planner' });
      const planResult = await planner.execute({
        id: generateId('task'),
        type: 'plan',
        description: '规划任务',
        params: { goal },
        context,
        dependencies: [],
      });

      if (!planResult.success || !planResult.data?.steps) {
        throw new Error(`Planning failed: ${planResult.error || 'No steps generated'}`);
      }

      const steps: AgentTask[] = planResult.data.steps.map((s: any) => ({
        id: s.id || generateId('step'),
        type: s.tool || 'ai',
        description: s.description,
        params: s.params || {},
        context: {},
        dependencies: s.dependencies || [],
      }));

      plan.steps = steps;
      log.info(`Plan created with ${steps.length} steps`);
      onProgress?.(plan, `已规划 ${steps.length} 个步骤`);

      // Phase 2: 执行 - 按依赖顺序执行各步骤
      plan.status = 'executing';
      const stepResults: Map<string, AgentResult> = new Map();

      // 拓扑排序
      const sortedSteps = this.topologicalSort(steps);

      for (const step of sortedSteps) {
        // 等待依赖完成
        for (const depId of step.dependencies) {
          const depResult = stepResults.get(depId);
          if (depResult?.data) {
            step.context[depId] = depResult.data;
          }
        }

        // 根据工具类型选择 Agent
        const agentType = this.mapToolToAgentType(step.type);
        const executor = this.spawnAgent(agentType, { name: `executor-${step.id}` });
        plan.agentAssignments.set(step.id, executor.id);

        onProgress?.(plan, `正在执行: ${step.description}`);

        const result = await executor.execute(step);
        stepResults.set(step.id, result);
        plan.results.push(result);

        // 执行完毕，终止 executor
        await this.terminateAgent(executor.id);

        if (!result.success) {
          log.warn(`Step failed: ${step.id} - ${result.error}`);
          // 继续执行其他不依赖此步骤的任务
        }
      }

      // Phase 3: 整合 - 使用 Combiner Agent 汇总结果
      onProgress?.(plan, '正在整合结果...');

      const combiner = this.spawnAgent('combiner', { name: 'result-combiner' });
      const combineResult = await combiner.execute({
        id: generateId('task'),
        type: 'combine',
        description: '整合所有步骤的结果',
        params: {
          goal,
          results: plan.results.map((r, i) => ({
            ...r,
            description: steps[i]?.description,
          })),
        },
        context: {},
        dependencies: [],
      });

      // 清理
      await this.terminateAgent(planner.id);
      await this.terminateAgent(combiner.id);

      plan.status = 'completed';
      onProgress?.(plan, '任务完成');

      log.info(`Multi-agent execution completed: ${planId}`);

      return {
        taskId: planId,
        agentId: 'orchestrator',
        success: combineResult.success,
        data: {
          plan: plan.goal,
          stepsExecuted: plan.results.length,
          stepsSucceeded: plan.results.filter(r => r.success).length,
          report: combineResult.data?.report || '',
          stepResults: plan.results,
        },
        duration: Date.now() - plan.createdAt.getTime(),
      };

    } catch (error: any) {
      plan.status = 'failed';
      log.error(`Multi-agent execution failed: ${error.message}`);

      // 清理所有 Agent
      for (const [id] of this.agents) {
        await this.terminateAgent(id);
      }

      return {
        taskId: planId,
        agentId: 'orchestrator',
        success: false,
        error: error.message,
        duration: Date.now() - plan.createdAt.getTime(),
      };
    }
  }

  // 获取活跃计划
  getActivePlans(): MultiAgentPlan[] {
    return Array.from(this.activePlans.values());
  }

  // 获取所有 Agent
  getAgents(): BaseAgent[] {
    return Array.from(this.agents.values());
  }

  private mapToolToAgentType(tool: string): AgentType {
    switch (tool) {
      case 'browser': return 'browser';
      case 'file': return 'file';
      case 'terminal': return 'terminal';
      case 'ai':
      case 'api':
      default: return 'custom'; // AIAnalysisAgent
    }
  }

  private topologicalSort(steps: AgentTask[]): AgentTask[] {
    const sorted: AgentTask[] = [];
    const visited = new Set<string>();

    const visit = (step: AgentTask) => {
      if (visited.has(step.id)) return;
      visited.add(step.id);

      for (const depId of step.dependencies) {
        const dep = steps.find(s => s.id === depId);
        if (dep) visit(dep);
      }

      sorted.push(step);
    };

    steps.forEach(visit);
    return sorted;
  }

  async shutdown(): Promise<void> {
    for (const [id] of this.agents) {
      await this.terminateAgent(id);
    }
    this.messageBus.clear();
    this.activePlans.clear();
    log.info('AgentOrchestrator shutdown');
  }
}
