/**
 * Test script for multi-user session management
 * This script simulates multiple Chrome extension connections to test session isolation
 */

import WebSocket from 'ws';

const SERVER_URL = 'ws://localhost:3001/chrome';
const NUM_CONNECTIONS = 3;

class TestConnection {
  constructor(id) {
    this.id = id;
    this.ws = null;
    this.sessionInfo = null;
    this.connected = false;
  }

  async connect() {
    return new Promise((resolve, reject) => {
      console.log(`🔌 Connection ${this.id}: Connecting to ${SERVER_URL}`);
      
      this.ws = new WebSocket(SERVER_URL);

      this.ws.on('open', () => {
        console.log(`✅ Connection ${this.id}: Connected`);
        this.connected = true;

        // Send connection info
        const connectionInfo = {
          type: 'connection_info',
          userAgent: `TestAgent-${this.id}`,
          timestamp: Date.now(),
          extensionId: `test-extension-${this.id}`
        };

        this.ws.send(JSON.stringify(connectionInfo));
      });

      this.ws.on('message', (data) => {
        try {
          const message = JSON.parse(data.toString());
          
          if (message.type === 'session_info') {
            this.sessionInfo = message.sessionInfo;
            console.log(`📋 Connection ${this.id}: Received session info:`, this.sessionInfo);
            resolve();
          } else {
            console.log(`📨 Connection ${this.id}: Received message:`, message);
          }
        } catch (error) {
          console.error(`❌ Connection ${this.id}: Error parsing message:`, error);
        }
      });

      this.ws.on('close', () => {
        console.log(`🔌 Connection ${this.id}: Disconnected`);
        this.connected = false;
      });

      this.ws.on('error', (error) => {
        console.error(`❌ Connection ${this.id}: Error:`, error);
        reject(error);
      });

      // Timeout after 5 seconds
      setTimeout(() => {
        if (!this.sessionInfo) {
          reject(new Error(`Connection ${this.id}: Timeout waiting for session info`));
        }
      }, 5000);
    });
  }

  async sendTestMessage() {
    if (!this.connected || !this.ws) {
      throw new Error(`Connection ${this.id}: Not connected`);
    }

    const testMessage = {
      action: 'callTool',
      params: {
        name: 'chrome_navigate',
        arguments: { url: `https://example.com?user=${this.id}` }
      },
      id: `test_${this.id}_${Date.now()}`
    };

    console.log(`📤 Connection ${this.id}: Sending test message:`, testMessage);
    this.ws.send(JSON.stringify(testMessage));
  }

  disconnect() {
    if (this.ws) {
      this.ws.close();
    }
  }
}

async function testMultiUserSessions() {
  console.log('🚀 Starting multi-user session test...\n');

  const connections = [];

  try {
    // Create and connect multiple test connections
    for (let i = 1; i <= NUM_CONNECTIONS; i++) {
      const connection = new TestConnection(i);
      connections.push(connection);
      
      console.log(`\n--- Connecting User ${i} ---`);
      await connection.connect();
      
      // Wait a bit between connections
      await new Promise(resolve => setTimeout(resolve, 1000));
    }

    console.log('\n🎉 All connections established successfully!');
    console.log('\n📊 Session Summary:');
    connections.forEach(conn => {
      console.log(`  User ${conn.id}: Session ${conn.sessionInfo.sessionId}, User ID: ${conn.sessionInfo.userId}`);
    });

    // Test sending messages from each connection
    console.log('\n--- Testing Message Routing ---');
    for (const connection of connections) {
      await connection.sendTestMessage();
      await new Promise(resolve => setTimeout(resolve, 500));
    }

    // Wait for responses
    console.log('\n⏳ Waiting for responses...');
    await new Promise(resolve => setTimeout(resolve, 3000));

    // Test session isolation by checking unique session IDs
    const sessionIds = connections.map(conn => conn.sessionInfo.sessionId);
    const uniqueSessionIds = new Set(sessionIds);
    
    console.log('\n🔍 Session Isolation Test:');
    console.log(`  Total connections: ${connections.length}`);
    console.log(`  Unique session IDs: ${uniqueSessionIds.size}`);
    console.log(`  Session isolation: ${uniqueSessionIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);

    // Test user ID uniqueness
    const userIds = connections.map(conn => conn.sessionInfo.userId);
    const uniqueUserIds = new Set(userIds);
    
    console.log(`  Unique user IDs: ${uniqueUserIds.size}`);
    console.log(`  User ID isolation: ${uniqueUserIds.size === connections.length ? '✅ PASS' : '❌ FAIL'}`);

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

async function testSessionPersistence() {
  console.log('\n🔄 Testing session persistence...');
  
  const connection = new TestConnection('persistence');
  
  try {
    await connection.connect();
    const originalSessionId = connection.sessionInfo.sessionId;
    
    console.log(`📋 Original session: ${originalSessionId}`);
    
    // Disconnect and reconnect
    connection.disconnect();
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    await connection.connect();
    const newSessionId = connection.sessionInfo.sessionId;
    
    console.log(`📋 New session: ${newSessionId}`);
    console.log(`🔄 Session persistence: ${originalSessionId === newSessionId ? '❌ FAIL (sessions should be different)' : '✅ PASS (new session created)'}`);
    
    connection.disconnect();
  } catch (error) {
    console.error('❌ Session persistence test failed:', error);
  }
}

// Run tests
async function runAllTests() {
  try {
    await testMultiUserSessions();
    await new Promise(resolve => setTimeout(resolve, 2000));
    await testSessionPersistence();
  } catch (error) {
    console.error('❌ Tests failed:', error);
    process.exit(1);
  }
}

// Check if server is running
console.log('🔍 Checking if remote server is running...');
const testWs = new WebSocket(SERVER_URL);

testWs.on('open', () => {
  testWs.close();
  console.log('✅ Server is running, starting tests...\n');
  runAllTests();
});

testWs.on('error', (error) => {
  console.error('❌ Cannot connect to server. Please start the remote server first:');
  console.error('   cd app/remote-server && npm run dev');
  console.error('\nError:', error.message);
  process.exit(1);
});
