/**
 * Complete Multi-User System Test
 * Tests the full flow: Chrome Extension → Remote Server → LiveKit Agent → Voice Commands → Chrome Extension
 */

import WebSocket from 'ws';

const SERVER_URL = 'ws://localhost:3001/chrome';
const NUM_USERS = 2;

class TestChromeUser {
  constructor(userId) {
    this.userId = userId;
    this.ws = null;
    this.sessionInfo = null;
    this.connected = false;
    this.liveKitAgentStarted = false;
    this.receivedMessages = [];
  }

  async connect() {
    return new Promise((resolve, reject) => {
      console.log(`\n🔌 [User ${this.userId}] Connecting Chrome extension...`);
      
      this.ws = new WebSocket(SERVER_URL);

      this.ws.on('open', () => {
        console.log(`✅ [User ${this.userId}] Chrome extension connected`);
        this.connected = true;

        // Generate unique user ID for this Chrome extension
        const chromeUserId = `user_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;

        // Send connection info with user ID (simulating Chrome extension)
        const connectionInfo = {
          type: 'connection_info',
          userId: chromeUserId, // Chrome extension provides its own user ID
          userAgent: `TestChromeUser-${this.userId}`,
          timestamp: Date.now(),
          extensionId: `test-extension-${this.userId}`
        };

        console.log(`📤 [User ${this.userId}] Sending connection info with user ID: ${chromeUserId}`);
        this.ws.send(JSON.stringify(connectionInfo));
      });

      this.ws.on('message', (data) => {
        try {
          const message = JSON.parse(data.toString());
          this.receivedMessages.push(message);
          
          console.log(`📨 [User ${this.userId}] Received message:`, message);

          if (message.type === 'session_info') {
            this.sessionInfo = message.sessionInfo;
            console.log(`🎯 [User ${this.userId}] Session established:`, this.sessionInfo);
            
            // Check if LiveKit agent should be started
            setTimeout(() => {
              this.checkLiveKitAgent();
            }, 2000);
            
            resolve();
          }

          // Handle tool calls from LiveKit agent
          if (message.action === 'callTool') {
            console.log(`🔧 [User ${this.userId}] Received tool call from LiveKit agent:`, message.params);
            
            // Simulate Chrome extension response
            const response = {
              id: message.id,
              success: true,
              result: `Tool ${message.params.name} executed successfully for user ${this.userId}`,
              timestamp: Date.now()
            };
            
            console.log(`📤 [User ${this.userId}] Sending tool response:`, response);
            this.ws.send(JSON.stringify(response));
          }

        } catch (error) {
          console.error(`❌ [User ${this.userId}] Error parsing message:`, error);
        }
      });

      this.ws.on('close', () => {
        console.log(`🔌 [User ${this.userId}] Chrome extension disconnected`);
        this.connected = false;
      });

      this.ws.on('error', (error) => {
        console.error(`❌ [User ${this.userId}] WebSocket error:`, error);
        reject(error);
      });

      // Timeout after 10 seconds
      setTimeout(() => {
        if (!this.sessionInfo) {
          reject(new Error(`[User ${this.userId}] Timeout waiting for session info`));
        }
      }, 10000);
    });
  }

  checkLiveKitAgent() {
    if (this.sessionInfo) {
      console.log(`🤖 [User ${this.userId}] LiveKit agent should be running for room: mcp-chrome-user-${this.sessionInfo.userId}`);
      this.liveKitAgentStarted = true;
    }
  }

  async sendTestVoiceCommand() {
    if (!this.connected || !this.ws) {
      throw new Error(`[User ${this.userId}] Not connected`);
    }

    // Simulate a voice command that would come from LiveKit agent
    const voiceCommand = {
      action: 'callTool',
      params: {
        name: 'chrome_navigate',
        arguments: { 
          url: `https://example.com?user=${this.userId}&test=voice_command`,
          userContext: this.sessionInfo?.userId
        }
      },
      id: `voice_${this.userId}_${Date.now()}`,
      source: 'livekit_agent'
    };

    console.log(`🎤 [User ${this.userId}] Simulating voice command:`, voiceCommand);
    this.ws.send(JSON.stringify(voiceCommand));
  }

  getStatus() {
    return {
      userId: this.userId,
      connected: this.connected,
      sessionInfo: this.sessionInfo,
      liveKitAgentStarted: this.liveKitAgentStarted,
      messagesReceived: this.receivedMessages.length
    };
  }

  disconnect() {
    if (this.ws) {
      console.log(`👋 [User ${this.userId}] Disconnecting Chrome extension`);
      this.ws.close();
    }
  }
}

async function testCompleteMultiUserSystem() {
  console.log('🚀 Starting Complete Multi-User System Test...\n');
  console.log('This test verifies:');
  console.log('1. Chrome Extension User ID Generation');
  console.log('2. Remote Server Session Management');
  console.log('3. Automatic LiveKit Agent Spawning');
  console.log('4. User ID Consistency Across Components');
  console.log('5. Voice Command Routing\n');

  const users = [];

  try {
    // Step 1: Connect multiple Chrome extension users
    console.log('📋 STEP 1: Connecting Chrome Extension Users');
    console.log('=' .repeat(50));

    for (let i = 1; i <= NUM_USERS; i++) {
      const user = new TestChromeUser(i);
      users.push(user);
      
      console.log(`\n🔄 Connecting User ${i}...`);
      await user.connect();
      console.log(`✅ User ${i} connected successfully`);
      
      // Wait a bit between connections
      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    // Step 2: Verify session isolation
    console.log('\n📋 STEP 2: Verifying Session Isolation');
    console.log('=' .repeat(50));

    users.forEach(user => {
      const status = user.getStatus();
      console.log(`👤 User ${status.userId}:`);
      console.log(`   Session ID: ${status.sessionInfo?.sessionId}`);
      console.log(`   User ID: ${status.sessionInfo?.userId}`);
      console.log(`   LiveKit Agent: ${status.liveKitAgentStarted ? '✅ Started' : '❌ Not Started'}`);
    });

    // Step 3: Test voice command routing
    console.log('\n📋 STEP 3: Testing Voice Command Routing');
    console.log('=' .repeat(50));

    for (const user of users) {
      console.log(`\n🎤 Testing voice command for User ${user.userId}...`);
      await user.sendTestVoiceCommand();
      
      // Wait for response
      await new Promise(resolve => setTimeout(resolve, 2000));
    }

    // Step 4: Verify user isolation
    console.log('\n📋 STEP 4: Verifying User Isolation');
    console.log('=' .repeat(50));

    users.forEach(user => {
      const status = user.getStatus();
      console.log(`👤 User ${status.userId}: Received ${status.messagesReceived} messages`);
    });

    console.log('\n✅ Multi-User System Test Completed Successfully!');
    console.log('\n📊 SUMMARY:');
    console.log(`   Total Users: ${users.length}`);
    console.log(`   All Connected: ${users.every(u => u.connected)}`);
    console.log(`   All Have Sessions: ${users.every(u => u.sessionInfo)}`);
    console.log(`   All Have LiveKit Agents: ${users.every(u => u.liveKitAgentStarted)}`);

  } catch (error) {
    console.error('❌ Test failed:', error);
  } finally {
    // Cleanup
    console.log('\n🧹 Cleaning up connections...');
    users.forEach(user => user.disconnect());
    
    setTimeout(() => {
      console.log('✅ Test cleanup completed');
      process.exit(0);
    }, 2000);
  }
}

// Run the test
testCompleteMultiUserSystem().catch(console.error);
