#!/usr/bin/env node

/**
 * BZZZ SDK JavaScript Collaborative Agent Example
 * ==============================================
 * 
 * Demonstrates building a collaborative agent using BZZZ SDK for Node.js.
 * Shows real-time coordination, decision sharing, and event-driven workflows.
 */

const { BzzzClient, EventType, DecisionType } = require('bzzz-sdk');
const EventEmitter = require('events');

class CollaborativeAgent extends EventEmitter {
    constructor(config) {
        super();
        this.config = {
            endpoint: 'http://localhost:8080',
            role: 'frontend_developer',
            agentId: 'collaborative-agent-js',
            ...config
        };
        
        this.client = null;
        this.isRunning = false;
        this.stats = {
            eventsProcessed: 0,
            decisionsPublished: 0,
            collaborationsStarted: 0,
            tasksCompleted: 0
        };
        
        this.collaborationQueue = [];
        this.activeCollaborations = new Map();
    }
    
    async initialize() {
        console.log('🚀 Initializing BZZZ Collaborative Agent');
        
        try {
            // Create BZZZ client
            this.client = new BzzzClient({
                endpoint: this.config.endpoint,
                role: this.config.role,
                agentId: this.config.agentId,
                timeout: 30000,
                retryCount: 3
            });
            
            // Test connection
            const status = await this.client.getStatus();
            console.log(`✅ Connected as ${status.agentId} (${status.role})`);
            console.log(`   Node ID: ${status.nodeId}`);
            console.log(`   Authority: ${status.authorityLevel}`);
            console.log(`   Can decrypt: ${status.canDecrypt.join(', ')}`);
            
            return true;
            
        } catch (error) {
            console.error('❌ Failed to initialize BZZZ client:', error.message);
            return false;
        }
    }
    
    async start() {
        console.log('🎯 Starting collaborative agent...');
        this.isRunning = true;
        
        // Set up event listeners
        await this.setupEventListeners();
        
        // Start background tasks
        this.startBackgroundTasks();
        
        // Announce availability
        await this.announceAvailability();
        
        console.log('✅ Collaborative agent is running');
        console.log('   Use Ctrl+C to stop');
    }
    
    async setupEventListeners() {
        console.log('🎧 Setting up event listeners...');
        
        try {
            // System events
            const eventStream = this.client.subscribeEvents();
            eventStream.on('event', (event) => this.handleSystemEvent(event));
            eventStream.on('error', (error) => console.error('Event stream error:', error));
            
            // Decision stream for collaboration opportunities
            const decisionStream = this.client.decisions.streamDecisions({
                contentType: 'decision',
                // Listen to all roles for collaboration opportunities
            });
            decisionStream.on('decision', (decision) => this.handleDecision(decision));
            decisionStream.on('error', (error) => console.error('Decision stream error:', error));
            
            console.log('✅ Event listeners configured');
            
        } catch (error) {
            console.error('❌ Failed to setup event listeners:', error.message);
        }
    }
    
    startBackgroundTasks() {
        // Process collaboration queue
        setInterval(() => this.processCollaborationQueue(), 5000);
        
        // Publish status updates
        setInterval(() => this.publishStatusUpdate(), 30000);
        
        // Clean up old collaborations
        setInterval(() => this.cleanupCollaborations(), 60000);
        
        // Simulate autonomous work
        setInterval(() => this.simulateAutonomousWork(), 45000);
    }
    
    async handleSystemEvent(event) {
        this.stats.eventsProcessed++;
        
        switch (event.type) {
            case EventType.DECISION_PUBLISHED:
                await this.handleDecisionPublished(event);
                break;
                
            case EventType.PEER_CONNECTED:
                await this.handlePeerConnected(event);
                break;
                
            case EventType.ADMIN_CHANGED:
                console.log(`👑 Admin changed: ${event.data.oldAdmin} → ${event.data.newAdmin}`);
                break;
                
            default:
                console.log(`📡 System event: ${event.type}`);
        }
    }
    
