#!/usr/bin/env node
const puppeteer = require('puppeteer');

async function getPlayerCount(roomCode) {
  const browser = await puppeteer.launch({ 
    headless: 'new',
    args: [
      '--no-sandbox', 
      '--disable-setuid-sandbox'
    ]
  });
  
  const page = await browser.newPage();
  
  // Set a realistic user agent to avoid bot detection
  await page.setUserAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36');
  let playerCount = null;
  let roomValidated = false;
  
  // Monitor network requests to see if API call happens
  page.on('response', async (response) => {
    const url = response.url();
    if (url.includes('ecast.jackboxgames.com/api/v2/rooms')) {
      if (process.env.DEBUG) {
        console.error('[NETWORK] Room API called:', url, 'Status:', response.status());
      }
      if (response.status() === 200) {
        roomValidated = true;
      }
    }
  });

  // Listen for console messages that contain the client/welcome WebSocket message
  page.on('console', async msg => {
    try {
      const args = msg.args();
      for (const arg of args) {
        const val = await arg.jsonValue();
        const str = typeof val === 'object' ? JSON.stringify(val) : String(val);
        
        // Debug: log all console messages that might be relevant
        if (process.env.DEBUG && (str.includes('welcome') || str.includes('here') || str.includes('opcode'))) {
          console.error('[CONSOLE]', str.substring(0, 200));
        }
        
        // Look for the client/welcome message with player data
        if (str.includes('client/welcome')) {
          try {
            let data;
            if (typeof val === 'object') {
              data = val;
            } else {
              // The string might be "recv <- {...}" so extract the JSON part
              const jsonStart = str.indexOf('{');
              if (jsonStart !== -1) {
                const jsonStr = str.substring(jsonStart);
                data = JSON.parse(jsonStr);
              }
            }
            
            if (data && data.opcode === 'client/welcome' && data.result) {
              // Look for the "here" object which contains all connected players
              if (data.result.here) {
                playerCount = Object.keys(data.result.here).length;
                if (process.env.DEBUG) {
                  console.error('[SUCCESS] Found player count:', playerCount);
                }
              } else if (process.env.DEBUG) {
                console.error('[DEBUG] client/welcome found but no "here" object. Keys:', Object.keys(data.result));
              }
            }
          } catch (e) {
            if (process.env.DEBUG) {
              console.error('[PARSE ERROR]', e.message);
            }
          }
        }
      }
    } catch (e) {
      // Ignore errors
    }
  });

  try {
    if (process.env.DEBUG) console.error('[1] Navigating to jackbox.tv...');
    await page.goto('https://jackbox.tv/', { waitUntil: 'networkidle2', timeout: 30000 });
    
    // Wait for the room code input to be ready
    if (process.env.DEBUG) console.error('[2] Waiting for form...');
    await page.waitForSelector('input#roomcode', { timeout: 10000 });
    
    // Type the room code using the input ID (more reliable)
    // Use the element.type() method which properly triggers React events
    if (process.env.DEBUG) console.error('[3] Typing room code:', roomCode);
    const roomInput = await page.$('input#roomcode');
    await roomInput.type(roomCode.toUpperCase(), { delay: 50 }); // Reduced delay from 100ms to 50ms
    
    // Wait for room validation (the app info appears after validation)
    if (process.env.DEBUG) {
      console.error('[4] Waiting for room validation...');
      const roomValue = await page.evaluate(() => document.querySelector('input#roomcode').value);
      console.error('[4] Room code value:', roomValue);
    }
    
    // Actually wait for the validation to complete - the game name label appears
    try {
      await page.waitForFunction(() => {
        const labels = Array.from(document.querySelectorAll('div, span, label'));
        return labels.some(el => {
          const text = el.textContent;
          return text.includes('Trivia') || text.includes('Party') || text.includes('Quiplash') || 
                 text.includes('Fibbage') || text.includes('Drawful') || text.includes('Murder');
        });
      }, { timeout: 5000 });
      if (process.env.DEBUG) console.error('[4.5] Room validated successfully!');
    } catch (e) {
      if (process.env.DEBUG) console.error('[4.5] Room validation timeout - continuing anyway...');
    }
    
    // Type the name using the input ID
    // This will trigger the input event that enables the Play button
    if (process.env.DEBUG) console.error('[5] Typing name...');
    const nameInput = await page.$('input#username');
    await nameInput.type('Observer', { delay: 30 }); // Reduced delay from 100ms to 30ms
    
    // Wait a moment for the button to enable and click immediately
    if (process.env.DEBUG) console.error('[6] Waiting for Play button...');
    await page.waitForFunction(() => {
      const buttons = Array.from(document.querySelectorAll('button'));
      const playBtn = buttons.find(b => {
        const text = b.textContent.toUpperCase();
        return (text.includes('PLAY') || text.includes('RECONNECT')) && !b.disabled;
      });
      return playBtn !== undefined;
    }, { timeout: 5000 }); // Reduced timeout from 10s to 5s
    
    if (process.env.DEBUG) console.error('[7] Clicking Play...');
    await page.evaluate(() => {
      const buttons = Array.from(document.querySelectorAll('button'));
      const playBtn = buttons.find(b => {
        const text = b.textContent.toUpperCase();
        return (text.includes('PLAY') || text.includes('RECONNECT')) && !b.disabled;
      });
      if (playBtn) {
        playBtn.click();
      } else {
        throw new Error('Play button not found or still disabled');
      }
    });
    
    // Wait for the WebSocket player count message (up to 5 seconds)
    if (process.env.DEBUG) console.error('[8] Waiting for player count message...');
    for (let i = 0; i < 10 && playerCount === null; i++) {
      await new Promise(resolve => setTimeout(resolve, 500));
    }
    
  } finally {
    await browser.close();
  }

  if (playerCount === null) {
    throw new Error('Could not get player count from WebSocket');
  }

  return playerCount;
}

// Main
const roomCode = process.argv[2];
if (!roomCode) {
  console.error('Usage: node jackbox-count-v3.js <ROOM_CODE>');
  process.exit(1);
}

getPlayerCount(roomCode.toUpperCase())
  .then(count => {
    console.log(count);
    process.exit(0);
  })
  .catch(err => {
    console.error('Error:', err.message);
    process.exit(1);
  });

