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

/**
 * Flight Details Tests (147-181)
 *
 * Tests the flight details page at /:locale/onlineboard/:flightSlug
 * e.g., /ru-ru/onlineboard/SU1234-20260406
 *
 * The flight details page is accessed either by:
 *   1. Clicking a flight result from a search results page
 *   2. Direct URL navigation to /onlineboard/{flight-slug}
 *
 * Since the Angular reference app may not have real flight data,
 * we navigate to a flight that exists (if any) or skip gracefully.
 */

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

/** Helper: tomorrow formatted as YYYYMMDD */
function formatTomorrow(): string {
  const d = new Date();
  d.setDate(d.getDate() + 1);
  return `${d.getFullYear()}${String(d.getMonth() + 1).padStart(2, '0')}${String(d.getDate()).padStart(2, '0')}`;
}

/**
 * Mock flight details endpoint.
 * Global mocks are already applied via fixture.
 * Must be called BEFORE page.goto().
 */
async function mockFlightDetailsAPIs(page: import('@playwright/test').Page) {
  // Mock flight details endpoint: /api/Requests/{id}/getflight
  // The Angular app calls this endpoint when navigating to /onlineboard/{flightSlug}
  await page.route('**/api/Requests/*/getflight', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify({
        id: 'SU1234-20260406',
        flightNumber: 'SU 1234',
        airlineName: 'Aeroflot',
        status: 'On Time',
        lastUpdated: '2026-04-07 15:30',
        departure: {
          cityCode: 'MOW',
          cityName: 'Moscow',
          terminal: '1',
          stationCode: 'SVO',
        },
        arrival: {
          cityCode: 'SPB',
          cityName: 'Saint Petersburg',
          terminal: '1',
          stationCode: 'LED',
        },
        aircraft: {
          model: 'Boeing 737-800',
          registration: 'VP-BDZ',
        },
        schedule: {
          scheduledDeparture: '10:30',
          scheduledArrival: '12:00',
          duration: '1h 30m',
          operatingDays: [1, 2, 3, 4, 5],
          utcOffset: '+03:00',
        },
        checkin: {
          status: 'Completed',
          startTime: '09:00',
          endTime: '10:00',
        },
        boarding: {
          status: 'In Progress',
          startTime: '10:00',
          endTime: '10:20',
        },
        deplaning: {
          status: 'Completed',
          startTime: '12:05',
          endTime: '12:20',
          transfer: 'T1',
          gate: '5',
          baggageBelt: '3',
        },
        catering: {
          available: true,
          services: ['Food', 'Drinks'],
        },
      }),
    });
  });

  // Mock flight search endpoints for navigation
  await page.route('**/api/flights/**', (route) => {
    route.fulfill({
      status: 200,
      contentType: 'application/json',
      body: JSON.stringify([]),
    });
  });
}

/**
 * Navigate to a flight details page.
 * If the flight slug is not provided, we attempt to navigate via search.
 */
async function navigateToFlightDetails(
  page: import('@playwright/test').Page,
  app: 'angular' | 'react',
  localePath: (path: string) => string,
  flightSlug: string = 'SU1234-20260406',
) {
  // Try to navigate directly to flight details
  const detailsURL = localePath(`onlineboard/${flightSlug}`);
  await page.goto(detailsURL, { waitUntil: 'networkidle' });

  // Verify the page loaded by checking for critical elements
  // If flight details page has a header, we're good
  // If we get a 404 or the page doesn't render, the test will skip
}

