import { test, expect } from '../support/cross-app-fixtures';
import { S, tid } from '../support/selectors';

test.describe('Popular Requests Behavior', () => {
  test.beforeEach(async ({ page, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
  });

  test('1: Popular requests panel is visible on onlineboard start page', async ({ page, app }) => {
    const panel = page.locator(tid(S.POPULAR_REQUESTS_PANEL, app));
    const fallback = page.locator(
      '.popular-requests, popular-requests, [data-testid="landing-popular-request"]',
    );
    const target = (await panel.count()) > 0 ? panel : fallback.first();
    if ((await target.count()) === 0) {
      test.skip(true, 'Popular requests panel not present in this app');
      return;
    }
    await expect(target).toBeVisible({ timeout: 10000 });
  });

  test('2: Popular requests panel shows up to 4 items', async ({ page, app }) => {
    const items = page.locator(tid(S.POPULAR_REQUEST_ITEM, app));
    const fallback = page.locator(
      'popular-request, .popular-requests__item, [data-testid="landing-popular-request"]',
    );
    const target = (await items.count()) > 0 ? items : fallback;
    const count = await target.count();
    if (count === 0) {
      test.skip(true, 'No popular request items found');
      return;
    }
    expect(count).toBeGreaterThanOrEqual(1);
    expect(count).toBeLessThanOrEqual(4);
  });

  test('3: Clicking a flight number request navigates to flight search', async ({
    page,
    app,
    locale,
  }) => {
    const items = page.locator(tid(S.POPULAR_REQUEST_ITEM, app));
    const fallback = page.locator(
      'popular-request, .popular-requests__item, [data-testid="landing-popular-request"]',
    );
    const target = (await items.count()) > 0 ? items : fallback;
    const count = await target.count();
    if (count === 0) {
      test.skip(true, 'No popular request items found');
      return;
    }

    // Find a flight-number request item (contains a flight number pattern like SU1234 or SU 1234)
    let flightItem = null;
    for (let i = 0; i < count; i++) {
      const text = await target.nth(i).textContent();
      if (text && /[A-Z]{2}\s*\d{1,4}/i.test(text)) {
        flightItem = target.nth(i);
        break;
      }
    }
    if (!flightItem) {
      test.skip(true, 'No flight-number popular request found');
      return;
    }

    const urlBefore = page.url();
    await flightItem.click();
    await page.waitForLoadState('networkidle');

    const urlAfter = page.url();
    // Should have navigated away from the landing page
    expect(urlAfter).not.toBe(urlBefore);
    // URL should indicate a flight search (flight number in path or query)
    expect(urlAfter).toMatch(/onlineboard\/(departure|arrival|flight)|flight/i);
  });

  test('4: Clicking a route request navigates to route search', async ({ page, app, locale }) => {
    const items = page.locator(tid(S.POPULAR_REQUEST_ITEM, app));
    const fallback = page.locator(
      'popular-request, .popular-requests__item, [data-testid="landing-popular-request"]',
    );
    const target = (await items.count()) > 0 ? items : fallback;
    const count = await target.count();
    if (count === 0) {
      test.skip(true, 'No popular request items found');
      return;
    }

    // Find a route request item (contains city names or route pattern like MOW-LED, or has a dash/arrow between cities)
    let routeItem = null;
    for (let i = 0; i < count; i++) {
      const text = await target.nth(i).textContent();
      // Route items typically contain an arrow, dash between cities, or two city codes
      if (text && (/[A-Z]{3}\s*[-\u2013\u2014\u2192]\s*[A-Z]{3}/.test(text) || /\u2014|\u2192|->/.test(text))) {
        routeItem = target.nth(i);
        break;
      }
    }
    if (!routeItem) {
      // Fallback: just click the last item (routes are often listed after flight numbers)
      routeItem = target.last();
    }

    const urlBefore = page.url();
    await routeItem.click();
    await page.waitForLoadState('networkidle');

    const urlAfter = page.url();
    expect(urlAfter).not.toBe(urlBefore);
    // URL should indicate a route/departure search
    expect(urlAfter).toMatch(/onlineboard\/(departure|arrival)|schedule/i);
  });

  test('5: Popular requests visible on schedule start page', async ({ page, app, localePath }) => {
    await page.goto(localePath('schedule'));
    await page.waitForLoadState('networkidle');

    const panel = page.locator(tid(S.POPULAR_REQUESTS_PANEL, app));
    const fallback = page.locator(
      '.popular-requests, popular-requests, [data-testid="landing-popular-request"]',
    );
    const target = (await panel.count()) > 0 ? panel : fallback.first();
    if ((await target.count()) === 0) {
      test.skip(true, 'Popular requests panel not present on schedule page');
      return;
    }
    await expect(target).toBeVisible({ timeout: 10000 });
  });

  test('6: Popular request items are keyboard accessible', async ({ page, app }) => {
    const items = page.locator(tid(S.POPULAR_REQUEST_ITEM, app));
    const fallback = page.locator(
      'popular-request, .popular-requests__item, [data-testid="landing-popular-request"]',
    );
    const target = (await items.count()) > 0 ? items : fallback;
    const count = await target.count();
    if (count === 0) {
      test.skip(true, 'No popular request items found');
      return;
    }

    const firstItem = target.first();
    await expect(firstItem).toBeVisible();

    // Check that the item or its child link/button is focusable
    const focusable = firstItem.locator('a, button, [tabindex="0"]');
    if ((await focusable.count()) > 0) {
      await focusable.first().focus();
      await expect(focusable.first()).toBeFocused();

      // Press Enter and verify it triggers navigation
      const urlBefore = page.url();
      await page.keyboard.press('Enter');
      await page.waitForLoadState('networkidle');
      const urlAfter = page.url();
      expect(urlAfter).not.toBe(urlBefore);
    } else {
      // The item itself might be focusable
      const tabindex = await firstItem.getAttribute('tabindex');
      const role = await firstItem.getAttribute('role');
      const tagName = await firstItem.evaluate((el) => el.tagName.toLowerCase());
      const isFocusable =
        tabindex !== null || role === 'link' || role === 'button' || tagName === 'a';
      expect(isFocusable).toBe(true);
    }
  });
});
