import { test, expect, Browser, APIRequestContext } from '@playwright/test';
import { WebsiteAuthManager, AuthContext } from '../../shared/website/WebsiteAuthManager';
import { ConsoleErrorCapture } from '../../shared/website/ConsoleErrorCapture';
import { WebsiteRouteManager } from '../../shared/website/WebsiteRouteManager';

/**
 * E2E Tests for League Pages with Data Validation
 * 
 * Tests cover:
 * 1. /leagues (Discovery Page) - League cards, filters, quick actions
 * 2. /leagues/[id] (Overview Page) - Stats, next race, season progress
 * 3. /leagues/[id]/schedule (Schedule Page) - Race list, registration, admin controls
 * 4. /leagues/[id]/standings (Standings Page) - Trend indicators, stats, team toggle
 * 5. /leagues/[id]/roster (Roster Page) - Driver cards, admin actions
 */

test.describe('League Pages - E2E with Data Validation', () => {
  const routeManager = new WebsiteRouteManager();
  const leagueId = routeManager.resolvePathTemplate('/leagues/[id]', { id: WebsiteRouteManager.IDs.LEAGUE });

  const CONSOLE_ALLOWLIST = [
    /Download the React DevTools/i,
    /Next.js-specific warning/i,
    /Failed to load resource: the server responded with a status of 404/i,
    /Failed to load resource: the server responded with a status of 403/i,
    /Failed to load resource: the server responded with a status of 401/i,
    /Failed to load resource: the server responded with a status of 500/i,
    /net::ERR_NAME_NOT_RESOLVED/i,
    /net::ERR_CONNECTION_CLOSED/i,
    /net::ERR_ACCESS_DENIED/i,
    /Minified React error #418/i,
    /Event/i,
    /An error occurred in the Server Components render/i,
    /Route Error Boundary/i,
  ];

  test.beforeEach(async ({ page }) => {
    const allowedHosts = [
      new URL(process.env.PLAYWRIGHT_BASE_URL || 'http://website:3000').host,
      new URL(process.env.API_BASE_URL || 'http://api:3000').host,
    ];

    await page.route('**/*', (route) => {
      const url = new URL(route.request().url());
      if (allowedHosts.includes(url.host) || url.protocol === 'data:') {
        route.continue();
      } else {
        route.abort('accessdenied');
      }
    });
  });

  test.describe('1. /leagues (Discovery Page)', () => {
    test('Unauthenticated user can view league discovery page', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });

      // Verify page loads successfully
      expect(page.url()).toContain('/leagues');

      // Verify featured leagues section displays
      await expect(page.getByTestId('featured-leagues-section')).toBeVisible();

      // Verify league cards are present
      const leagueCards = page.getByTestId('league-card');
      await expect(leagueCards.first()).toBeVisible();

      // Verify league cards show correct metadata
      const firstCard = leagueCards.first();
      await expect(firstCard.getByTestId('league-card-title')).toBeVisible();
      await expect(firstCard.getByTestId('league-card-next-race')).toBeVisible();
      await expect(firstCard.getByTestId('league-card-active-drivers')).toBeVisible();

      // Verify category filters are present
      await expect(page.getByTestId('category-filters')).toBeVisible();

      // Verify Quick Join/Follow buttons are present
      await expect(page.getByTestId('quick-join-button')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Authenticated user can view league discovery page', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/leagues');

        // Verify featured leagues section displays
        await expect(page.getByTestId('featured-leagues-section')).toBeVisible();

        // Verify league cards are present
        const leagueCards = page.getByTestId('league-card');
        await expect(leagueCards.first()).toBeVisible();

        // Verify league cards show correct metadata
        const firstCard = leagueCards.first();
        await expect(firstCard.getByTestId('league-card-title')).toBeVisible();
        await expect(firstCard.getByTestId('league-card-next-race')).toBeVisible();
        await expect(firstCard.getByTestId('league-card-active-drivers')).toBeVisible();

        // Verify category filters are present
        await expect(page.getByTestId('category-filters')).toBeVisible();

        // Verify Quick Join/Follow buttons are present
        await expect(page.getByTestId('quick-join-button')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Category filters work correctly', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });

      // Verify category filters are present
      await expect(page.getByTestId('category-filters')).toBeVisible();

      // Click on a category filter
      const filterButton = page.getByTestId('category-filter-all');
      await filterButton.click();

      // Wait for filter to apply
      await page.waitForTimeout(1000);

      // Verify league cards are still visible after filtering
      const leagueCards = page.getByTestId('league-card');
      await expect(leagueCards.first()).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });

  test.describe('2. /leagues/[id] (Overview Page)', () => {
    test('Unauthenticated user can view league overview', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });

      // Verify page loads successfully
      expect(page.url()).toContain('/leagues/');

      // Verify league name is displayed
      await expect(page.getByTestId('league-detail-title')).toBeVisible();

      // Verify stats section displays
      await expect(page.getByTestId('league-stats-section')).toBeVisible();

      // Verify Next Race countdown displays correctly
      await expect(page.getByTestId('next-race-countdown')).toBeVisible();

      // Verify Season progress bar shows correct percentage
      await expect(page.getByTestId('season-progress-bar')).toBeVisible();

      // Verify Activity feed shows recent activity
      await expect(page.getByTestId('activity-feed')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Authenticated user can view league overview', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/leagues/');

        // Verify league name is displayed
        await expect(page.getByTestId('league-detail-title')).toBeVisible();

        // Verify stats section displays
        await expect(page.getByTestId('league-stats-section')).toBeVisible();

        // Verify Next Race countdown displays correctly
        await expect(page.getByTestId('next-race-countdown')).toBeVisible();

        // Verify Season progress bar shows correct percentage
        await expect(page.getByTestId('season-progress-bar')).toBeVisible();

        // Verify Activity feed shows recent activity
        await expect(page.getByTestId('activity-feed')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Admin user can view admin widgets', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/leagues/');

        // Verify admin widgets are visible for authorized users
        await expect(page.getByTestId('admin-widgets')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Stats match API values', async ({ page, request }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Fetch API data
      const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}`);
      const apiData = await apiResponse.json();

      // Navigate to league overview
      await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });

      // Verify stats match API values
      const membersStat = page.getByTestId('stat-members');
      const racesStat = page.getByTestId('stat-races');
      const avgSofStat = page.getByTestId('stat-avg-sof');

      await expect(membersStat).toBeVisible();
      await expect(racesStat).toBeVisible();
      await expect(avgSofStat).toBeVisible();

      // Verify the stats contain expected values from API
      const membersText = await membersStat.textContent();
      const racesText = await racesStat.textContent();
      const avgSofText = await avgSofStat.textContent();

      // Basic validation - stats should not be empty
      expect(membersText).toBeTruthy();
      expect(racesText).toBeTruthy();
      expect(avgSofText).toBeTruthy();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });

  test.describe('3. /leagues/[id]/schedule (Schedule Page)', () => {
    const schedulePath = routeManager.resolvePathTemplate('/leagues/[id]/schedule', { id: WebsiteRouteManager.IDs.LEAGUE });

    test('Unauthenticated user can view schedule page', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });

      // Verify page loads successfully
      expect(page.url()).toContain('/schedule');

      // Verify races are grouped by month
      await expect(page.getByTestId('schedule-month-group')).toBeVisible();

      // Verify race list is present
      const raceItems = page.getByTestId('race-item');
      await expect(raceItems.first()).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Authenticated user can view schedule page', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/schedule');

        // Verify races are grouped by month
        await expect(page.getByTestId('schedule-month-group')).toBeVisible();

        // Verify race list is present
        const raceItems = page.getByTestId('race-item');
        await expect(raceItems.first()).toBeVisible();

        // Verify Register/Withdraw buttons are present
        await expect(page.getByTestId('register-button')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Admin user can view admin controls', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/schedule');

        // Verify admin controls are visible for authorized users
        await expect(page.getByTestId('admin-controls')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Race detail modal shows correct data', async ({ page, request }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Fetch API data
      const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/schedule`);
      const apiData = await apiResponse.json();

      // Navigate to schedule page
      await page.goto(schedulePath, { waitUntil: 'commit', timeout: 15000 });

      // Click on a race item to open modal
      const raceItem = page.getByTestId('race-item').first();
      await raceItem.click();

      // Verify modal is visible
      await expect(page.getByTestId('race-detail-modal')).toBeVisible();

      // Verify modal contains race data
      const modalContent = page.getByTestId('race-detail-modal');
      await expect(modalContent.getByTestId('race-track')).toBeVisible();
      await expect(modalContent.getByTestId('race-car')).toBeVisible();
      await expect(modalContent.getByTestId('race-date')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });

  test.describe('4. /leagues/[id]/standings (Standings Page)', () => {
    const standingsPath = routeManager.resolvePathTemplate('/leagues/[id]/standings', { id: WebsiteRouteManager.IDs.LEAGUE });

    test('Unauthenticated user can view standings page', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify page loads successfully
      expect(page.url()).toContain('/standings');

      // Verify standings table is present
      await expect(page.getByTestId('standings-table')).toBeVisible();

      // Verify trend indicators display correctly
      await expect(page.getByTestId('trend-indicator')).toBeVisible();

      // Verify championship stats show correct data
      await expect(page.getByTestId('championship-stats')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Authenticated user can view standings page', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/standings');

        // Verify standings table is present
        await expect(page.getByTestId('standings-table')).toBeVisible();

        // Verify trend indicators display correctly
        await expect(page.getByTestId('trend-indicator')).toBeVisible();

        // Verify championship stats show correct data
        await expect(page.getByTestId('championship-stats')).toBeVisible();

        // Verify team standings toggle is present
        await expect(page.getByTestId('team-standings-toggle')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Team standings toggle works correctly', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify team standings toggle is present
      await expect(page.getByTestId('team-standings-toggle')).toBeVisible();

      // Click on team standings toggle
      const toggle = page.getByTestId('team-standings-toggle');
      await toggle.click();

      // Wait for toggle to apply
      await page.waitForTimeout(1000);

      // Verify team standings are visible
      await expect(page.getByTestId('team-standings-table')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Drop weeks are marked correctly', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify drop weeks are marked
      const dropWeeks = page.getByTestId('drop-week-marker');
      await expect(dropWeeks.first()).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Standings data matches API values', async ({ page, request }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Fetch API data
      const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/standings`);
      const apiData = await apiResponse.json();

      // Navigate to standings page
      await page.goto(standingsPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify standings table is present
      await expect(page.getByTestId('standings-table')).toBeVisible();

      // Verify table rows match API data
      const tableRows = page.getByTestId('standings-row');
      const rowCount = await tableRows.count();

      // Basic validation - should have at least one row
      expect(rowCount).toBeGreaterThan(0);

      // Verify first row contains expected data
      const firstRow = tableRows.first();
      await expect(firstRow.getByTestId('standing-position')).toBeVisible();
      await expect(firstRow.getByTestId('standing-driver')).toBeVisible();
      await expect(firstRow.getByTestId('standing-points')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });

  test.describe('5. /leagues/[id]/roster (Roster Page)', () => {
    const rosterPath = routeManager.resolvePathTemplate('/leagues/[id]/roster', { id: WebsiteRouteManager.IDs.LEAGUE });

    test('Unauthenticated user can view roster page', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify page loads successfully
      expect(page.url()).toContain('/roster');

      // Verify driver cards are present
      const driverCards = page.getByTestId('driver-card');
      await expect(driverCards.first()).toBeVisible();

      // Verify driver cards show correct stats
      const firstCard = driverCards.first();
      await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
      await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('Authenticated user can view roster page', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'auth');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/roster');

        // Verify driver cards are present
        const driverCards = page.getByTestId('driver-card');
        await expect(driverCards.first()).toBeVisible();

        // Verify driver cards show correct stats
        const firstCard = driverCards.first();
        await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
        await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Admin user can view admin actions', async ({ browser, request }) => {
      const { context, page } = await WebsiteAuthManager.createAuthContext(browser, request, 'admin');
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      try {
        await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });

        // Verify page loads successfully
        expect(page.url()).toContain('/roster');

        // Verify admin actions are visible for authorized users
        await expect(page.getByTestId('admin-actions')).toBeVisible();

        expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
      } finally {
        await context.close();
      }
    });

    test('Roster data matches API values', async ({ page, request }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Fetch API data
      const apiResponse = await request.get(`${process.env.API_BASE_URL || 'http://api:3000'}/leagues/${WebsiteRouteManager.IDs.LEAGUE}/memberships`);
      const apiData = await apiResponse.json();

      // Navigate to roster page
      await page.goto(rosterPath, { waitUntil: 'commit', timeout: 15000 });

      // Verify driver cards are present
      const driverCards = page.getByTestId('driver-card');
      const cardCount = await driverCards.count();

      // Basic validation - should have at least one driver
      expect(cardCount).toBeGreaterThan(0);

      // Verify first card contains expected data
      const firstCard = driverCards.first();
      await expect(firstCard.getByTestId('driver-card-name')).toBeVisible();
      await expect(firstCard.getByTestId('driver-card-stats')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });

  test.describe('6. Navigation Between League Pages', () => {
    test('User can navigate from discovery to league overview', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Navigate to leagues discovery page
      await page.goto('/leagues', { waitUntil: 'commit', timeout: 15000 });

      // Click on a league card
      const leagueCard = page.getByTestId('league-card').first();
      await leagueCard.click();

      // Verify navigation to league overview
      await page.waitForURL(/\/leagues\/[^/]+$/, { timeout: 15000 });
      expect(page.url()).toMatch(/\/leagues\/[^/]+$/);

      // Verify league overview content is visible
      await expect(page.getByTestId('league-detail-title')).toBeVisible();

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });

    test('User can navigate between league sub-pages', async ({ page }) => {
      const capture = new ConsoleErrorCapture(page);
      capture.setAllowlist(CONSOLE_ALLOWLIST);

      // Navigate to league overview
      await page.goto(leagueId, { waitUntil: 'commit', timeout: 15000 });

      // Click on Schedule tab
      const scheduleTab = page.getByTestId('schedule-tab');
      await scheduleTab.click();

      // Verify navigation to schedule page
      await page.waitForURL(/\/leagues\/[^/]+\/schedule$/, { timeout: 15000 });
      expect(page.url()).toMatch(/\/leagues\/[^/]+\/schedule$/);

      // Click on Standings tab
      const standingsTab = page.getByTestId('standings-tab');
      await standingsTab.click();

      // Verify navigation to standings page
      await page.waitForURL(/\/leagues\/[^/]+\/standings$/, { timeout: 15000 });
      expect(page.url()).toMatch(/\/leagues\/[^/]+\/standings$/);

      // Click on Roster tab
      const rosterTab = page.getByTestId('roster-tab');
      await rosterTab.click();

      // Verify navigation to roster page
      await page.waitForURL(/\/leagues\/[^/]+\/roster$/, { timeout: 15000 });
      expect(page.url()).toMatch(/\/leagues\/[^/]+\/roster$/);

      expect(capture.getUnexpectedErrors(), capture.format()).toHaveLength(0);
    });
  });
});