test.describe('Flight Details (Cross-App)', () => {
  test.beforeEach(async ({ page, app, localePath }) => {
    await mockAllAPIs(page);
    await mockFlightDetailsAPIs(page);
    // Navigate to flight details
    await navigateToFlightDetails(page, app, localePath, 'SU1234-20260406');
  });

  // ────────────────────────────────────────────────────────────────────────
  // Navigation & Page Load (6 tests: 147-152)
  // ────────────────────────────────────────────────────────────────────────

  test('147: Flight details page loads without errors', async ({ page }) => {
    // Verify page is not in an error state
    const errorElements = page.locator('[data-testid*="error"], .error-container, [role="alert"]');
    const errorCount = await errorElements.count();
    expect(errorCount).toBe(0);

    // Verify page title or header is present
    const header = page.locator('h1, h2, [data-testid*="header"], [data-testid*="flight"]').first();
    const headerCount = await header.count();
    expect(headerCount).toBeGreaterThanOrEqual(0);
  });

  test('148: Flight details URL contains correct flight slug', async ({ page, locale }) => {
    const url = page.url();
    expect(url).toMatch(new RegExp(`/${locale}/onlineboard/SU\\d+-\\d+`));
  });

  test('149: Page title displays flight number', async ({ page }) => {
    // Check for flight number in page title or heading
    const flightNumber = page.locator('h1, h2, [data-testid*="flight-number"]').first();
    if ((await flightNumber.count()) > 0) {
      const text = await flightNumber.textContent();
      expect(text).toMatch(/SU\s*1234|SU1234/i);
    }
  });

  test('150: Back button navigates to previous search results', async ({ page, app }) => {
    // Some implementations may not have explicit back buttons
    const backButton = page.locator(
      `${tid(S.BOARD_CANCEL_BUTTON, app)}, button[aria-label*="Back"i], a[href*="back"]`,
    );
    if ((await backButton.count()) > 0) {
      const urlBefore = page.url();
      await backButton.first().click();
      await page.waitForTimeout(500);
      const urlAfter = page.url();
      // URL should have changed
      expect(urlAfter).not.toBe(urlBefore);
    } else {
      test.skip(true, 'Back button not found in this app');
    }
  });

  test('151: Page renders with correct layout (header + content)', async ({ page }) => {
    // Look for main layout structure
    const body = page.locator('body');
    expect(await body.count()).toBeGreaterThan(0);

    // Should have some content beyond just empty page
    const content = page.locator('main, [role="main"], .container, .content, .page-content');
    const contentCount = await content.count();
    expect(contentCount).toBeGreaterThanOrEqual(0);
  });

  test('152: All text content matches current locale', async ({ page, locale }) => {
    // Check that locale is reflected in visible content or attributes
    const html = page.locator('html');
    const langAttr = await html.getAttribute('lang');
    if (langAttr) {
      expect(langAttr.toLowerCase()).toMatch(/ru|en/i);
    }
  });

  // ────────────────────────────────────────────────────────────────────────
  // Flight Header & Basic Info (8 tests: 153-160)
  // ────────────────────────────────────────────────────────────────────────

  test('153: Flight number is displayed with correct formatting', async ({ page, app }) => {
    const flightNumber = page.locator(tid(S.DETAILS_FLIGHT_NUMBER, app));
    if ((await flightNumber.count()) > 0) {
      await expect(flightNumber).toBeVisible();
      const text = await flightNumber.textContent();
      expect(text).toMatch(/SU\s*1234|SU1234/i);
    } else {
      test.skip(true, 'Flight number selector not found');
    }
  });

  test('154: Flight status badge shows current status', async ({ page, app }) => {
    const statusBadge = page.locator(tid(S.DETAILS_STATUS, app));
    if ((await statusBadge.count()) > 0) {
      await expect(statusBadge).toBeVisible();
      const text = await statusBadge.textContent();
      expect(text).toBeTruthy();
    } else {
      test.skip(true, 'Status badge not found');
    }
  });

  test('155: Airline logo is displayed', async ({ page, app }) => {
    const logo = page.locator(tid(S.DETAILS_OPERATOR_LOGO, app));
    if ((await logo.count()) > 0) {
      await expect(logo).toBeVisible();
    } else {
      // Fallback: look for any image or logo element
      const altLogo = page.locator('img[alt*="airline" i], img[alt*="aeroflot" i]');
      if ((await altLogo.count()) > 0) {
        await expect(altLogo.first()).toBeVisible();
      } else {
        test.skip(true, 'Airline logo not found');
      }
    }
  });

  test('156: Aircraft model is displayed', async ({ page, app }) => {
    const aircraftModel = page.locator(tid(S.DETAILS_AIRCRAFT_MODEL, app));
    if ((await aircraftModel.count()) > 0) {
      await expect(aircraftModel).toBeVisible();
      const text = await aircraftModel.textContent();
      expect(text).toBeTruthy();
    } else {
      // Fallback: look for aircraft text
      const altAircraft = page.locator('[data-testid*="aircraft"], [data-testid*="equipment"]');
      if ((await altAircraft.count()) > 0) {
        await expect(altAircraft.first()).toBeVisible();
      } else {
        test.skip(true, 'Aircraft model not found');
      }
    }
  });

  test('157: Departure time is displayed with timezone', async ({ page, app }) => {
    const depTime = page.locator(tid(S.DETAILS_DEPARTURE_TIME, app));
    if ((await depTime.count()) > 0) {
      await expect(depTime).toBeVisible();
      const text = await depTime.textContent();
      expect(text).toMatch(/\d+:\d+/);
    } else {
      test.skip(true, 'Departure time selector not found');
    }
  });

  test('158: Arrival time is displayed with timezone', async ({ page, app }) => {
    const arrTime = page.locator(tid(S.DETAILS_ARRIVAL_TIME, app));
    if ((await arrTime.count()) > 0) {
      await expect(arrTime).toBeVisible();
      const text = await arrTime.textContent();
      expect(text).toMatch(/\d+:\d+/);
    } else {
      test.skip(true, 'Arrival time selector not found');
    }
  });

  test('159: Flight duration is displayed', async ({ page, app }) => {
    const duration = page.locator(tid(S.DETAILS_DURATION, app));
    if ((await duration.count()) > 0) {
      await expect(duration).toBeVisible();
      const text = await duration.textContent();
      expect(text).toMatch(/\d+h/);
    } else {
      // Fallback: look for duration text
      const altDuration = page.locator('text=/\\d+h\\s*\\d*m/i');
      if ((await altDuration.count()) > 0) {
        await expect(altDuration.first()).toBeVisible();
      } else {
        test.skip(true, 'Duration not found');
      }
    }
  });

  test('160: Days of operation info is displayed', async ({ page }) => {
    // Look for day badges or operating schedule info
    const dayBadges = page.locator(
      '[data-testid*="day" i], .day-badge, [data-testid*="operating" i]',
    );
    if ((await dayBadges.count()) > 0) {
      await expect(dayBadges.first()).toBeVisible();
    } else {
      test.skip(true, 'Days of operation info not displayed');
    }
  });

  // ────────────────────────────────────────────────────────────────────────
  // Departure & Arrival Section (6 tests: 161-166)
  // ────────────────────────────────────────────────────────────────────────

  test('161: Departure station code is displayed', async ({ page, app }) => {
    const depStation = page.locator(tid(S.DETAILS_DEPARTURE_STATION, app));
    if ((await depStation.count()) > 0) {
      await expect(depStation).toBeVisible();
      const text = await depStation.textContent();
      expect(text).toMatch(/MOW|LED|SVO/i);
    } else {
      test.skip(true, 'Departure station selector not found');
    }
  });

  test('162: Departure station name is displayed', async ({ page }) => {
    // Look for city name (e.g., "Moscow") or station name
    const depName = page.locator('[data-testid*="departure"] [data-testid*="name"]');
    if ((await depName.count()) > 0) {
      await expect(depName.first()).toBeVisible();
    } else {
      test.skip(true, 'Departure station name not found');
    }
  });

  test('163: Departure terminal is displayed', async ({ page, app }) => {
    const terminal = page.locator(tid(S.DETAILS_TERMINAL_LINK, app));
    if ((await terminal.count()) > 0) {
      await expect(terminal).toBeVisible();
    } else {
      // Fallback: look for terminal text
      const altTerminal = page.locator('text=/Terminal\\s*\\d+/i');
      if ((await altTerminal.count()) > 0) {
        await expect(altTerminal.first()).toBeVisible();
      } else {
        test.skip(true, 'Terminal info not displayed (may be optional)');
      }
    }
  });

  test('164: Arrival station code is displayed', async ({ page, app }) => {
    const arrStation = page.locator(tid(S.DETAILS_ARRIVAL_STATION, app));
    if ((await arrStation.count()) > 0) {
      await expect(arrStation).toBeVisible();
      const text = await arrStation.textContent();
      expect(text).toMatch(/MOW|LED|SVO|VKO/i);
    } else {
      test.skip(true, 'Arrival station selector not found');
    }
  });

  test('165: Arrival station name is displayed', async ({ page }) => {
    // Look for city name
    const arrName = page.locator('[data-testid*="arrival"] [data-testid*="name"]');
    if ((await arrName.count()) > 0) {
      await expect(arrName.first()).toBeVisible();
    } else {
      test.skip(true, 'Arrival station name not found');
    }
  });

  test('166: Arrival terminal is displayed', async ({ page }) => {
    // Look for terminal information in arrival section
    const terminal = page.locator('[data-testid*="arrival"]').locator('text=/Terminal/');
    if ((await terminal.count()) > 0) {
      await expect(terminal.first()).toBeVisible();
    } else {
      test.skip(true, 'Arrival terminal not displayed (may be optional)');
    }
  });

  // ────────────────────────────────────────────────────────────────────────
  // Route & Transfer Info (4 tests: 167-170)
  // ────────────────────────────────────────────────────────────────────────

  test('167: Direct flight shows no intermediate stops', async ({ page, app }) => {
    // For a direct flight, there should be no transfer section visible
    // or the transfer section should explicitly state "Direct"
    const transferSection = page.locator(tid(S.DETAILS_TRANSFER_SECTION, app));
    if ((await transferSection.count()) > 0) {
      const text = await transferSection.textContent();
      expect(text).toMatch(/Direct|no transfer|прямой/i);
    } else {
      test.skip(true, 'Transfer section not found (expected for direct flight)');
    }
  });

  test('168: Transfer flight shows transfer station', async ({ page, app }) => {
    // If flight has transfers, the transfer station should be shown
    const transferSection = page.locator(tid(S.DETAILS_TRANSFER_SECTION, app));
    if ((await transferSection.count()) > 0) {
      const text = await transferSection.textContent();
      // Should contain either a station code or explicit transfer info
      expect(text).toBeTruthy();
    } else {
      test.skip(true, 'Transfer section not shown (flight may be direct)');
    }
  });

  test('169: Full route section shows all segments', async ({ page, app }) => {
    const fullRoute = page.locator(tid(S.DETAILS_FULL_ROUTE, app));
    if ((await fullRoute.count()) > 0) {
      await expect(fullRoute).toBeVisible();
    } else {
      test.skip(true, 'Full route section not found');
    }
  });

  test('170: Transfer time is displayed for multi-segment flights', async ({ page }) => {
    // Look for transfer time information
    const transferTime = page.locator('[data-testid*="transfer"]');
    if ((await transferTime.count()) > 0) {
      await expect(transferTime.first()).toBeVisible();
    } else {
      test.skip(true, 'Transfer time not displayed (may be direct flight)');
    }
  });

  // ────────────────────────────────────────────────────────────────────────
  // Action Buttons (7 tests: 171-177)
  // ────────────────────────────────────────────────────────────────────────

  test('171: "Buy Ticket" button is visible and clickable', async ({ page, app }) => {
    const buyBtn = page.locator(tid(S.DETAILS_BUY_TICKET_BUTTON, app));
    if ((await buyBtn.count()) > 0) {
      await expect(buyBtn).toBeVisible();
      await expect(buyBtn).toBeEnabled();
    } else {
      test.skip(true, 'Buy Ticket button not found');
    }
  });

  test('172: "Register" button is visible and clickable', async ({ page, app }) => {
    const regBtn = page.locator(tid(S.DETAILS_REGISTRATION_BUTTON, app));
    if ((await regBtn.count()) > 0) {
      await expect(regBtn).toBeVisible();
      await expect(regBtn).toBeEnabled();
    } else {
      test.skip(true, 'Registration button not found');
    }
  });

  test('173: "Print" button is visible and clickable', async ({ page, app }) => {
    const printBtn = page.locator(tid(S.DETAILS_PRINT_BUTTON, app));
    if ((await printBtn.count()) > 0) {
      await expect(printBtn).toBeVisible();
      await expect(printBtn).toBeEnabled();
    } else {
      test.skip(true, 'Print button not found');
    }
  });

  test('174: "Share" button is visible and clickable', async ({ page, app }) => {
    const shareBtn = page.locator(tid(S.DETAILS_SHARE_BUTTON, app));
    if ((await shareBtn.count()) > 0) {
      await expect(shareBtn).toBeVisible();
      await expect(shareBtn).toBeEnabled();
    } else {
      test.skip(true, 'Share button not found');
    }
  });

  test('175: "Flight Status" button is visible and clickable', async ({ page, app }) => {
    const statusBtn = page.locator(tid(S.DETAILS_FLIGHT_STATUS_BUTTON, app));
    if ((await statusBtn.count()) > 0) {
      await expect(statusBtn).toBeVisible();
      await expect(statusBtn).toBeEnabled();
    } else {
      test.skip(true, 'Flight Status button not found');
    }
  });

  test('176: "Book Now" button leads to booking page', async ({ page }) => {
    // Look for a button that triggers booking
    const bookBtn = page.locator('button[data-testid*="booking"], a[href*="book"]');
    if ((await bookBtn.count()) > 0) {
      const href = await bookBtn.first().getAttribute('href');
      if (href) {
        expect(href).toBeTruthy();
      }
    } else {
      test.skip(true, 'Book Now button not found');
    }
  });

  test('177: Share button opens share dialog', async ({ page, app }) => {
    const shareBtn = page.locator(tid(S.DETAILS_SHARE_BUTTON, app));
    if ((await shareBtn.count()) > 0) {
      await shareBtn.first().click();
      await page.waitForTimeout(500);
      // Check if a dialog or modal opened
      const dialog = page.locator('[role="dialog"], .modal, .share-dialog');
      const dialogOrClipboard =
        (await dialog.count()) > 0 ||
        (await page.evaluate(() => navigator.clipboard !== undefined));
      expect(dialogOrClipboard).toBeTruthy();
    } else {
      test.skip(true, 'Share button not found');
    }
  });

  // ────────────────────────────────────────────────────────────────────────
  // Additional Info & Details (4 tests: 178-181)
  // ────────────────────────────────────────────────────────────────────────

  test('178: Equipment info (aircraft type) is displayed', async ({ page }) => {
    // Look for aircraft/equipment information
    const equipment = page.locator('[data-testid*="equipment"], [data-testid*="aircraft"]');
    if ((await equipment.count()) > 0) {
      await expect(equipment.first()).toBeVisible();
    } else {
      test.skip(true, 'Equipment info not displayed');
    }
  });

  test('179: Codeshare info (if applicable) is displayed', async ({ page }) => {
    // Look for codeshare information
    const codeshare = page.locator('[data-testid*="codeshare"]');
    if ((await codeshare.count()) > 0) {
      await expect(codeshare.first()).toBeVisible();
    } else {
      test.skip(true, 'Codeshare info not displayed (may not apply)');
    }
  });

  test('180: Frequent flyer/baggage info is displayed', async ({ page }) => {
    // Look for baggage or frequent flyer information
    const baggage = page.locator(
      '[data-testid*="baggage"], [data-testid*="miles"], [data-testid*="frequent"]',
    );
    if ((await baggage.count()) > 0) {
      await expect(baggage.first()).toBeVisible();
    } else {
      test.skip(true, 'Baggage/frequent flyer info not displayed (may be optional)');
    }
  });

  test('181: Page renders without console errors', async ({ page }) => {
    // Collect all console messages from the page
    const errors: string[] = [];
    page.on('console', (msg) => {
      if (msg.type() === 'error') {
        errors.push(msg.text());
      }
    });

    // Check for uncaught exceptions
    page.on('pageerror', (error) => {
      errors.push(error.toString());
    });

    // Wait a bit for any delayed errors
    await page.waitForTimeout(500);

    // Filter out known safe errors and network-related errors
    const safeErrors = errors.filter(
      (err) =>
        !err.includes('Loading chunk') &&
        !err.includes('NetworkError') &&
        !err.includes('404') &&
        !err.includes('CORS') &&
        !err.includes('Failed to fetch') &&
        !err.includes('aeroflot.ru'),
    );

    expect(safeErrors).toEqual([]);
  });
});
