import { test, expect, Page } from '@playwright/test';

/**
 * Focused Tests for Take Bet Flow
 * Investigating why taking a bet doesn't work
 */

const TEST_USERS = {
  alice: { email: 'alice@example.com', password: 'password123' },
  bob: { email: 'bob@example.com', password: 'password123' },
};

interface TestErrors {
  jsErrors: string[];
  networkErrors: { url: string; status: number; method: string; body?: any }[];
  consoleErrors: string[];
}

function setupErrorTracking(page: Page): TestErrors {
  const errors: TestErrors = {
    jsErrors: [],
    networkErrors: [],
    consoleErrors: [],
  };

  page.on('pageerror', (error) => {
    errors.jsErrors.push(`${error.name}: ${error.message}`);
  });

  page.on('response', async (response) => {
    if (response.status() >= 400) {
      let body = null;
      try {
        body = await response.json();
      } catch {}
      errors.networkErrors.push({
        url: response.url(),
        status: response.status(),
        method: response.request().method(),
        body,
      });
    }
  });

  page.on('console', (msg) => {
    if (msg.type() === 'error') {
      errors.consoleErrors.push(msg.text());
    }
  });

  return errors;
}

async function login(page: Page, user: { email: string; password: string }) {
  await page.goto('/login');
  await page.waitForLoadState('networkidle');
  await page.fill('input[type="email"]', user.email);
  await page.fill('input[type="password"]', user.password);
  await page.click('button[type="submit"]');
  await page.waitForLoadState('networkidle');
  await page.waitForTimeout(1500);
}

