import { test, expect } from '@playwright/test';
import { WebSocketMonitor } from '../utils/websocket-monitor';
import { loginToJamUI, navigateToSessionCreation, fillSessionForm, waitForAPICalls } from '../utils/test-helpers';
import * as fs from 'fs';
import * as path from 'path';

test.describe('WebSocket Connection Verification', () => {
  test('dual WebSocket connections are established during session join', async ({ page }) => {
    const wsMonitor = new WebSocketMonitor();
    wsMonitor.monitor(page);

    // Login
    await loginToJamUI(page);
    await waitForAPICalls(page);

    // Navigate to session creation
    await navigateToSessionCreation(page);
    await waitForAPICalls(page);

    // Create session using form
    await fillSessionForm(page);
    await waitForAPICalls(page, 5000);

    // Verify connections
    const verification = wsMonitor.verifyDualConnections();

    console.log('\nWebSocket Connection Verification:');
    console.log(`  Native client connection: ${verification.hasNativeClient ? 'YES' : 'NO'}`);
    console.log(`  Server connection: ${verification.hasServerConnection ? 'YES' : 'NO'}`);
    console.log(`  Both established: ${verification.bothEstablished ? 'YES' : 'NO'}`);

    const connections = wsMonitor.getConnections();
    console.log(`\nTotal connections: ${connections.length}`);
    connections.forEach((conn, idx) => {
      console.log(`  ${idx + 1}. ${conn.url}`);
      console.log(`     Messages: ${conn.messages.length}`);
      console.log(`     Type: ${conn.isNativeClient ? 'Native Client' : conn.isServerConnection ? 'Server' : 'Unknown'}`);
    });

    // Save results
    const resultsDir = path.join(__dirname, '../test-results/websocket-verification');
    if (!fs.existsSync(resultsDir)) {
      fs.mkdirSync(resultsDir, { recursive: true });
    }

    fs.writeFileSync(
      path.join(resultsDir, 'connections.json'),
      wsMonitor.toJSON()
    );

    // Assertions
    expect(verification.bothEstablished).toBe(true);
    expect(wsMonitor.getConnectionCount()).toBeGreaterThanOrEqual(2);
  });

  test('native client connection is to localhost:3060', async ({ page }) => {
    const wsMonitor = new WebSocketMonitor();
    wsMonitor.monitor(page);

    await loginToJamUI(page);
    await navigateToSessionCreation(page);
    await page.keyboard.press('Control+Shift+Digit0');
    await waitForAPICalls(page, 3000);
    await clickQuickStart(page);
    await waitForAPICalls(page, 5000);

    const nativeClient = wsMonitor.getNativeClientConnection();

    expect(nativeClient).toBeDefined();
    expect(nativeClient?.url).toContain('localhost:3060');
    expect(nativeClient?.url).toContain('ws://');

    console.log(`\nNative client connection URL: ${nativeClient?.url}`);
    console.log(`Messages sent/received: ${nativeClient?.messages.length || 0}`);
  });

  test('server connection is to jamkazam.local:6767', async ({ page }) => {
    const wsMonitor = new WebSocketMonitor();
    wsMonitor.monitor(page);

    await loginToJamUI(page);
    await navigateToSessionCreation(page);
    await page.keyboard.press('Control+Shift+Digit0');
    await waitForAPICalls(page, 3000);
    await clickQuickStart(page);
    await waitForAPICalls(page, 5000);

    const serverConn = wsMonitor.getServerConnection();

    expect(serverConn).toBeDefined();
    expect(serverConn?.url).toMatch(/jamkazam\.(local|com):6767/);
    expect(serverConn?.url).toContain('ws://');
    expect(serverConn?.url).toContain('/websocket');

    console.log(`\nServer connection URL: ${serverConn?.url}`);
    console.log(`Messages sent/received: ${serverConn?.messages.length || 0}`);

    // Check URL parameters
    if (serverConn) {
      const url = new URL(serverConn.url);
      console.log('\nServer connection parameters:');
      console.log(`  channel_id: ${url.searchParams.get('channel_id') || 'N/A'}`);
      console.log(`  client_type: ${url.searchParams.get('client_type') || 'N/A'}`);
      console.log(`  client_id: ${url.searchParams.get('client_id') || 'N/A'}`);
      console.log(`  product: ${url.searchParams.get('product') || 'N/A'}`);

      // Verify expected parameters
      expect(url.searchParams.get('client_type')).toBe('browser');
      expect(url.searchParams.get('product')).toBe('JamClientModern');
    }
  });

  test('WebSocket connections send and receive messages', async ({ page }) => {
    const wsMonitor = new WebSocketMonitor();
    wsMonitor.monitor(page);

    await loginToJamUI(page);
    await navigateToSessionCreation(page);
    await page.keyboard.press('Control+Shift+Digit0');
    await waitForAPICalls(page, 3000);
    await clickQuickStart(page);
    await waitForAPICalls(page, 10000); // Wait longer for messages

    const totalMessages = wsMonitor.getTotalMessageCount();

    console.log(`\nTotal WebSocket messages: ${totalMessages}`);

    const connections = wsMonitor.getConnections();
    for (const conn of connections) {
      const sentCount = conn.messages.filter(m => m.direction === 'sent').length;
      const receivedCount = conn.messages.filter(m => m.direction === 'received').length;

      console.log(`\n${conn.isNativeClient ? 'Native Client' : 'Server'} (${conn.url}):`);
      console.log(`  Sent: ${sentCount}`);
      console.log(`  Received: ${receivedCount}`);
      console.log(`  Total: ${conn.messages.length}`);
    }

    // Should have substantial message traffic
    expect(totalMessages).toBeGreaterThan(100);
  });

  test('WebSocket connections remain active during session', async ({ page }) => {
    const wsMonitor = new WebSocketMonitor();
    wsMonitor.monitor(page);

    await loginToJamUI(page);
    await navigateToSessionCreation(page);
    await page.keyboard.press('Control+Shift+Digit0');
    await waitForAPICalls(page, 3000);
    await clickQuickStart(page);
    await waitForAPICalls(page, 5000);

    // Wait a bit longer
    await page.waitForTimeout(3000);

    const activeConnections = wsMonitor.getActiveConnections();

    console.log(`\nActive WebSocket connections: ${activeConnections.length}`);
    activeConnections.forEach(conn => {
      console.log(`  ${conn.isNativeClient ? 'Native Client' : 'Server'}: OPEN`);
    });

    // Both connections should still be active
    expect(activeConnections.length).toBeGreaterThanOrEqual(2);

    // Verify neither connection is closed
    const nativeClient = wsMonitor.getNativeClientConnection();
    const server = wsMonitor.getServerConnection();

    expect(nativeClient?.closed).toBe(false);
    expect(server?.closed).toBe(false);
  });
});
