import { test, expect } from '@playwright/test';
import { APIInterceptor } from '../utils/api-interceptor';
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('Session Join Flow - Detailed API Comparison', () => {
  test('capture complete session join API calls (jam-ui)', async ({ page }) => {
    const apiInterceptor = new APIInterceptor();
    const wsMonitor = new WebSocketMonitor();

    apiInterceptor.intercept(page);
    wsMonitor.monitor(page);

    console.log('\n========================================');
    console.log('SESSION JOIN FLOW - API CAPTURE');
    console.log('========================================\n');

    // Login first
    await loginToJamUI(page);
    await waitForAPICalls(page, 3000);

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

    console.log('Starting session creation + join flow...\n');

    // Clear previous calls - we only want session join calls
    apiInterceptor.reset();
    const wsConnectionsBefore = wsMonitor.getConnectionCount();

    // Create and join session
    await fillSessionForm(page, { sessionType: 'private' });
    await waitForAPICalls(page, 8000);

    // Capture all data
    const apiCalls = apiInterceptor.getCalls();
    const wsConnections = wsMonitor.getConnections();
    const newWsConnections = wsConnections.slice(wsConnectionsBefore);

    console.log('========================================');
    console.log('SESSION JOIN API CALLS (jam-ui)');
    console.log('========================================\n');

    // Group API calls by type
    const sessionCreationCalls = apiCalls.filter(c =>
      c.method === 'POST' && c.pathname.match(/\/api\/sessions\/?$/)
    );

    const participantCalls = apiCalls.filter(c =>
      c.pathname.includes('/participants')
    );

    const sessionDetailCalls = apiCalls.filter(c =>
      c.method === 'GET' && c.pathname.match(/\/api\/sessions\/[a-f0-9-]+\/?$/)
    );

    const sessionHistoryCalls = apiCalls.filter(c =>
      c.pathname.includes('/history')
    );

    const trackCalls = apiCalls.filter(c =>
      c.pathname.includes('/tracks')
    );

    const chatCalls = apiCalls.filter(c =>
      c.pathname.includes('/chat') && c.url.includes('music_session')
    );

    const udpCalls = apiCalls.filter(c =>
      c.pathname.includes('/udp_reachable')
    );

    const otherCalls = apiCalls.filter(c =>
      !sessionCreationCalls.includes(c) &&
      !participantCalls.includes(c) &&
      !sessionDetailCalls.includes(c) &&
      !sessionHistoryCalls.includes(c) &&
      !trackCalls.includes(c) &&
      !chatCalls.includes(c) &&
      !udpCalls.includes(c)
    );

    console.log('REST API CALLS:\n');
    console.log('1. Session Creation:');
    sessionCreationCalls.forEach(c => {
      console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
      if (c.responseBody?.id) {
        console.log(`   Session ID: ${c.responseBody.id}`);
      }
    });

    console.log('\n2. Add Participant (Join):');
    participantCalls.forEach(c => {
      console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
    });

    console.log('\n3. Get Session Details:');
    sessionDetailCalls.forEach(c => {
      console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
    });

    console.log('\n4. Get Session History:');
    sessionHistoryCalls.forEach(c => {
      console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
    });

    console.log('\n5. Update Tracks:');
    if (trackCalls.length > 0) {
      trackCalls.forEach(c => {
        console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
      });
    } else {
      console.log('   ❌ NOT CALLED');
    }

    console.log('\n6. Load Session Chat:');
    if (chatCalls.length > 0) {
      chatCalls.forEach(c => {
        console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
      });
    } else {
      console.log('   ❌ NOT CALLED');
    }

    console.log('\n7. UDP Reachability Check:');
    if (udpCalls.length > 0) {
      udpCalls.forEach(c => {
        console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
      });
    } else {
      console.log('   ❌ NOT CALLED');
    }

    console.log('\n8. Other API Calls:');
    otherCalls.forEach(c => {
      console.log(`   ${c.method} ${c.pathname} -> ${c.responseStatus}`);
    });

    console.log('\n========================================');
    console.log('WEBSOCKET CONNECTIONS');
    console.log('========================================\n');

    newWsConnections.forEach((conn, idx) => {
      console.log(`Connection ${idx + 1}:`);
      console.log(`  URL: ${conn.url}`);
      console.log(`  Type: ${conn.isNativeClient ? 'Native Client' : conn.isServerConnection ? 'Server' : 'Other'}`);
      console.log(`  Messages: ${conn.messages.length}`);
      console.log(`  Status: ${conn.closed ? 'Closed' : 'Open'}`);

      if (conn.url.includes('?')) {
        const url = new URL(conn.url);
        console.log(`  Parameters:`);
        url.searchParams.forEach((value, key) => {
          console.log(`    ${key}: ${value.substring(0, 50)}${value.length > 50 ? '...' : ''}`);
        });
      }
      console.log('');
    });

    console.log('========================================');
    console.log('SUMMARY');
    console.log('========================================\n');
    console.log(`Total REST API calls: ${apiCalls.length}`);
    console.log(`  - Session creation: ${sessionCreationCalls.length}`);
    console.log(`  - Add participant: ${participantCalls.length}`);
    console.log(`  - Get session details: ${sessionDetailCalls.length}`);
    console.log(`  - Get session history: ${sessionHistoryCalls.length}`);
    console.log(`  - Update tracks: ${trackCalls.length}`);
    console.log(`  - Session chat: ${chatCalls.length}`);
    console.log(`  - UDP reachability: ${udpCalls.length}`);
    console.log(`  - Other calls: ${otherCalls.length}`);
    console.log(`\nWebSocket connections: ${newWsConnections.length}`);
    console.log(`Total WebSocket messages: ${newWsConnections.reduce((sum, c) => sum + c.messages.length, 0)}`);

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

    const analysis = {
      timestamp: new Date().toISOString(),
      restApiCalls: {
        total: apiCalls.length,
        sessionCreation: sessionCreationCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        addParticipant: participantCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        getSessionDetails: sessionDetailCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        getSessionHistory: sessionHistoryCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        updateTracks: trackCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        sessionChat: chatCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        udpReachability: udpCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
        other: otherCalls.map(c => ({ method: c.method, url: c.url, status: c.responseStatus })),
      },
      websocketConnections: newWsConnections.map(c => ({
        url: c.url,
        type: c.isNativeClient ? 'native' : c.isServerConnection ? 'server' : 'other',
        messageCount: c.messages.length,
        status: c.closed ? 'closed' : 'open',
      })),
    };

    fs.writeFileSync(
      path.join(resultsDir, 'jam-ui-session-join.json'),
      JSON.stringify(analysis, null, 2)
    );

    fs.writeFileSync(
      path.join(resultsDir, 'jam-ui-all-api-calls.json'),
      JSON.stringify(apiCalls, null, 2)
    );

    fs.writeFileSync(
      path.join(resultsDir, 'jam-ui-websockets.json'),
      wsMonitor.toJSON()
    );

    console.log(`\n✓ Analysis saved to: ${resultsDir}`);

    // Basic assertions
    expect(sessionCreationCalls.length).toBeGreaterThan(0);
    expect(participantCalls.length).toBeGreaterThan(0);
  });
});
