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

/**
 * User Stories 181-210: Advanced Features & Edge Cases
 *
 * 181-185: Multi-leg flight scenarios
 * 186-190: Search history scenarios
 * 191-194: Error scenarios
 * 195-200: Input validation scenarios
 * 201-205: Search edge cases
 * 206-210: Locale scenarios
 */

test.describe('User Stories 181-210: Advanced Features & Edge Cases', () => {
  test.beforeEach(async ({ page, localePath }) => {
    await mockAllAPIs(page);
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 181-185: Multi-leg flight scenarios
  // ─────────────────────────────────────────────────────────────────────────

  test('181.1: Multi-leg flight shows segments', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    if (count > 0) {
      await flightResults.first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(500);

      const segments = page.locator(
        'flight-segment, .flight-segment, [data-testid*="segment"], .flight__segment',
      );
      const segmentCount = await segments.count();
      expect(segmentCount).toBeGreaterThanOrEqual(0);
    }
  });

  test('182.1: User switches multi-leg segments', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    if (count > 0) {
      await flightResults.first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(500);

      const segments = page.locator(
        'flight-segment, .flight-segment, [data-testid*="segment"], .flight__segment',
      );
      const segmentCount = await segments.count();
      if (segmentCount > 1) {
        const urlBefore = page.url();
        await segments.nth(1).click();
        await page.waitForTimeout(300);
        const urlAfter = page.url();
        expect(urlAfter.length).toBeGreaterThan(0);
      }
    }
  });

  test('183.1: Multi-leg shows timeline', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    if (count > 0) {
      await flightResults.first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(500);

      const timeline = page.locator(
        'flight-timeline, .flight-timeline, [data-testid*="timeline"], .flight__timeline',
      );
      const timelineCount = await timeline.count();
      expect(timelineCount).toBeGreaterThanOrEqual(0);
    }
  });

  test('184.1: Multi-leg shows transfer info', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    if (count > 0) {
      await flightResults.first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(500);

      const transferInfo = page.locator(
        'flight-transfer, .flight-transfer, [data-testid*="transfer"], .flight__transfer',
      );
      const transferCount = await transferInfo.count();
      expect(transferCount).toBeGreaterThanOrEqual(0);
    }
  });

  test('185.1: Multi-leg shows full route', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    if (count > 0) {
      await flightResults.first().click();
      await page.waitForLoadState('networkidle');
      await page.waitForTimeout(500);

      const fullRoute = page.locator(tid(S.DETAILS_FULL_ROUTE, app));
      const fallbackRoute = page.locator('.flight-route, .route-display, [class*="route"]');
      const target = (await fullRoute.count()) > 0 ? fullRoute : fallbackRoute;

      await expect(target.first()).toBeVisible();
    }
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 186-190: Search history scenarios
  // ─────────────────────────────────────────────────────────────────────────

  test('186.1: Recent searches display on landing', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const historySection = page.locator(
      'search-history, [data-testid="landing-search-history"], .search-history, [class*="search-history"]',
    );
    const count = await historySection.count();
    expect(count).toBeGreaterThan(0);
  });

  test('187.1: Re-search from history item', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(2000);

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const historyItems = page.locator(
      'search-history .history-item, [data-testid="landing-search-history-item"], .search-history__item',
    );
    const count = await historyItems.count();
    if (count > 0) {
      const urlBefore = page.url();
      await historyItems.first().click();
      await page.waitForTimeout(1000);
      const urlAfter = page.url();
      expect(urlAfter).not.toBe(urlBefore);
    }
  });

  test('188.1: Clear recent searches', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const historySection = page.locator(
      'search-history, [data-testid="landing-search-history"], .search-history, [class*="search-history"]',
    );
    const count = await historySection.count();
    if (count > 0) {
      const clearButton = historySection.locator(
        'button[aria-label*="clear"], button[aria-label*="Clear"], .history-clear, .clear-history',
      );
      const clearCount = await clearButton.count();
      if (clearCount > 0) {
        await clearButton.first().click();
        await page.waitForTimeout(300);
      }
    }
  });

  test('189.1: Recent searches persist on reload', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(2000);

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const historyItems = page.locator(
      'search-history .history-item, [data-testid="landing-search-history-item"], .search-history__item',
    );
    const countBefore = await historyItems.count();

    await page.reload();
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const historyItemsAfter = page.locator(
      'search-history .history-item, [data-testid="landing-search-history-item"], .search-history__item',
    );
    const countAfter = await historyItemsAfter.count();

    expect(countAfter).toBeGreaterThanOrEqual(countBefore);
  });

  test('190.1: Recent searches persist when navigating', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(2000);

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const historyItems = page.locator(
      'search-history .history-item, [data-testid="landing-search-history-item"], .search-history__item',
    );
    const countBefore = await historyItems.count();

    await page.goto(localePath('schedule'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(500);

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const historyItemsAfter = page.locator(
      'search-history .history-item, [data-testid="landing-search-history-item"], .search-history__item',
    );
    const countAfter = await historyItemsAfter.count();

    expect(countAfter).toBeGreaterThanOrEqual(countBefore);
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 191-194: Error scenarios
  // ─────────────────────────────────────────────────────────────────────────

  test('191.1: 404 error page displays for invalid route', async ({ page, app, localePath }) => {
    await page.goto(localePath('/nonexistent-page-xyz-123'));
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const pageText = await page.textContent('body');
    const hasErrorIndicator =
      pageText?.includes('404') ||
      pageText?.includes('not found') ||
      pageText?.includes('page not found') ||
      pageText?.includes('не найдена') ||
      pageText?.includes('страница') ||
      false;

    expect(hasErrorIndicator).toBe(true);
  });

  test('192.1: 500 error page displays on server error', async ({ page, app, localePath }) => {
    await mockAllAPIs(page);

    await page.route('**/api/Requests/**', (route) => {
      route.fulfill({
        status: 500,
        contentType: 'application/json',
        body: JSON.stringify({ error: 'Internal Server Error' }),
      });
    });

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const flightInput = page.locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app));
    if (await flightInput.isVisible().catch(() => false)) {
      await flightInput.fill('SU100');
      const searchButton = page.locator(tid(S.FILTER_FLIGHT_NUMBER_SEARCH, app));
      if (await searchButton.isVisible().catch(() => false)) {
        await searchButton.click();
        await page.waitForTimeout(2000);
      }
    }

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  test('193.1: Network error handled gracefully', async ({ page, app, localePath }) => {
    await mockAllAPIs(page);

    await page.route('**/api/Requests/**', (route) => {
      route.abort('failed');
    });

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  test('194.1: Timeout error handled gracefully', async ({ page, app, localePath }) => {
    await mockAllAPIs(page);

    await page.route('**/api/Requests/**', (route) => {
      route.abort('timedout');
    });

    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 195-200: Input validation scenarios
  // ─────────────────────────────────────────────────────────────────────────

  test('195.1: Invalid input shows validation error', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const routeTab = page.locator(tid(S.FILTER_ROUTE_TAB, app));
    const fallback = page.locator('[data-testid="route-filter"]');
    const tabEl = (await routeTab.count()) > 0 ? routeTab : fallback;

    const isExpanded = await page
      .locator(tid(S.FILTER_ROUTE_DEPARTURE_INPUT, app))
      .isVisible()
      .catch(() => false);

    if (!isExpanded) {
      const headerLink = tabEl.locator('.p-accordion-header-link, .p-accordion-header a').first();
      if ((await headerLink.count()) > 0) {
        await headerLink.click();
      } else {
        await tabEl.click();
      }
      await page.waitForTimeout(500);
    }

    const departureInput = page.locator(tid(S.FILTER_ROUTE_DEPARTURE_INPUT, app));
    await departureInput.fill('INVALIDCITYXYZ123');
    await page.waitForTimeout(500);

    const searchButton = page.locator(tid(S.FILTER_ROUTE_SEARCH, app));
    await searchButton.click();
    await page.waitForTimeout(1000);

    const errorMessages = page.locator(
      '.p-error, .error-message, [role="alert"], .ng-invalid.ng-dirty',
    );
    const count = await errorMessages.count();
    if (count > 0) {
      expect(count).toBeGreaterThanOrEqual(1);
    }
  });

  test('196.1: Keyboard navigation works', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const body = page.locator('body');
    await body.focus();
    await page.keyboard.press('Tab');

    const focusedElement = await page.evaluate(() => {
      return document.activeElement?.tagName.toLowerCase() || '';
    });

    expect(focusedElement).toMatch(/input|button|a|select|textarea/);
  });

  test('197.1: Screen reader accessibility', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const navElement = page.locator('nav[aria-label], [role="navigation"]');
    const navCount = await navElement.count();
    expect(navCount).toBeGreaterThan(0);

    const mainElement = page.locator('main[aria-label], [role="main"]');
    const mainCount = await mainElement.count();
    expect(mainCount).toBeGreaterThan(0);
  });

  test('198.1: Browser resize handles layout', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    await page.setViewportSize({ width: 1280, height: 720 });
    await page.waitForTimeout(500);

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);

    await page.setViewportSize({ width: 768, height: 1024 });
    await page.waitForTimeout(500);

    const bodyVisibleMobile = await page.isVisible('body');
    expect(bodyVisibleMobile).toBe(true);
  });

  test('199.1: Scroll page works', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    await page.evaluate(() => {
      window.scrollTo(0, 500);
    });
    await page.waitForTimeout(500);

    const scrollPosition = await page.evaluate(() => window.scrollY);
    expect(scrollPosition).toBeGreaterThan(0);
  });

  test('200.1: Hover over interactive elements', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const buttons = page.locator('button, a, [role="button"]');
    const buttonCount = await buttons.count();
    if (buttonCount > 0) {
      await buttons.first().hover();
      await page.waitForTimeout(300);
    }
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 201-205: Search edge cases
  // ─────────────────────────────────────────────────────────────────────────

  test('201.1: Flight with missing information displays', async ({ page, app, localePath }) => {
    const today = formatToday();
    await page.goto(`/${localePath('onlineboard')}/departure/MOW-${today}`);
    await page.waitForLoadState('networkidle');
    await page.waitForTimeout(1000);

    const flightResults = page.locator(
      'flight-result, .flight-result, [data-testid*="flight-result"], .flight__item',
    );
    const count = await flightResults.count();
    expect(count).toBeGreaterThanOrEqual(0);
  });

  test('202.1: Very long flight number is accepted', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const flightTab = page.locator(tid(S.FILTER_FLIGHT_TAB, app));
    const fallback = page.locator('[data-testid="flight-filter"]');
    const tabEl = (await flightTab.count()) > 0 ? flightTab : fallback;

    const isExpanded = await page
      .locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app))
      .isVisible()
      .catch(() => false);

    if (!isExpanded) {
      const headerLink = tabEl.locator('.p-accordion-header-link, .p-accordion-header a').first();
      if ((await headerLink.count()) > 0) {
        await headerLink.click();
      } else {
        await tabEl.click();
      }
      await page.waitForTimeout(500);
    }

    const flightInput = page.locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app));
    const longFlightNumber = 'SU' + '1234'.repeat(10);
    await flightInput.fill(longFlightNumber);
    await page.waitForTimeout(500);

    const searchButton = page.locator(tid(S.FILTER_FLIGHT_NUMBER_SEARCH, app));
    await searchButton.click();
    await page.waitForTimeout(1000);

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  test('203.1: Unicode in flight number is accepted', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const flightTab = page.locator(tid(S.FILTER_FLIGHT_TAB, app));
    const fallback = page.locator('[data-testid="flight-filter"]');
    const tabEl = (await flightTab.count()) > 0 ? flightTab : fallback;

    const isExpanded = await page
      .locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app))
      .isVisible()
      .catch(() => false);

    if (!isExpanded) {
      const headerLink = tabEl.locator('.p-accordion-header-link, .p-accordion-header a').first();
      if ((await headerLink.count()) > 0) {
        await headerLink.click();
      } else {
        await tabEl.click();
      }
      await page.waitForTimeout(500);
    }

    const flightInput = page.locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app));
    await flightInput.fill('СУ1234');
    await page.waitForTimeout(500);

    const searchButton = page.locator(tid(S.FILTER_FLIGHT_NUMBER_SEARCH, app));
    await searchButton.click();
    await page.waitForTimeout(1000);

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  test('204.1: Rapid searches handled gracefully', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const routeTab = page.locator(tid(S.FILTER_ROUTE_TAB, app));
    const fallback = page.locator('[data-testid="route-filter"]');
    const tabEl = (await routeTab.count()) > 0 ? routeTab : fallback;

    const isExpanded = await page
      .locator(tid(S.FILTER_ROUTE_DEPARTURE_INPUT, app))
      .isVisible()
      .catch(() => false);

    if (!isExpanded) {
      const headerLink = tabEl.locator('.p-accordion-header-link, .p-accordion-header a').first();
      if ((await headerLink.count()) > 0) {
        await headerLink.click();
      } else {
        await tabEl.click();
      }
      await page.waitForTimeout(500);
    }

    const departureInput = page.locator(tid(S.FILTER_ROUTE_DEPARTURE_INPUT, app));
    const searchButton = page.locator(tid(S.FILTER_ROUTE_SEARCH, app));

    for (let i = 0; i < 5; i++) {
      await departureInput.fill(`City${i}`);
      await page.waitForTimeout(100);
      await searchButton.click();
      await page.waitForTimeout(200);
    }

    const consoleErrors: string[] = [];
    page.on('console', (msg) => {
      if (msg.type() === 'error') {
        consoleErrors.push(msg.text());
      }
    });

    await page.waitForTimeout(1000);
    expect(consoleErrors.length).toBeLessThanOrEqual(0);
  });

  test('205.1: Special characters in flight number handled', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const flightTab = page.locator(tid(S.FILTER_FLIGHT_TAB, app));
    const fallback = page.locator('[data-testid="flight-filter"]');
    const tabEl = (await flightTab.count()) > 0 ? flightTab : fallback;

    const isExpanded = await page
      .locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app))
      .isVisible()
      .catch(() => false);

    if (!isExpanded) {
      const headerLink = tabEl.locator('.p-accordion-header-link, .p-accordion-header a').first();
      if ((await headerLink.count()) > 0) {
        await headerLink.click();
      } else {
        await tabEl.click();
      }
      await page.waitForTimeout(500);
    }

    const flightInput = page.locator(tid(S.FILTER_FLIGHT_NUMBER_INPUT, app));
    await flightInput.fill('SU@#$%123');
    await page.waitForTimeout(500);

    const searchButton = page.locator(tid(S.FILTER_FLIGHT_NUMBER_SEARCH, app));
    await searchButton.click();
    await page.waitForTimeout(1000);

    const bodyVisible = await page.isVisible('body');
    expect(bodyVisible).toBe(true);
  });

  // ─────────────────────────────────────────────────────────────────────────
  // Story 210: Locale translation check (no switcher needed)
  // ─────────────────────────────────────────────────────────────────────────

  test('210.1: Locale displays correct translations', async ({ page, app, localePath }) => {
    await page.goto(localePath('onlineboard'));
    await page.waitForLoadState('networkidle');

    const h1 = page.locator('h1').first();
    await expect(h1).toBeVisible({ timeout: 10000 });

    const h1Text = await h1.textContent();
    expect(h1Text?.trim().length).toBeGreaterThan(0);

    if (localePath('').includes('ru-ru')) {
      expect((h1Text?.toLowerCase() || '').match(/табло|онлайн/)).toBeTruthy();
    } else if (localePath('').includes('en-us')) {
      expect(h1Text?.toLowerCase()).toMatch(/board|flight|online/i);
    }
  });
});

function formatToday(): string {
  const d = new Date();
  return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
}