test.describe('Take Bet Flow Investigation', () => {
  test('TAKE-001: Bob takes bet via TradingPanel', async ({ page }) => {
    const errors = setupErrorTracking(page);

    console.log('\n=== TAKE-001: Take Bet via TradingPanel ===');

    // Login as Bob
    await login(page, TEST_USERS.bob);
    console.log('Logged in as Bob');

    // Go to home page and click on an event
    await page.goto('/');
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // Click on first event name to go to event detail page
    const eventLinks = page.locator('text=/\\w+ vs \\w+/i');
    const linkCount = await eventLinks.count();
    console.log(`Found ${linkCount} event links`);

    if (linkCount > 0) {
      await eventLinks.first().click();
      await page.waitForTimeout(2000);

      await page.screenshot({ path: 'tests/screenshots/take001-event-page.png', fullPage: true });

      // Look for "Take Existing Bet" section in TradingPanel
      const takeExistingSection = page.locator('text=Take Existing Bet');
      const hasTakeSection = await takeExistingSection.isVisible().catch(() => false);
      console.log(`"Take Existing Bet" section visible: ${hasTakeSection}`);

      // Look for Take buttons
      const takeButtons = page.locator('button').filter({ hasText: /^take$/i });
      const takeButtonCount = await takeButtons.count();
      console.log(`Found ${takeButtonCount} Take buttons`);

      if (takeButtonCount > 0) {
        // Set up API listener
        let apiCalled = false;
        let apiUrl = '';
        let apiResponse: any = null;

        page.on('request', req => {
          if (req.url().includes('/take') && req.method() === 'POST') {
            apiCalled = true;
            apiUrl = req.url();
            console.log('Take API Request:', req.url());
          }
        });

        page.on('response', async resp => {
          if (resp.url().includes('/take')) {
            apiResponse = {
              status: resp.status(),
              body: await resp.json().catch(() => null)
            };
          }
        });

        // Click first Take button
        await takeButtons.first().click();
        console.log('Clicked Take button');

        await page.waitForTimeout(3000);
        await page.screenshot({ path: 'tests/screenshots/take001-after-take.png', fullPage: true });

        console.log(`API was called: ${apiCalled}`);
        if (apiCalled) {
          console.log(`API URL: ${apiUrl}`);
        }
        if (apiResponse) {
          console.log('API Response:', apiResponse);
        }

        // Check for toast messages
        const successToast = await page.locator('text=Bet taken successfully').isVisible().catch(() => false);
        const errorToast = await page.locator('[role="status"]').textContent().catch(() => '');
        console.log(`Success toast visible: ${successToast}`);
        console.log(`Toast content: ${errorToast}`);
      } else {
        console.log('No Take buttons found in TradingPanel - checking if there are open bets');

        // Check order book for open bets
        const openIndicators = await page.locator('text=/\\d+ open/i').count();
        console.log(`Open bet indicators found: ${openIndicators}`);
      }
    }

    console.log('\n--- Errors ---');
    console.log('JS Errors:', errors.jsErrors);
    console.log('Network Errors:', errors.networkErrors);
  });

  test('TAKE-002: Bob takes bet via SpreadGrid modal', async ({ page }) => {
    const errors = setupErrorTracking(page);

    console.log('\n=== TAKE-002: Take Bet via SpreadGrid Modal ===');

    await login(page, TEST_USERS.bob);
    console.log('Logged in as Bob');

    await page.goto('/sport-events');
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // Select first event
    const eventButtons = page.locator('button').filter({ hasText: /vs/i });
    if (await eventButtons.count() > 0) {
      await eventButtons.first().click();
      await page.waitForTimeout(1500);

      await page.screenshot({ path: 'tests/screenshots/take002-spread-grid.png', fullPage: true });

      // Find a spread with open bets (green background, shows "X open")
      const spreadsWithOpen = page.locator('button').filter({ hasText: /open/i });
      const openSpreadCount = await spreadsWithOpen.count();
      console.log(`Found ${openSpreadCount} spreads with open bets`);

      if (openSpreadCount > 0) {
        // Click on spread with open bets
        await spreadsWithOpen.first().click();
        await page.waitForTimeout(1000);

        await page.screenshot({ path: 'tests/screenshots/take002-spread-modal.png', fullPage: true });

        // Look for Take Bet button in modal
        const takeBetButtons = page.locator('button').filter({ hasText: /take bet/i });
        const takeBtnCount = await takeBetButtons.count();
        console.log(`Found ${takeBtnCount} "Take Bet" buttons in modal`);

        if (takeBtnCount > 0) {
          // Log modal content before clicking
          const modalContent = await page.locator('.fixed.inset-0').textContent().catch(() => '');
          console.log('Modal content preview:', modalContent?.substring(0, 300));

          // Set up API listener
          const apiPromise = page.waitForResponse(
            resp => resp.url().includes('/take') && resp.request().method() === 'POST',
            { timeout: 10000 }
          ).catch(() => null);

          // Click Take Bet button
          await takeBetButtons.first().click();
          console.log('Clicked "Take Bet" button');

          await page.waitForTimeout(1500);
          await page.screenshot({ path: 'tests/screenshots/take002-take-modal.png', fullPage: true });

          // Check if TakeBetModal opened
          const takeModalTitle = await page.locator('h2, h3').filter({ hasText: /take bet/i }).isVisible().catch(() => false);
          console.log(`TakeBetModal title visible: ${takeModalTitle}`);

          // Check for data issues in modal (the bug: betInfo is array used as object)
          const takeModalContent = await page.locator('.fixed.inset-0').last().textContent().catch(() => '');
          console.log('TakeBetModal content:', takeModalContent?.substring(0, 500));

          const hasUndefined = takeModalContent?.includes('undefined');
          const hasNaN = takeModalContent?.includes('NaN');
          console.log(`Modal shows undefined: ${hasUndefined}`);
          console.log(`Modal shows NaN: ${hasNaN}`);

          if (hasUndefined || hasNaN) {
            console.log('DEFECT CONFIRMED: TakeBetModal has data display issue');
          }

          // Look for confirm button in TakeBetModal
          const confirmTakeBtn = page.locator('button').filter({ hasText: /take bet.*\$/i });
          if (await confirmTakeBtn.isVisible().catch(() => false)) {
            console.log('Clicking confirm button in TakeBetModal');
            await confirmTakeBtn.click();

            await page.waitForTimeout(3000);
            await page.screenshot({ path: 'tests/screenshots/take002-after-confirm.png', fullPage: true });

            const response = await apiPromise;
            if (response) {
              console.log(`Take API status: ${response.status()}`);
              const body = await response.json().catch(() => null);
              console.log('Take API response:', body);
            } else {
              console.log('No API call made');
            }
          }
        }
      } else {
        console.log('No spreads with open bets found');
      }
    }

    console.log('\n--- Errors ---');
    console.log('JS Errors:', errors.jsErrors);
    console.log('Network Errors:', errors.networkErrors);
  });

  test('TAKE-003: Verify TakeBetModal receives correct data', async ({ page }) => {
    const errors = setupErrorTracking(page);

    console.log('\n=== TAKE-003: TakeBetModal Data Verification ===');

    await login(page, TEST_USERS.bob);
    await page.goto('/sport-events');
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    // Select first event
    const eventButtons = page.locator('button').filter({ hasText: /vs/i });
    if (await eventButtons.count() > 0) {
      await eventButtons.first().click();
      await page.waitForTimeout(1500);

      // Find spread with high number of open bets
      const openTexts = await page.locator('text=/\\d+ open/').all();
      console.log(`Found ${openTexts.length} open bet indicators`);

      // Find the parent button of an open bet indicator
      for (const openText of openTexts.slice(0, 3)) {
        const parentButton = openText.locator('xpath=ancestor::button');
        if (await parentButton.count() > 0) {
          const spreadText = await parentButton.textContent();
          console.log(`Clicking spread: ${spreadText?.trim()}`);

          await parentButton.click();
          await page.waitForTimeout(800);

          // Check modal for available bets
          const availableBets = page.locator('.fixed.inset-0').locator('text=Available to Take');
          const hasAvailable = await availableBets.isVisible().catch(() => false);
          console.log(`"Available to Take" section visible: ${hasAvailable}`);

          if (hasAvailable) {
            // Get bet details from modal
            const betDetails = await page.locator('.bg-green-50, .border-green-200').first().textContent().catch(() => '');
            console.log(`First available bet details: ${betDetails}`);

            // Click Take Bet
            const takeBetBtn = page.locator('button').filter({ hasText: /^take bet$/i });
            if (await takeBetBtn.count() > 0) {
              await takeBetBtn.first().click();
              await page.waitForTimeout(1000);

              await page.screenshot({ path: 'tests/screenshots/take003-take-modal.png', fullPage: true });

              // Analyze TakeBetModal content
              const modalText = await page.locator('.fixed.inset-0').last().textContent().catch(() => '');

              // Check for proper values (should have $ amounts, usernames, etc.)
              const has$Amount = /\$\d+/.test(modalText || '');
              const hasCreatorInfo = /by \w+/.test(modalText || '');
              const hasPotInfo = /pot/i.test(modalText || '');

              console.log('\nTakeBetModal Content Analysis:');
              console.log(`  Has $ amount: ${has$Amount}`);
              console.log(`  Has creator info: ${hasCreatorInfo}`);
              console.log(`  Has pot info: ${hasPotInfo}`);
              console.log(`  Modal text sample: ${modalText?.substring(0, 400)}`);

              // Close modal and continue
              const closeBtn = page.locator('button').filter({ hasText: /cancel|×|close/i });
              if (await closeBtn.count() > 0) {
                await closeBtn.first().click();
              }
            }
          }

          // Close modal
          await page.keyboard.press('Escape');
          await page.waitForTimeout(300);
        }
      }
    }

    console.log('\n--- Error Summary ---');
    console.log('JS Errors:', errors.jsErrors);
    if (errors.jsErrors.length > 0) {
      console.log('DEFECT: JavaScript errors occurred');
    }
  });

  test('TAKE-004: Direct API test - take existing bet', async ({ page, request }) => {
    console.log('\n=== TAKE-004: Direct API Take Bet Test ===');

    // First, login as Alice and create a bet
    await login(page, TEST_USERS.alice);

    // Get token via evaluating the auth store
    const aliceAuth = await page.evaluate(() => {
      const authStr = localStorage.getItem('auth-storage');
      return authStr ? JSON.parse(authStr) : null;
    });
    console.log('Alice auth storage:', aliceAuth ? 'Found' : 'Not found');

    let aliceToken = null;
    if (aliceAuth?.state?.token) {
      aliceToken = aliceAuth.state.token;
    }

    if (!aliceToken) {
      // Try alternate storage location
      aliceToken = await page.evaluate(() => localStorage.getItem('token'));
    }

    console.log(`Alice token: ${aliceToken ? 'Retrieved' : 'Not found'}`);

    if (!aliceToken) {
      // Try to get token from cookies or session storage
      const cookies = await page.context().cookies();
      console.log('Cookies:', cookies.map(c => c.name));

      const sessionData = await page.evaluate(() => sessionStorage.getItem('token'));
      console.log(`Session token: ${sessionData ? 'Found' : 'Not found'}`);
    }

    // Get events via the page's network context
    await page.goto('/sport-events');
    await page.waitForLoadState('networkidle');

    // Create bet via UI since we can't reliably get token
    const eventButtons = page.locator('button').filter({ hasText: /vs/i });
    if (await eventButtons.count() > 0) {
      await eventButtons.first().click();
      await page.waitForTimeout(1500);

      // Click on a spread
      const spreadCells = page.locator('button').filter({ hasText: /^[+-]?\d+\.?\d*$/ });
      await spreadCells.first().click();
      await page.waitForTimeout(500);

      // Create bet
      const createBtn = page.locator('button').filter({ hasText: /create new bet/i });
      if (await createBtn.isVisible()) {
        await createBtn.click();
        await page.waitForTimeout(500);

        // Fill stake
        await page.locator('input[type="number"]').fill('25');
        await page.locator('button[type="submit"]').click();
        await page.waitForTimeout(2000);

        console.log('Created bet as Alice');
      }
    }

    // Logout Alice
    await page.goto('/');
    await page.waitForTimeout(500);
    const logoutBtn = page.locator('button').filter({ hasText: /logout/i });
    if (await logoutBtn.isVisible()) {
      await logoutBtn.click();
      await page.waitForTimeout(1000);
    }

    // Login as Bob
    await login(page, TEST_USERS.bob);
    console.log('Logged in as Bob');

    // Navigate and take bet
    await page.goto('/sport-events');
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const bobEventBtns = page.locator('button').filter({ hasText: /vs/i });
    if (await bobEventBtns.count() > 0) {
      await bobEventBtns.first().click();
      await page.waitForTimeout(1500);

      await page.screenshot({ path: 'tests/screenshots/take004-bob-grid.png', fullPage: true });

      // Find and click spread with open bets
      const openSpread = page.locator('button').filter({ hasText: /open/i }).first();
      if (await openSpread.isVisible()) {
        await openSpread.click();
        await page.waitForTimeout(800);

        await page.screenshot({ path: 'tests/screenshots/take004-detail-modal.png', fullPage: true });

        // Click Take Bet
        const takeBtn = page.locator('button').filter({ hasText: /take bet/i }).first();
        if (await takeBtn.isVisible()) {
          // Monitor API call
          const apiPromise = page.waitForResponse(
            resp => resp.url().includes('/take'),
            { timeout: 10000 }
          ).catch(() => null);

          await takeBtn.click();
          await page.waitForTimeout(1000);

          await page.screenshot({ path: 'tests/screenshots/take004-take-modal.png', fullPage: true });

          // Click confirm in TakeBetModal
          const confirmBtn = page.locator('button').filter({ hasText: /take bet.*\$|confirm/i }).last();
          if (await confirmBtn.isVisible()) {
            await confirmBtn.click();
            await page.waitForTimeout(3000);

            const response = await apiPromise;
            if (response) {
              console.log(`API Response: ${response.status()}`);
              const body = await response.json().catch(() => null);
              console.log('Response body:', body);

              if (response.status() >= 200 && response.status() < 300) {
                console.log('SUCCESS: Bet taken via UI');
              } else {
                console.log('FAILURE: Bet taking failed');
              }
            } else {
              console.log('WARNING: No API call detected');
            }
          }
        }
      }
    }
  });
});
