import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { CallToolRequestSchema } from '@modelcontextprotocol/sdk/types.js';
import { z } from 'zod';
import { ConfigManager } from '../../config/config-manager.js';
import { ProcessStore } from './process-store.js';
import { ProcessEngine } from './process-engine.js';
import { ProcessBuilder } from './process-builder.js';
import { TriggerSuggestionEngine } from './trigger-suggestion-engine.js';
import { TriggerManager } from './trigger-manager.js';
import { ProcessDefinition } from './types.js';
import { processTemplates, getProcessTemplate } from './templates.js';
import { AgentOrchestrator } from '../agent-orchestration/orchestrator.js';

let store: ProcessStore;
let engine: ProcessEngine;
let builder: ProcessBuilder;
let triggerSuggestionEngine: TriggerSuggestionEngine;
let triggerManager: TriggerManager;
let agentOrchestrator: AgentOrchestrator;

const createProcessSchema = z.object({
  name: z.string(),
  description: z.string().optional(),
  persona: z.string().optional()
});

const executeProcessSchema = z.object({
  processId: z.string(),
  variables: z.record(z.any()).optional()
});

const suggestTriggersSchema = z.object({
  processId: z.string()
});

const processBuilderSchema = z.object({
  action: z.enum(['start', 'continue', 'cancel']),
  sessionId: z.string().optional(),
  response: z.any().optional()
});