    async handleDecisionPublished(event) {
        const { address, creatorRole, contentType } = event.data;
        
        // Check if this decision needs collaboration
        if (await this.needsCollaboration(event.data)) {
            console.log(`🤝 Collaboration opportunity: ${address}`);
            this.collaborationQueue.push({
                address,
                creatorRole,
                contentType,
                timestamp: new Date(),
                priority: this.calculatePriority(event.data)
            });
        }
    }
    
    async handlePeerConnected(event) {
        const { agentId, role } = event.data;
        console.log(`🌐 New peer connected: ${agentId} (${role})`);
        
        // Check if this peer can help with pending collaborations
        await this.checkCollaborationOpportunities(role);
    }
    
    async handleDecision(decision) {
        console.log(`📋 Decision received: ${decision.task} from ${decision.role}`);
        
        // Analyze decision for collaboration potential
        if (this.canContribute(decision)) {
            await this.offerCollaboration(decision);
        }
    }
    
    async needsCollaboration(eventData) {
        // Simple heuristic: collaboration needed for architectural decisions
        // or when content mentions frontend/UI concerns
        return eventData.contentType === 'architectural' ||
               (eventData.summary && eventData.summary.toLowerCase().includes('frontend')) ||
               (eventData.summary && eventData.summary.toLowerCase().includes('ui'));
    }
    
    calculatePriority(eventData) {
        let priority = 1;
        
        if (eventData.contentType === 'architectural') priority += 2;
        if (eventData.creatorRole === 'senior_software_architect') priority += 1;
        if (eventData.summary && eventData.summary.includes('urgent')) priority += 3;
        
        return Math.min(priority, 5); // Cap at 5
    }
    
    canContribute(decision) {
        const frontendKeywords = ['react', 'vue', 'angular', 'frontend', 'ui', 'css', 'javascript'];
        const content = decision.decision.toLowerCase();
        
        return frontendKeywords.some(keyword => content.includes(keyword));
    }
    
    async processCollaborationQueue() {
        if (this.collaborationQueue.length === 0) return;
        
        // Sort by priority and age
        this.collaborationQueue.sort((a, b) => {
            const priorityDiff = b.priority - a.priority;
            if (priorityDiff !== 0) return priorityDiff;
            return a.timestamp - b.timestamp; // Earlier timestamp = higher priority
        });
        
        // Process top collaboration
        const collaboration = this.collaborationQueue.shift();
        await this.startCollaboration(collaboration);
    }
    
    async startCollaboration(collaboration) {
        console.log(`🤝 Starting collaboration: ${collaboration.address}`);
        this.stats.collaborationsStarted++;
        
        try {
            // Get the original decision content
            const content = await this.client.decisions.getContent(collaboration.address);
            
            // Analyze and provide frontend perspective
            const frontendAnalysis = await this.analyzeFrontendImpact(content);
            
            // Publish collaborative response
            await this.client.decisions.publishArchitectural({
                task: `frontend_analysis_${collaboration.address.split('/').pop()}`,
                decision: `Frontend impact analysis for: ${content.task}`,
                rationale: frontendAnalysis.rationale,
                alternatives: frontendAnalysis.alternatives,
                implications: frontendAnalysis.implications,
                nextSteps: frontendAnalysis.nextSteps
            });
            
            console.log(`✅ Published frontend analysis for ${collaboration.address}`);
            this.stats.decisionsPublished++;
            
            // Track active collaboration
            this.activeCollaborations.set(collaboration.address, {
                startTime: new Date(),
                status: 'active',
                contributions: 1
            });
            
        } catch (error) {
            console.error(`❌ Failed to start collaboration: ${error.message}`);
        }
    }
    
