import { chromium } from '@playwright/test';
import * as fs from 'fs';
import * as path from 'path';

/**
 * Standalone script to capture network traffic for the "Join Session" flow
 * This runs independently without the global Playwright test setup
 *
 * Usage: node --loader ts-node/esm test/capture-session-flow-standalone.spec.ts
 * Or: npx ts-node test/capture-session-flow-standalone.spec.ts
 */
async function captureSessionFlow() {
  console.log('Starting session flow capture...\n');

  // Launch browser with ability to capture network traffic
  const browser = await chromium.launch({
    headless: false, // Use headed mode to see what's happening
    slowMo: 500, // Slow down by 500ms to make actions visible
  });

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

  const context = await browser.newContext({
    ignoreHTTPSErrors: true,
    recordHar: {
      path: path.join(testResultsDir, 'session-join-flow.har'),
      mode: 'full', // Capture full request/response bodies
    },
  });

  const page = await context.newPage();

  // Arrays to collect network activity
  const wsMessages: any[] = [];
  const apiCalls: any[] = [];
  const allNetworkActivity: any[] = [];

  // Listen to all network requests
  page.on('request', request => {
    const url = request.url();
    const entry = {
      step: 'REQUEST',
      method: request.method(),
      url: url,
      headers: request.headers(),
      timestamp: new Date().toISOString(),
    };

    if (url.includes('/api/')) {
      console.log(`[API REQUEST] ${request.method()} ${url}`);
      apiCalls.push(entry);
    }
    allNetworkActivity.push(entry);
  });

  page.on('response', async response => {
    const url = response.url();
    let body = null;
    try {
      const contentType = response.headers()['content-type'] || '';
      if (contentType.includes('application/json') || contentType.includes('text/')) {
        body = await response.text();
      }
    } catch (e) {
      // Some responses can't be read
    }

    const entry = {
      step: 'RESPONSE',
      status: response.status(),
      statusText: response.statusText(),
      url: url,
      headers: response.headers(),
      body: body,
      timestamp: new Date().toISOString(),
    };

    if (url.includes('/api/')) {
      console.log(`[API RESPONSE] ${response.status()} ${url}`);
      apiCalls.push(entry);
    }
    allNetworkActivity.push(entry);
  });

  // Listen to WebSocket events
  page.on('websocket', ws => {
    console.log(`[WEBSOCKET] Opened: ${ws.url()}`);
    wsMessages.push({
      event: 'open',
      url: ws.url(),
      timestamp: new Date().toISOString(),
    });

    ws.on('framesent', frame => {
      console.log(`[WS SENT] ${frame.payload.toString().substring(0, 100)}...`);
      wsMessages.push({
        event: 'sent',
        payload: frame.payload.toString(),
        timestamp: new Date().toISOString(),
      });
    });

    ws.on('framereceived', frame => {
      console.log(`[WS RECEIVED] ${frame.payload.toString().substring(0, 100)}...`);
      wsMessages.push({
        event: 'received',
        payload: frame.payload.toString(),
        timestamp: new Date().toISOString(),
      });
    });

    ws.on('close', () => {
      console.log('[WEBSOCKET] Closed');
      wsMessages.push({
        event: 'close',
        timestamp: new Date().toISOString(),
      });
    });
  });

  try {
    console.log('\n=== STEP 1: Navigate to signin page ===');
    await page.goto('http://www.jamkazam.local:3100/signin', {
      waitUntil: 'networkidle',
      timeout: 30000,
    });
    await page.waitForTimeout(2000);

    console.log('\n=== STEP 2: Fill in login credentials ===');
    // Try multiple selectors for email field
    const emailSelectors = [
      'input#session_email',
      'input[name="email"]',
      'input[type="email"]',
      'input[placeholder*="email" i]',
    ];

    let emailFilled = false;
    for (const selector of emailSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          await page.fill(selector, 'nuwan@jamkazam.com');
          console.log(`Filled email using selector: ${selector}`);
          emailFilled = true;
          break;
        }
      } catch (e) {
        continue;
      }
    }

    if (!emailFilled) {
      console.error('Could not find email input field!');
      console.log('Available input fields:');
      const inputs = await page.$$('input');
      for (const input of inputs) {
        const type = await input.getAttribute('type');
        const name = await input.getAttribute('name');
        const id = await input.getAttribute('id');
        console.log(`  - input: type=${type}, name=${name}, id=${id}`);
      }
    }

    // Try multiple selectors for password field
    const passwordSelectors = [
      'input#session_password',
      'input[name="password"]',
      'input[type="password"]',
    ];

    let passwordFilled = false;
    for (const selector of passwordSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          await page.fill(selector, 'jam123');
          console.log(`Filled password using selector: ${selector}`);
          passwordFilled = true;
          break;
        }
      } catch (e) {
        continue;
      }
    }

    await page.waitForTimeout(1000);

    console.log('\n=== STEP 3: Click sign in button ===');
    const submitSelectors = [
      'button[type="submit"]',
      'input[type="submit"]',
      'button:has-text("Sign in")',
      'button:has-text("Login")',
      'button:has-text("Sign In")',
      'input[value="Sign in"]',
      'input[value="Login"]',
    ];

    let submitClicked = false;
    for (const selector of submitSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          await page.click(selector);
          console.log(`Clicked submit using selector: ${selector}`);
          submitClicked = true;
          break;
        }
      } catch (e) {
        continue;
      }
    }

    if (!submitClicked) {
      console.error('Could not find submit button!');
      console.log('Available buttons:');
      const buttons = await page.$$('button, input[type="submit"]');
      for (const button of buttons) {
        const text = await button.textContent();
        const type = await button.getAttribute('type');
        const value = await button.getAttribute('value');
        console.log(`  - button: text="${text}", type=${type}, value=${value}`);
      }
    }

    // Wait for navigation after login
    console.log('Waiting for navigation after login...');
    await page.waitForLoadState('networkidle', { timeout: 15000 }).catch(() => {
      console.log('networkidle timeout - continuing anyway');
    });
    await page.waitForTimeout(3000);

    console.log('\n=== STEP 4: Press Cmd+Shift+0 to skip upgrade modal ===');
    await page.keyboard.press('Meta+Shift+Digit0');
    await page.waitForTimeout(1500);
    console.log('Upgrade modal skipped');

    console.log('\n=== STEP 5: Look for and click "Create Session" tile ===');
    // Try multiple selectors for create session button
    const createSessionSelectors = [
      '[data-testid="create-session"]',
      'button:has-text("Create Session")',
      'a:has-text("Create Session")',
      'div:has-text("Create Session")',
      '.tile:has-text("Create Session")',
      '[title*="Create Session"]',
    ];

    let sessionClicked = false;
    for (const selector of createSessionSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          await page.click(selector);
          console.log(`Clicked create session using selector: ${selector}`);
          sessionClicked = true;
          break;
        }
      } catch (e) {
        continue;
      }
    }

    if (!sessionClicked) {
      console.warn('Could not find "Create Session" button - taking screenshot');
      await page.screenshot({ path: path.join(testResultsDir, 'dashboard-screenshot.png'), fullPage: true });
    }

    await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {
      console.log('networkidle timeout - continuing anyway');
    });
    await page.waitForTimeout(2000);

    console.log('\n=== STEP 6: Press Control+Shift+0 to remove backdrop ===');
    // Press Control+Shift+0 to trick browser as native client and remove backdrop
    // This works even with the modal open
    await page.keyboard.press('Control+Shift+Digit0');
    await page.waitForTimeout(2000);
    console.log('Backdrop removed, browser tricked as native client');

    console.log('\n=== STEP 7: Click "Create Quick Start" button ===');
    const quickStartSelectors = [
      'button:has-text("Create Quick Start")',
      'button:has-text("Quick Start")',
      'button:has-text("Create quick start")',
      '[data-testid="quick-start"]',
    ];

    let quickStartClicked = false;
    for (const selector of quickStartSelectors) {
      try {
        const element = await page.$(selector);
        if (element) {
          await page.click(selector);
          console.log(`Clicked quick start using selector: ${selector}`);
          quickStartClicked = true;
          break;
        }
      } catch (e) {
        continue;
      }
    }

    if (!quickStartClicked) {
      console.warn('Could not find "Create Quick Start" button - taking screenshot');
      await page.screenshot({ path: path.join(testResultsDir, 'session-create-screenshot.png'), fullPage: true });
    }

    // Wait for session to load and WebSocket messages
    console.log('\nWaiting for session to load and capturing WebSocket traffic...');
    await page.waitForLoadState('networkidle', { timeout: 10000 }).catch(() => {
      console.log('networkidle timeout - continuing anyway');
    });
    await page.waitForTimeout(10000); // Give plenty of time for WebSocket messages

    console.log('\n=== Recording Complete ===\n');

    // Save all captured data
    const apiCallsPath = path.join(testResultsDir, 'api-calls.json');
    fs.writeFileSync(apiCallsPath, JSON.stringify(apiCalls, null, 2));
    console.log(`✓ API calls saved to: ${apiCallsPath}`);
    console.log(`  Total API calls: ${apiCalls.length}`);

    const wsMessagesPath = path.join(testResultsDir, 'websocket-messages.json');
    fs.writeFileSync(wsMessagesPath, JSON.stringify(wsMessages, null, 2));
    console.log(`✓ WebSocket messages saved to: ${wsMessagesPath}`);
    console.log(`  Total WebSocket messages: ${wsMessages.length}`);

    const allActivityPath = path.join(testResultsDir, 'all-network-activity.json');
    fs.writeFileSync(allActivityPath, JSON.stringify(allNetworkActivity, null, 2));
    console.log(`✓ All network activity saved to: ${allActivityPath}`);
    console.log(`  Total network requests: ${allNetworkActivity.length}`);

    // Take final screenshot
    await page.screenshot({ path: path.join(testResultsDir, 'final-state.png'), fullPage: true });
    console.log(`✓ Final screenshot saved`);

    console.log('\nKeeping browser open for 10 seconds for manual inspection...');
    await page.waitForTimeout(10000);

  } catch (error) {
    console.error('\n❌ Error during capture:', error);
    await page.screenshot({ path: path.join(testResultsDir, 'error-screenshot.png'), fullPage: true });
    throw error;
  } finally {
    console.log('\nClosing browser and saving HAR file...');
    await context.close();
    await browser.close();
    console.log('✓ HAR file saved to: test-results/session-join-flow.har\n');
  }
}

// Run the capture
captureSessionFlow()
  .then(() => {
    console.log('✅ Capture completed successfully!');
    process.exit(0);
  })
  .catch((error) => {
    console.error('❌ Capture failed:', error);
    process.exit(1);
  });