export async function setupProcessAutomation(server: Server, configManager: ConfigManager) {
  // Initialize components
  store = new ProcessStore(configManager);
  await store.init();
  
  // Initialize agent orchestrator
  agentOrchestrator = new AgentOrchestrator();
  
  engine = new ProcessEngine(store, agentOrchestrator);
  triggerSuggestionEngine = new TriggerSuggestionEngine(store);
  builder = new ProcessBuilder(store);
  triggerManager = new TriggerManager(engine, store);
  
  // Start trigger manager
  await triggerManager.start();

  // Register 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_process': {
        const validatedArgs = createProcessSchema.parse(args);
        
        const process: ProcessDefinition = {
          id: generateId('process'),
          name: validatedArgs.name,
          description: validatedArgs.description,
          version: '1.0.0',
          persona: validatedArgs.persona as any,
          triggers: [],
          activities: [],
          variables: {},
          metadata: {
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
            executionCount: 0
          }
        };
        
        await store.saveProcess(process);
        
        return {
          content: [
            {
              type: 'text',
              text: `✅ Process "${process.name}" created!\n\nProcess ID: ${process.id}\n\nNext steps:\n1. Use create_process_interactive to define the process through a wizard\n2. Or manually add activities and triggers\n3. Test the process with execute_process`
            }
          ]
        };
      }

      case 'create_process_interactive': {
        const validatedArgs = processBuilderSchema.parse(args);
        
        if (validatedArgs.action === 'start') {
          const session = await builder.startProcessBuilder();
          
          return {
            content: [
              {
                type: 'text',
                text: `🤖 Starting Process Automation Builder\n\n${builder.formatCurrentStep(session.id)}`
              }
            ],
            structured: {
              sessionId: session.id,
              action: 'waiting_for_response'
            }
          };
        }
        
        if (validatedArgs.action === 'continue' && validatedArgs.sessionId) {
          const result = await builder.continueBuilder(
            validatedArgs.sessionId,
            validatedArgs.response
          );
          
          if (!result.valid) {
            return {
              content: [
                {
                  type: 'text',
                  text: `❌ ${result.message}\n\nPlease try again.`
                }
              ],
              structured: {
                sessionId: validatedArgs.sessionId,
                action: 'waiting_for_response',
                error: result.message
              }
            };
          }
          
          if (result.completed && result.process) {
            await store.saveProcess(result.process);
            
            return {
              content: [
                {
                  type: 'text',
                  text: `✅ Process "${result.process.name}" created successfully!\n\n🤖 **Process Details**:\n📋 ID: ${result.process.id}\n👤 Persona: ${result.process.persona || 'general'}\n⚡ Triggers: ${result.process.triggers.length}\n📊 Activities: ${result.process.activities.length}\n\nThe process is now ready to run. You can:\n- Execute it manually with execute_process\n- Wait for scheduled triggers\n- Monitor executions with list_executions`
                }
              ],
              structured: {
                process: result.process,
                completed: true
              }
            };
          }
          
          return {
            content: [
              {
                type: 'text',
                text: builder.formatCurrentStep(validatedArgs.sessionId)
              }
            ],
            structured: {
              sessionId: validatedArgs.sessionId,
              action: 'waiting_for_response'
            }
          };
        }
        
        if (validatedArgs.action === 'cancel' && validatedArgs.sessionId) {
          builder.cancelSession(validatedArgs.sessionId);
          
          return {
            content: [
              {
                type: 'text',
                text: '❌ Process builder cancelled.'
              }
            ]
          };
        }
        
        throw new Error('Invalid action or missing parameters');
      }

      case 'suggest_triggers': {
        const validatedArgs = suggestTriggersSchema.parse(args);
        const process = await store.getProcess(validatedArgs.processId);
        
        if (!process) {
          throw new Error('Process not found');
        }
        
        const suggestions = await triggerSuggestionEngine.suggestTriggers(process);
        
        let response = `🎯 **Trigger Suggestions for "${process.name}"**\n\n`;
        
        for (const [index, suggestion] of suggestions.entries()) {
          const trigger = suggestion.trigger;
          response += `**${index + 1}. ${trigger.name}** (${Math.round(suggestion.confidence * 100)}% confidence)\n`;
          response += `   Type: ${trigger.type}\n`;
          
          if (trigger.type === 'schedule' && trigger.config.cron) {
            response += `   Schedule: ${trigger.config.cron}\n`;
          }
          
          response += `   📝 ${suggestion.reasoning}\n`;
          
          if (suggestion.conflicts && suggestion.conflicts.length > 0) {
            response += `   ⚠️ Conflicts detected:\n`;
            for (const conflict of suggestion.conflicts) {
              response += `      - ${conflict.description}\n`;
              if (conflict.suggestion) {
                response += `        💡 ${conflict.suggestion}\n`;
              }
            }
          }
          
          response += '\n';
        }
        
        return {
          content: [
            {
              type: 'text',
              text: response
            }
          ],
          structured: {
            suggestions
          }
        };
      }

      case 'execute_process': {
        const validatedArgs = executeProcessSchema.parse(args);
        const process = await store.getProcess(validatedArgs.processId);
        
        if (!process) {
          throw new Error('Process not found');
        }
        
        const execution = await engine.executeProcess(
          process,
          'manual',
          validatedArgs.variables
        );
        
        let response = `🚀 Process "${process.name}" execution ${execution.status}\n\n`;
        response += `Execution ID: ${execution.id}\n`;
        response += `Duration: ${execution.duration ? `${execution.duration}ms` : 'In progress'}\n\n`;
        
        if (execution.status === 'completed') {
          response += '✅ All activities completed successfully!\n';
        } else if (execution.status === 'failed') {
          response += `❌ Process failed: ${execution.error?.message}\n`;
        }
        
        return {
          content: [
            {
              type: 'text',
              text: response
            }
          ],
          structured: {
            execution
          }
        };
      }

      case 'list_processes': {
        const processes = await store.getAllProcesses();
        
        if (processes.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: 'No processes found. Create one with create_process or create_process_interactive.'
              }
            ]
          };
        }
        
        let response = `📋 **Available Processes** (${processes.length})\n\n`;
        
        for (const process of processes) {
          const metrics = await store.getProcessMetrics(process.id);
          response += `**${process.name}**\n`;
          response += `  ID: ${process.id}\n`;
          response += `  Persona: ${process.persona || 'general'}\n`;
          response += `  Triggers: ${process.triggers.length}\n`;
          response += `  Activities: ${process.activities.length}\n`;
          response += `  Executions: ${metrics.executionCount}\n`;
          response += `  Success Rate: ${Math.round(metrics.successRate * 100)}%\n\n`;
        }
        
        return {
          content: [
            {
              type: 'text',
              text: response
            }
          ]
        };
      }

      case 'list_executions': {
        const executions = await store.getRecentExecutions(20);
        
        if (executions.length === 0) {
          return {
            content: [
              {
                type: 'text',
                text: 'No executions found. Run a process with execute_process.'
              }
            ]
          };
        }
        
        let response = `📊 **Recent Process Executions**\n\n`;
        
        for (const execution of executions) {
          const process = await store.getProcess(execution.processId);
          response += `**${process?.name || 'Unknown Process'}**\n`;
          response += `  Status: ${getStatusEmoji(execution.status)} ${execution.status}\n`;
          response += `  Started: ${new Date(execution.startedAt).toLocaleString()}\n`;
          
          if (execution.duration) {
            response += `  Duration: ${execution.duration}ms\n`;
          }
          
          if (execution.error) {
            response += `  Error: ${execution.error.message}\n`;
          }
          
          response += '\n';
        }
        
        return {
          content: [
            {
              type: 'text',
              text: response
            }
          ]
        };
      }
      
      case 'process_list_templates': {
        let response = `📋 **Available Process Templates**\n\n`;
        
        for (const template of processTemplates) {
          response += `**${template.name}** (${template.id})\n`;
          response += `  ${template.description}\n`;
          response += `  Category: ${template.category}\n`;
          if (template.persona) {
            response += `  Persona: ${template.persona}\n`;
          }
          response += '\n';
        }
        
        response += `\nUse \`process_create_from_template\` to create a process from any template.`;
        
        return {
          content: [
            {
              type: 'text',
              text: response
            }
          ],
          structured: {
            templates: processTemplates.map(t => ({
              id: t.id,
              name: t.name,
              description: t.description,
              category: t.category,
              persona: t.persona
            }))
          }
        };
      }
      
      case 'process_create_from_template': {
        const { templateId, name, variables } = args as {
          templateId: string;
          name?: string;
          variables?: Record<string, any>;
        };
        
        const template = getProcessTemplate(templateId);
        if (!template) {
          throw new Error(`Template "${templateId}" not found`);
        }
        
        // Replace variables in the template
        const processVars = { ...template.variables, ...variables };
        const processName = name || template.processDefinition.name.replace(/\$\{(\w+)\}/g, 
          (_, key) => processVars[key] || _
        );
        
        const process: ProcessDefinition = {
          id: generateId('process'),
          name: processName,
          description: template.processDefinition.description,
          version: template.processDefinition.version,
          persona: template.persona,
          triggers: template.processDefinition.triggers.map(t => ({
            ...t,
            id: generateId('trigger')
          })),
          activities: template.processDefinition.activities.map(a => ({
            ...a,
            id: generateId('activity')
          })),
          variables: processVars,
          metadata: {
            createdAt: new Date().toISOString(),
            updatedAt: new Date().toISOString(),
            executionCount: 0,
          }
        };
        
        await store.saveProcess(process);
        
        return {
          content: [
            {
              type: 'text',
              text: `✅ Process created from template "${template.name}"!\n\n` +
                   `📋 **Process Details**:\n` +
                   `- Name: ${process.name}\n` +
                   `- ID: ${process.id}\n` +
                   `- Triggers: ${process.triggers.length}\n` +
                   `- Activities: ${process.activities.length}\n\n` +
                   `The process is ready to use!`
            }
          ],
          structured: {
            processId: process.id,
            process
          }
        };
      }

      default:
        return null as any;
    }
  });

  return {
    tools: [
      {
        name: 'create_process',
        description: 'Create a new automation process',
        inputSchema: {
          type: 'object',
          properties: {
            name: {
              type: 'string',
              description: 'Name of the process'
            },
            description: {
              type: 'string',
              description: 'Description of what the process does'
            },
            persona: {
              type: 'string',
              description: 'Target persona (e.g., software-engineer, cto, ceo)'
            }
          },
          required: ['name']
        }
      },
      {
        name: 'create_process_interactive',
        description: 'Create a process through an interactive wizard that helps define activities and suggests triggers',
        inputSchema: {
          type: 'object',
          properties: {
            action: {
              type: 'string',
              enum: ['start', 'continue', 'cancel'],
              description: 'Action to perform'
            },
            sessionId: {
              type: 'string',
              description: 'Session ID for continuing a wizard'
            },
            response: {
              description: 'Response to the current question'
            }
          },
          required: ['action']
        }
      },
      {
        name: 'suggest_triggers',
        description: 'Get AI-powered trigger suggestions for a process',
        inputSchema: {
          type: 'object',
          properties: {
            processId: {
              type: 'string',
              description: 'ID of the process'
            }
          },
          required: ['processId']
        }
      },
      {
        name: 'execute_process',
        description: 'Execute a process manually',
        inputSchema: {
          type: 'object',
          properties: {
            processId: {
              type: 'string',
              description: 'ID of the process to execute'
            },
            variables: {
              type: 'object',
              description: 'Initial variables for the process'
            }
          },
          required: ['processId']
        }
      },
      {
        name: 'list_processes',
        description: 'List all available processes',
        inputSchema: {
          type: 'object',
          properties: {},
          required: []
        }
      },
      {
        name: 'list_executions',
        description: 'List recent process executions',
        inputSchema: {
          type: 'object',
          properties: {},
          required: []
        }
      },
      {
        name: 'process_list_templates',
        description: 'List available process templates',
        inputSchema: {
          type: 'object',
          properties: {},
          required: []
        }
      },
      {
        name: 'process_create_from_template',
        description: 'Create a process from a pre-built template',
        inputSchema: {
          type: 'object',
          properties: {
            templateId: {
              type: 'string',
              description: 'ID of the template to use'
            },
            name: {
              type: 'string',
              description: 'Custom name for the process (optional)'
            },
            variables: {
              type: 'object',
              description: 'Variables to customize the template'
            }
          },
          required: ['templateId']
        }
      }
    ],
    resources: []
  };
}

function generateId(prefix: string): string {
  return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
}

function getStatusEmoji(status: string): string {
  const emojis: Record<string, string> = {
    pending: '⏳',
    running: '🔄',
    waiting: '⏸️',
    paused: '⏸️',
    completed: '✅',
    failed: '❌',
    cancelled: '🚫'
  };
  
  return emojis[status] || '❓';
}