export class ActivityExecutor {
    processEngine; // Avoid circular dependency typing
    server;
    agentOrchestrator;
    constructor(processEngine, agentOrchestrator) {
        this.processEngine = processEngine;
        this.agentOrchestrator = agentOrchestrator;
    }
    setServer(server) {
        this.server = server;
    }
    async execute(activity, inputs, execution) {
        switch (activity.type) {
            case 'tool':
                return this.executeToolActivity(activity, inputs);
            case 'human':
                return this.executeHumanActivity(activity, inputs, execution);
            case 'agent':
                return this.executeAgentActivity(activity, inputs);
            case 'conditional':
                return this.executeConditionalActivity(activity, inputs, execution);
            case 'loop':
                return this.executeLoopActivity(activity, inputs, execution);
            case 'parallel':
                return this.executeParallelActivity(activity, inputs, execution);
            case 'external':
                return this.executeExternalActivity(activity, inputs);
            default:
                throw new Error(`Unknown activity type: ${activity.type}`);
        }
    }
    async executeToolActivity(activity, inputs) {
        const config = activity.config;
        if (!config.toolName) {
            throw new Error('Tool activity missing toolName');
        }
        if (!this.server) {
            throw new Error('Server not initialized for tool execution');
        }
        // In a real implementation, this would call the actual MCP tool
        // For now, we'll simulate the response
        console.log(`Executing tool: ${config.toolName} with args:`, config.toolArgs);
        // Simulate tool execution
        return {
            success: true,
            toolName: config.toolName,
            executedAt: new Date().toISOString(),
            // Tool-specific outputs would go here
        };
    }
    async executeHumanActivity(activity, inputs, execution) {
        const config = activity.config;
        // Change execution status to waiting
        execution.status = 'waiting';
        this.processEngine.emit('execution:waiting', { execution, activity });
        // In a real implementation, this would:
        // 1. Create a task/notification for the assigned users
        // 2. Wait for user response
        // 3. Validate the response
        // 4. Return the user's input
        console.log(`Waiting for human input: ${activity.name}`);
        console.log(`Assigned to: ${config.assignTo?.join(', ')}`);
        console.log(`Prompt: ${config.prompt}`);
        // For now, simulate immediate response
        await new Promise(resolve => setTimeout(resolve, 1000));
        execution.status = 'running';
        return {
            approved: true,
            approvedBy: config.assignTo?.[0] || 'system',
            approvedAt: new Date().toISOString(),
            comments: 'Simulated approval'
        };
    }
    async executeAgentActivity(activity, inputs) {
        const config = activity.config;
        if (!config.agentType) {
            throw new Error('Agent activity missing agentType in config');
        }
        if (!config.agentTask) {
            throw new Error('Agent activity missing agentTask in config');
        }
        try {
            // 1. Create an orchestration session for this activity
            const sessionName = `Process Activity: ${activity.name || 'Agent Task'}`;
            const session = this.agentOrchestrator.createSession(sessionName, config.agentTask);
            // 2. Create agent with appropriate template
            const agentRole = this.mapAgentTypeToRole(config.agentType);
            const template = this.getAgentTemplate(agentRole);
            const agent = this.agentOrchestrator.createAgent(template, `${config.agentType}-${Date.now()}`);
            // 3. Create a task for the agent
            const capabilities = config.agentCapabilities || this.getDefaultCapabilities(agentRole);
            const task = this.agentOrchestrator.createTask(config.agentTask, capabilities, [] // no dependencies for now
            );
            // 4. Execute the task with the agent
            const taskResult = await this.agentOrchestrator.executeTask(task.id);
            // 5. Complete the session
            this.agentOrchestrator.completeSession();
            // 6. Return real agent results
            return {
                agentType: config.agentType,
                agentId: agent.id,
                taskId: task.id,
                taskCompleted: taskResult.success,
                results: taskResult.output || {},
                artifacts: taskResult.artifacts || [],
                duration: taskResult.performance?.duration || 0,
                executionSummary: `Agent ${agent.name} completed task: ${config.agentTask}`,
                sessionId: session.id
            };
        }
        catch (error) {
            console.error(`Agent activity failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
            // Fallback to simulation if orchestration fails
            console.log(`Falling back to simulated execution for agent: ${config.agentType}`);
            console.log(`Task: ${config.agentTask}`);
            return {
                agentType: config.agentType,
                agentId: 'fallback-agent',
                taskId: 'fallback-task',
                taskCompleted: false,
                error: error instanceof Error ? error.message : 'Unknown error',
                results: {
                    analysis: 'Agent execution failed - simulated fallback',
                    recommendations: ['Check agent orchestration configuration']
                },
                artifacts: [],
                duration: 0,
                executionSummary: `Fallback execution for ${config.agentType}: ${config.agentTask}`
            };
        }
    }
    mapAgentTypeToRole(agentType) {
        const roleMap = {
            'researcher': 'researcher',
            'coder': 'coder',
            'reviewer': 'reviewer',
            'tester': 'tester',
            'documenter': 'documenter',
            'analyzer': 'researcher', // Analyzer maps to researcher role
            'developer': 'coder',
            'qa': 'tester',
            'coordinator': 'primary'
        };
        return roleMap[agentType.toLowerCase()] || 'primary';
    }
    getAgentTemplate(role) {
        const templates = {
            primary: {
                name: 'Primary Coordinator',
                role: 'primary',
                systemPrompt: 'You are the primary coordinator. Manage the overall task and delegate to specialists.',
                capabilities: ['coordination', 'planning', 'delegation', 'summary'],
            },
            researcher: {
                name: 'Research Specialist',
                role: 'researcher',
                systemPrompt: 'You are a research specialist. Find information and analyze requirements.',
                capabilities: ['research', 'analysis', 'documentation', 'search'],
            },
            coder: {
                name: 'Code Developer',
                role: 'coder',
                systemPrompt: 'You are a code developer. Write clean, efficient, and tested code.',
                capabilities: ['coding', 'debugging', 'refactoring', 'optimization'],
            },
            reviewer: {
                name: 'Code Reviewer',
                role: 'reviewer',
                systemPrompt: 'You are a code reviewer. Examine code for quality, security, and best practices.',
                capabilities: ['review', 'quality-assurance', 'security', 'best-practices'],
            },
            tester: {
                name: 'Quality Tester',
                role: 'tester',
                systemPrompt: 'You are a quality tester. Design and execute tests to ensure software quality.',
                capabilities: ['testing', 'automation', 'quality-assurance', 'bug-detection'],
            },
            documenter: {
                name: 'Documentation Specialist',
                role: 'documenter',
                systemPrompt: 'You are a documentation specialist. Create clear, comprehensive documentation.',
                capabilities: ['documentation', 'writing', 'knowledge-management', 'tutorials'],
            }
        };
        return templates[role];
    }
    getDefaultCapabilities(role) {
        const capabilityMap = {
            primary: ['coordination', 'planning', 'delegation'],
            researcher: ['research', 'analysis', 'documentation'],
            coder: ['coding', 'debugging', 'refactoring'],
            reviewer: ['review', 'quality-assurance', 'security'],
            tester: ['testing', 'automation', 'quality-assurance'],
            documenter: ['documentation', 'writing', 'knowledge-management'],
            custom: ['general', 'flexible', 'adaptable']
        };
        return capabilityMap[role] || ['general'];
    }
    async executeConditionalActivity(activity, inputs, execution) {
        const config = activity.config;
        if (!config.conditions) {
            throw new Error('Conditional activity missing conditions');
        }
        // Evaluate each condition
        for (const branch of config.conditions) {
            if (await this.evaluateCondition(branch.condition, execution.variables)) {
                // Execute activities in this branch
                const results = {};
                for (const branchActivity of branch.activities) {
                    const result = await this.execute(branchActivity, inputs, execution);
                    Object.assign(results, result);
                }
                return results;
            }
        }
        // Execute default branch if no conditions matched
        if (config.defaultBranch) {
            const results = {};
            for (const defaultActivity of config.defaultBranch) {
                const result = await this.execute(defaultActivity, inputs, execution);
                Object.assign(results, result);
            }
            return results;
        }
        return { conditionMatched: false };
    }
    async executeLoopActivity(activity, inputs, execution) {
        const config = activity.config;
        if (!config.collection || !config.activities) {
            throw new Error('Loop activity missing collection or activities');
        }
        // Get collection from variables
        const collection = execution.variables[config.collection] || [];
        const itemVariable = config.itemVariable || 'item';
        const maxIterations = config.maxIterations || 1000;
        const results = [];
        let iteration = 0;
        for (const item of collection) {
            if (iteration >= maxIterations) {
                console.warn(`Loop reached max iterations (${maxIterations})`);
                break;
            }
            // Set loop variable
            execution.variables[itemVariable] = item;
            execution.variables[`${itemVariable}Index`] = iteration;
            // Execute loop activities
            const iterationResults = {};
            for (const loopActivity of config.activities) {
                const result = await this.execute(loopActivity, inputs, execution);
                Object.assign(iterationResults, result);
            }
            results.push(iterationResults);
            iteration++;
        }
        // Clean up loop variables
        delete execution.variables[itemVariable];
        delete execution.variables[`${itemVariable}Index`];
        return {
            loopCompleted: true,
            iterations: iteration,
            results
        };
    }
    async executeParallelActivity(activity, inputs, execution) {
        const config = activity.config;
        if (!config.branches) {
            throw new Error('Parallel activity missing branches');
        }
        const waitForAll = config.waitForAll !== false; // Default true
        // Execute all branches in parallel
        const branchPromises = config.branches.map(async (branch, index) => {
            const branchResults = {};
            try {
                for (const branchActivity of branch) {
                    const result = await this.execute(branchActivity, inputs, execution);
                    Object.assign(branchResults, result);
                }
                return { success: true, results: branchResults, branchIndex: index };
            }
            catch (error) {
                return {
                    success: false,
                    error: error instanceof Error ? error.message : String(error),
                    branchIndex: index
                };
            }
        });
        if (waitForAll) {
            // Wait for all branches to complete
            const branchResults = await Promise.all(branchPromises);
            return {
                parallelCompleted: true,
                branches: branchResults
            };
        }
        else {
            // Return first completed branch
            const firstResult = await Promise.race(branchPromises);
            return {
                parallelCompleted: true,
                firstCompleted: firstResult
            };
        }
    }
    async executeExternalActivity(activity, inputs) {
        const config = activity.config;
        if (!config.url) {
            throw new Error('External activity missing URL');
        }
        // In a real implementation, this would make an HTTP request
        console.log(`Making external request to: ${config.url}`);
        console.log(`Method: ${config.method || 'GET'}`);
        // Simulate external call
        await new Promise(resolve => setTimeout(resolve, 1500));
        return {
            status: 200,
            response: {
                message: 'External call completed',
                data: { example: 'response data' }
            }
        };
    }
    async evaluateCondition(condition, variables) {
        // In a real implementation, use a proper expression evaluator
        // For now, simple string matching
        console.log(`Evaluating condition: ${condition}`);
        // Handle simple equality checks
        const match = condition.match(/(\w+)\s*===?\s*(.+)/);
        if (match) {
            const [, varName, value] = match;
            const varValue = variables[varName];
            const expectedValue = value.replace(/['"]/g, '').trim();
            return String(varValue) === expectedValue;
        }
        // Default to true for demo
        return true;
    }
}
//# sourceMappingURL=activity-executor.js.map