    async analyzeFrontendImpact(content) {
        // Simulate frontend analysis based on the content
        const analysis = {
            rationale: "Frontend perspective analysis",
            alternatives: [],
            implications: [],
            nextSteps: []
        };
        
        const contentLower = content.decision.toLowerCase();
        
        if (contentLower.includes('api') || contentLower.includes('service')) {
            analysis.rationale = "API changes will require frontend integration updates";
            analysis.implications.push("Frontend API client needs updating");
            analysis.implications.push("UI loading states may need adjustment");
            analysis.nextSteps.push("Update API client interfaces");
            analysis.nextSteps.push("Test error handling in UI");
        }
        
        if (contentLower.includes('database') || contentLower.includes('schema')) {
            analysis.implications.push("Data models in frontend may need updates");
            analysis.nextSteps.push("Review frontend data validation");
            analysis.nextSteps.push("Update TypeScript interfaces if applicable");
        }
        
        if (contentLower.includes('security') || contentLower.includes('auth')) {
            analysis.implications.push("Authentication flow in UI requires review");
            analysis.nextSteps.push("Update login/logout components");
            analysis.nextSteps.push("Review JWT handling in frontend");
        }
        
        // Add some alternatives
        analysis.alternatives.push("Progressive rollout with feature flags");
        analysis.alternatives.push("A/B testing for UI changes");
        
        return analysis;
    }
    
    async offerCollaboration(decision) {
        console.log(`💡 Offering collaboration on: ${decision.task}`);
        
        // Create a collaboration offer
        await this.client.decisions.publishCode({
            task: `collaboration_offer_${Date.now()}`,
            decision: `Frontend developer available for collaboration on: ${decision.task}`,
            filesModified: [], // No files yet
            linesChanged: 0,
            testResults: {
                passed: 0,
                failed: 0,
                coverage: 0
            },
            language: 'javascript'
        });
    }
    
    async checkCollaborationOpportunities(peerRole) {
        // If a senior architect joins, they might want to collaborate
        if (peerRole === 'senior_software_architect' && this.collaborationQueue.length > 0) {
            console.log(`🎯 Senior architect available - prioritizing collaborations`);
            // Boost priority of architectural collaborations
            this.collaborationQueue.forEach(collab => {
                if (collab.contentType === 'architectural') {
                    collab.priority = Math.min(collab.priority + 1, 5);
                }
            });
        }
    }
    
    async simulateAutonomousWork() {
        if (!this.isRunning) return;
        
        console.log('🔄 Performing autonomous frontend work...');
        
        const tasks = [
            'optimize_bundle_size',
            'update_component_library',
            'improve_accessibility',
            'refactor_styling',
            'add_responsive_design'
        ];
        
        const randomTask = tasks[Math.floor(Math.random() * tasks.length)];
        
        try {
            await this.client.decisions.publishCode({
                task: randomTask,
                decision: `Autonomous frontend improvement: ${randomTask.replace(/_/g, ' ')}`,
                filesModified: [
                    `src/components/${randomTask}.js`,
                    `src/styles/${randomTask}.css`,
                    `tests/${randomTask}.test.js`
                ],
                linesChanged: Math.floor(Math.random() * 100) + 20,
                testResults: {
                    passed: Math.floor(Math.random() * 10) + 5,
                    failed: Math.random() < 0.1 ? 1 : 0,
                    coverage: Math.random() * 20 + 80
                },
                language: 'javascript'
            });
            
            this.stats.tasksCompleted++;
            console.log(`✅ Completed autonomous task: ${randomTask}`);
            
        } catch (error) {
            console.error(`❌ Failed autonomous task: ${error.message}`);
        }
    }
    
    async publishStatusUpdate() {
        if (!this.isRunning) return;
        
        try {
            await this.client.decisions.publishSystemStatus({
                status: "Collaborative agent operational",
                metrics: {
                    eventsProcessed: this.stats.eventsProcessed,
                    decisionsPublished: this.stats.decisionsPublished,
                    collaborationsStarted: this.stats.collaborationsStarted,
                    tasksCompleted: this.stats.tasksCompleted,
                    activeCollaborations: this.activeCollaborations.size,
                    queueLength: this.collaborationQueue.length
                },
                healthChecks: {
                    client_connected: !!this.client,
                    event_streaming: this.isRunning,
                    collaboration_system: this.collaborationQueue.length < 10
                }
            });
            
        } catch (error) {
            console.error(`❌ Failed to publish status: ${error.message}`);
        }
    }
    
