import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { ConfigManager } from '../../config/config-manager.js';
import { AgentOrchestrator } from './orchestrator.js';
import { OrchestrationStrategies } from './strategies.js';
import { Agent, Task, ConversationThread } from './types.js';

let configManager: ConfigManager;
let orchestrator: AgentOrchestrator;

export async function setupAgentOrchestrationTools(server: Server, config?: ConfigManager) {
  configManager = config || new ConfigManager();
  orchestrator = new AgentOrchestrator();

  // Add agent orchestration tool handlers
  server.setRequestHandler(CallToolRequestSchema, async (request) => {
    const { name, arguments: args } = request.params;

    if (!args) {
      throw new Error('No arguments provided');
    }

    switch (name) {
      case 'create_orchestration_session': {
        const { name: sessionName, goal } = args as { name: string; goal: string };
        
        const session = orchestrator.createSession(sessionName, goal);
        
        return {
          content: [
            {
              type: 'text',
              text: `🎭 Orchestration session created!\n\n` +
                    `📋 Session: ${session.name}\n` +
                    `🎯 Goal: ${session.goal}\n` +
                    `🆔 ID: ${session.id}\n` +
                    `📊 Status: ${session.status}\n\n` +
                    `Next steps:\n` +
                    `1. Create agents with 'create_agent'\n` +
                    `2. Apply a strategy with 'apply_strategy'\n` +
                    `3. Or create custom tasks with 'create_orchestrated_task'`,
            },
          ],
          structured: {
            session: {
              id: session.id,
              name: session.name,
              goal: session.goal,
              status: session.status,
            },
          },
        };
      }
      
      case 'create_agent': {
        const { 
          role, 
          name: agentName,
          capabilities = []
        } = args as {
          role: Agent['role'];
          name?: string;
          capabilities?: string[];
        };
        
        const template = {
          name: agentName || `${role} Agent`,
          role,
          systemPrompt: `You are a ${role} agent. Focus on your specialized role.`,
          capabilities: capabilities.length > 0 ? capabilities : ['general'],
        };
        
        const agent = orchestrator.createAgent(template, agentName);
        
        return {
          content: [
            {
              type: 'text',
              text: `🤖 Agent created!\n\n` +
                    `👤 Name: ${agent.name}\n` +
                    `🎭 Role: ${agent.role}\n` +
                    `🔧 Capabilities: ${agent.capabilities.join(', ')}\n` +
                    `📊 Status: ${agent.status}\n` +
                    `🆔 ID: ${agent.id}`,
            },
          ],
          structured: {
            agent: {
              id: agent.id,
              name: agent.name,
              role: agent.role,
              capabilities: agent.capabilities,
              status: agent.status,
            },
          },
        };
      }
      
      case 'send_agent_message': {
        const { from, to, content, type = 'query' } = args as {
          from: string;
          to: string | string[];
          content: string;
          type?: 'query' | 'response' | 'instruction' | 'result' | 'error';
        };
        
        await orchestrator.sendMessage(from, to, content, type);
        
        const recipients = Array.isArray(to) ? to.join(', ') : to;
        
        return {
          content: [
            {
              type: 'text',
              text: `💬 Message sent!\n\n` +
                    `📤 From: ${from}\n` +
                    `📥 To: ${recipients}\n` +
                    `📝 Type: ${type}\n` +
                    `💭 Content: ${content.substring(0, 100)}...`,
            },
          ],
        };
      }
      
      case 'create_orchestrated_task': {
        const { 
          description, 
          requiredCapabilities = [],
          dependencies = []
        } = args as {
          description: string;
          requiredCapabilities?: string[];
          dependencies?: string[];
        };
        
        const task = orchestrator.createTask(description, requiredCapabilities, dependencies);
        
        return {
          content: [
            {
              type: 'text',
              text: `📋 Task created!\n\n` +
                    `📝 Description: ${task.description}\n` +
                    `🔧 Required: ${task.requiredCapabilities.join(', ') || 'None'}\n` +
                    `👥 Assigned to: ${task.assignedTo.length} agent(s)\n` +
                    `📊 Status: ${task.status}\n` +
                    `🔗 Dependencies: ${task.dependencies.length}`,
            },
          ],
          structured: {
            task: {
              id: task.id,
              description: task.description,
              status: task.status,
              assignedTo: task.assignedTo,
            },
          },
        };
      }
      
      case 'execute_orchestrated_task': {
        const { taskId } = args as { taskId: string };
        
        try {
          const result = await orchestrator.executeTask(taskId);
          
          return {
            content: [
              {
                type: 'text',
                text: `✅ Task executed!\n\n` +
                      `📊 Success: ${result.success}\n` +
                      `📤 Output: ${result.output}\n` +
                      `📦 Artifacts: ${result.artifacts.length}\n` +
                      `⏱️ Duration: ${result.performance.duration}ms`,
              },
            ],
            structured: result,
          };
        } catch (error) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Task execution failed: ${(error as Error).message}`,
              },
            ],
          };
        }
      }
      
      case 'apply_strategy': {
        const { strategyName, customStrategy } = args as {
          strategyName?: string;
          customStrategy?: any;
        };
        
        let strategy;
        if (strategyName) {
          strategy = OrchestrationStrategies.getStrategy(strategyName);
          if (!strategy) {
            const available = [
              'Feature Development',
              'Code Refactoring',
              'Bug Investigation',
              'API Design',
              'Performance Optimization',
              'Security Audit',
            ];
            
            return {
              content: [
                {
                  type: 'text',
                  text: `❌ Strategy "${strategyName}" not found.\n\n` +
                        `Available strategies:\n${available.map(s => `• ${s}`).join('\n')}`,
                },
              ],
            };
          }
        } else if (customStrategy) {
          strategy = customStrategy;
        } else {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Please provide either strategyName or customStrategy`,
              },
            ],
          };
        }
        
        await orchestrator.applyStrategy(strategy);
        
        return {
          content: [
            {
              type: 'text',
              text: `🎯 Strategy applied!\n\n` +
                    `📋 Strategy: ${strategy.name}\n` +
                    `📝 Description: ${strategy.description}\n` +
                    `🔢 Steps: ${strategy.steps.length}\n\n` +
                    `The agents are now working according to the strategy.`,
            },
          ],
          structured: {
            strategy: strategy.name,
            stepsExecuted: strategy.steps.length,
          },
        };
      }
      
      case 'get_agent_conversations': {
        const { agentIds } = args as { agentIds: string[] };
        
        const conversations = orchestrator.getConversationHistory(agentIds);
        
        const summary = conversations.map(thread => {
          const lastMessage = thread.messages[thread.messages.length - 1];
          return `📍 ${thread.topic}\n` +
                 `   Messages: ${thread.messages.length}\n` +
                 `   Last: ${lastMessage?.content.substring(0, 50)}...`;
        }).join('\n\n');
        
        return {
          content: [
            {
              type: 'text',
              text: `💬 Conversation History\n\n` +
                    `Found ${conversations.length} conversation(s):\n\n${summary}`,
            },
          ],
          structured: {
            conversations: conversations.map(thread => ({
              id: thread.id,
              topic: thread.topic,
              messageCount: thread.messages.length,
              participants: thread.participants,
              status: thread.status,
            })),
          },
        };
      }
      
      case 'get_agent_state': {
        const { agentId } = args as { agentId: string };
        
        const agent = orchestrator.getAgentState(agentId);
        
        if (!agent) {
          return {
            content: [
              {
                type: 'text',
                text: `❌ Agent ${agentId} not found`,
              },
            ],
          };
        }
        
        return {
          content: [
            {
              type: 'text',
              text: `🤖 Agent State: ${agent.name}\n\n` +
                    `🎭 Role: ${agent.role}\n` +
                    `📊 Status: ${agent.status}\n` +
                    `🧠 Memory:\n` +
                    `  • Context items: ${agent.memory.context.length}\n` +
                    `  • Findings: ${Object.keys(agent.memory.findings).length}\n` +
                    `  • Decisions: ${agent.memory.decisions.length}\n` +
                    `  • Conversations: ${agent.memory.conversations.length}\n` +
                    `⏰ Last active: ${agent.lastActiveAt.toISOString()}`,
            },
          ],
          structured: {
            agent: {
              ...agent,
              memory: {
                contextCount: agent.memory.context.length,
                findingsCount: Object.keys(agent.memory.findings).length,
                decisionsCount: agent.memory.decisions.length,
                conversationsCount: agent.memory.conversations.length,
              },
            },
          },
        };
      }
      
      case 'complete_orchestration_session': {
        orchestrator.completeSession();
        
        return {
          content: [
            {
              type: 'text',
              text: `✅ Orchestration session completed!\n\n` +
                    `Check the session results for summary, artifacts, and insights.`,
            },
          ],
        };
      }
      
      case 'suggest_orchestration_strategy': {
        const { taskType } = args as { taskType: string };
        
        const strategies = OrchestrationStrategies.getApplicableStrategies(taskType);
        
        if (strategies.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: `No pre-defined strategies found for task type: ${taskType}\n\n` +
                      `You can create a custom strategy or use one of the available strategies.`,
              },
            ],
          };
        }
        
        const suggestions = strategies.map(s => 
          `📋 ${s.name}\n   ${s.description}\n   Steps: ${s.steps.length}`
        ).join('\n\n');
        
        return {
          content: [
            {
              type: 'text',
              text: `🎯 Suggested strategies for "${taskType}":\n\n${suggestions}`,
            },
          ],
          structured: {
            strategies: strategies.map(s => ({
              name: s.name,
              description: s.description,
              steps: s.steps.length,
            })),
          },
        };
      }
      
      default:
        // Not an agent orchestration tool
        return null as any;
    }
  });

  return {
    tools: [
      {
        name: 'create_orchestration_session',
        description: 'Create a new agent orchestration session',
        inputSchema: {
          type: 'object',
          properties: {
            name: { type: 'string', description: 'Session name' },
            goal: { type: 'string', description: 'Goal to achieve' },
          },
          required: ['name', 'goal'],
        },
      },
      {
        name: 'create_agent',
        description: 'Create a specialized agent',
        inputSchema: {
          type: 'object',
          properties: {
            role: { 
              type: 'string',
              enum: ['primary', 'researcher', 'coder', 'reviewer', 'tester', 'documenter', 'custom'],
              description: 'Agent role'
            },
            name: { type: 'string', description: 'Custom agent name' },
            capabilities: { 
              type: 'array',
              items: { type: 'string' },
              description: 'Agent capabilities'
            },
          },
          required: ['role'],
        },
      },
      {
        name: 'send_agent_message',
        description: 'Send a message between agents',
        inputSchema: {
          type: 'object',
          properties: {
            from: { type: 'string', description: 'Sender agent ID' },
            to: { 
              oneOf: [
                { type: 'string' },
                { type: 'array', items: { type: 'string' } }
              ],
              description: 'Recipient agent ID(s)'
            },
            content: { type: 'string', description: 'Message content' },
            type: { 
              type: 'string',
              enum: ['query', 'response', 'instruction', 'result', 'error'],
              default: 'query',
              description: 'Message type'
            },
          },
          required: ['from', 'to', 'content'],
        },
      },
      {
        name: 'create_orchestrated_task',
        description: 'Create a task for agents to work on',
        inputSchema: {
          type: 'object',
          properties: {
            description: { type: 'string', description: 'Task description' },
            requiredCapabilities: { 
              type: 'array',
              items: { type: 'string' },
              description: 'Required agent capabilities'
            },
            dependencies: { 
              type: 'array',
              items: { type: 'string' },
              description: 'Dependent task IDs'
            },
          },
          required: ['description'],
        },
      },
      {
        name: 'execute_orchestrated_task',
        description: 'Execute a task with assigned agents',
        inputSchema: {
          type: 'object',
          properties: {
            taskId: { type: 'string', description: 'Task ID to execute' },
          },
          required: ['taskId'],
        },
      },
      {
        name: 'apply_strategy',
        description: 'Apply a pre-defined orchestration strategy',
        inputSchema: {
          type: 'object',
          properties: {
            strategyName: { 
              type: 'string',
              description: 'Name of pre-defined strategy'
            },
            customStrategy: { 
              type: 'object',
              description: 'Custom strategy object'
            },
          },
          required: []
        },
      },
      {
        name: 'get_agent_conversations',
        description: 'Get conversation history between agents',
        inputSchema: {
          type: 'object',
          properties: {
            agentIds: { 
              type: 'array',
              items: { type: 'string' },
              description: 'Agent IDs to filter conversations'
            },
          },
          required: ['agentIds'],
        },
      },
      {
        name: 'get_agent_state',
        description: 'Get current state and memory of an agent',
        inputSchema: {
          type: 'object',
          properties: {
            agentId: { type: 'string', description: 'Agent ID' },
          },
          required: ['agentId'],
        },
      },
      {
        name: 'complete_orchestration_session',
        description: 'Complete the current orchestration session',
        inputSchema: {
          type: 'object',
          properties: {},
          required: []
        },
      },
      {
        name: 'suggest_orchestration_strategy',
        description: 'Get strategy suggestions for a task type',
        inputSchema: {
          type: 'object',
          properties: {
            taskType: { type: 'string', description: 'Type of task (e.g., feature, bug, refactor)' },
          },
          required: ['taskType'],
        },
      },
    ],
    resources: [],
  };
}