    async announceAvailability() {
        try {
            await this.client.decisions.publishArchitectural({
                task: 'agent_availability',
                decision: 'Collaborative frontend agent is now available',
                rationale: 'Providing frontend expertise and collaboration capabilities',
                implications: [
                    'Can analyze frontend impact of backend changes',
                    'Available for UI/UX collaboration',
                    'Monitors for frontend-related decisions'
                ],
                nextSteps: [
                    'Listening for collaboration opportunities',
                    'Ready to provide frontend perspective',
                    'Autonomous frontend improvement tasks active'
                ]
            });
            
            console.log('📢 Announced availability to BZZZ network');
            
        } catch (error) {
            console.error(`❌ Failed to announce availability: ${error.message}`);
        }
    }
    
    async cleanupCollaborations() {
        const now = new Date();
        const oneHour = 60 * 60 * 1000;
        
        for (const [address, collaboration] of this.activeCollaborations) {
            if (now - collaboration.startTime > oneHour) {
                console.log(`🧹 Cleaning up old collaboration: ${address}`);
                this.activeCollaborations.delete(address);
            }
        }
        
        // Also clean up old queue items
        this.collaborationQueue = this.collaborationQueue.filter(
            collab => now - collab.timestamp < oneHour
        );
    }
    
    printStats() {
        console.log('\n📊 Agent Statistics:');
        console.log(`   Events processed: ${this.stats.eventsProcessed}`);
        console.log(`   Decisions published: ${this.stats.decisionsPublished}`);
        console.log(`   Collaborations started: ${this.stats.collaborationsStarted}`);
        console.log(`   Tasks completed: ${this.stats.tasksCompleted}`);
        console.log(`   Active collaborations: ${this.activeCollaborations.size}`);
        console.log(`   Queue length: ${this.collaborationQueue.length}`);
    }
    
    async stop() {
        console.log('\n🛑 Stopping collaborative agent...');
        this.isRunning = false;
        
        try {
            // Publish shutdown notice
            await this.client.decisions.publishSystemStatus({
                status: "Collaborative agent shutting down",
                metrics: this.stats,
                healthChecks: {
                    client_connected: false,
                    event_streaming: false,
                    collaboration_system: false
                }
            });
            
            // Close client connection
            if (this.client) {
                await this.client.close();
            }
            
            this.printStats();
            console.log('✅ Collaborative agent stopped gracefully');
            
        } catch (error) {
            console.error(`❌ Error during shutdown: ${error.message}`);
        }
    }
}

// Main execution
async function main() {
    const agent = new CollaborativeAgent({
        role: 'frontend_developer',
        agentId: 'collaborative-frontend-js'
    });
    
    // Handle graceful shutdown
    process.on('SIGINT', async () => {
        console.log('\n🔄 Received shutdown signal...');
        await agent.stop();
        process.exit(0);
    });
    
    try {
        // Initialize and start the agent
        if (await agent.initialize()) {
            await agent.start();
            
            // Keep running until stopped
            process.on('SIGTERM', () => {
                agent.stop().then(() => process.exit(0));
            });
            
        } else {
            console.error('❌ Failed to initialize collaborative agent');
            process.exit(1);
        }
        
    } catch (error) {
        console.error('❌ Unexpected error:', error.message);
        process.exit(1);
    }
}

// Export for use as module
module.exports = CollaborativeAgent;

// Run if called directly
if (require.main === module) {
    main().catch(error => {
        console.error('❌ Fatal error:', error);
        process.exit(1);
    });
}