import { expect, type Page, type Locator } from '@playwright/test';
import type { Flight, FlightStatus, FlightDirection } from '../../src/entities/flight/types';
import type { ScheduleEntry, ScheduleSearchParams } from '../../src/entities/schedule/types';
import type { Airport } from '../../src/entities/airport/types';
import type { Destination } from '../../src/entities/destination/types';

// ============================================================================
// Test Data Generators
// ============================================================================

export const CITIES = [
  { code: 'MOW', name: 'Moscow', nameRu: 'Москва' },
  { code: 'LED', name: 'Saint Petersburg', nameRu: 'Санкт-Петербург' },
  { code: 'AER', name: 'Sochi', nameRu: 'Сочи' },
  { code: 'OVB', name: 'Novosibirsk', nameRu: 'Новосибирск' },
  { code: 'KRR', name: 'Krasnodar', nameRu: 'Краснодар' },
  { code: 'SVX', name: 'Yekaterinburg', nameRu: 'Екатеринбург' },
  { code: 'KJA', name: 'Krasnoyarsk', nameRu: 'Красноярск' },
  { code: 'GOJ', name: 'Nizhny Novgorod', nameRu: 'Нижний Новгород' },
  { code: 'KUF', name: 'Samara', nameRu: 'Самара' },
  { code: 'UFA', name: 'Ufa', nameRu: 'Уфа' },
  { code: 'KZN', name: 'Kazan', nameRu: 'Казань' },
  { code: 'ROV', name: 'Rostov-on-Don', nameRu: 'Ростов-на-Дону' },
  { code: 'VVO', name: 'Vladivostok', nameRu: 'Владивосток' },
  { code: 'KHV', name: 'Khabarovsk', nameRu: 'Хабаровск' },
  { code: 'IKT', name: 'Irkutsk', nameRu: 'Иркутск' },
  { code: 'OMS', name: 'Omsk', nameRu: 'Омск' },
  { code: 'KGD', name: 'Kaliningrad', nameRu: 'Калининград' },
  { code: 'MRV', name: 'Mineralnye Vody', nameRu: 'Минеральные Воды' },
  { code: 'MCX', name: 'Makhachkala', nameRu: 'Махачкала' },
  { code: 'AAQ', name: 'Anapa', nameRu: 'Анапа' },
] as const;

export const AIRPORTS = [
  { code: 'SVO', name: 'Sheremetyevo', cityCode: 'MOW', cityName: 'Moscow', countryCode: 'RU' },
  { code: 'DME', name: 'Domodedovo', cityCode: 'MOW', cityName: 'Moscow', countryCode: 'RU' },
  { code: 'VKO', name: 'Vnukovo', cityCode: 'MOW', cityName: 'Moscow', countryCode: 'RU' },
  {
    code: 'LED',
    name: 'Pulkovo',
    cityCode: 'LED',
    cityName: 'Saint Petersburg',
    countryCode: 'RU',
  },
  { code: 'AER', name: 'Adler', cityCode: 'AER', cityName: 'Sochi', countryCode: 'RU' },
  { code: 'OVB', name: 'Tolmachevo', cityCode: 'OVB', cityName: 'Novosibirsk', countryCode: 'RU' },
  { code: 'KRR', name: 'Pashkovsky', cityCode: 'KRR', cityName: 'Krasnodar', countryCode: 'RU' },
  { code: 'SVX', name: 'Koltsovo', cityCode: 'SVX', cityName: 'Yekaterinburg', countryCode: 'RU' },
  { code: 'KJA', name: 'Emelyanovo', cityCode: 'KJA', cityName: 'Krasnoyarsk', countryCode: 'RU' },
  {
    code: 'GOJ',
    name: 'Strigino',
    cityCode: 'GOJ',
    cityName: 'Nizhny Novgorod',
    countryCode: 'RU',
  },
] as const;

export const FLIGHT_NUMBERS = [
  'SU 1124',
  'SU 1076',
  'SU 6170',
  'SU 1208',
  'SU 1108',
  'SU 6245',
  'SU 1455',
  'SU 1483',
  'SU 1759',
  'SU 6268',
  'SU 6132',
  'SU 1525',
  'SU 1400',
  'SU 1510',
  'SU 1190',
  'SU 1130',
  'SU 1234',
  'SU 6310',
  'SU 1350',
  'SU 1720',
] as const;

export const AIRLINE_CODES = ['SU', 'FV'] as const;

export const AIRLINE_NAMES = {
  SU: 'Aeroflot',
  FV: 'Rossiya',
} as const;

export const AIRCRAFT_TYPES = [
  'Airbus A320',
  'Airbus A321',
  'Airbus A321neo',
  'Boeing 737-800',
  'Boeing 777-300',
  'Boeing 777-300ER',
  'Sukhoi SuperJet 100',
] as const;

export const STATUS_TYPES: FlightStatus[] = [
  'scheduled',
  'checkin',
  'boarding',
  'departed',
  'inFlight',
  'landed',
  'arrived',
  'delayed',
  'cancelled',
  'gateChanged',
];

// ============================================================================
// Flight Data Generators
// ============================================================================

export function generateFlightId(): string {
  return `fl-${Math.random().toString(36).substring(2, 10)}`;
}

export function generateFlightNumber(): string {
  const num = Math.floor(Math.random() * 9000) + 1000;
  return `SU ${num}`;
}

export function generateFlight({
  direction = 'departure',
  date = new Date().toISOString().split('T')[0],
  cityCode = 'MOW',
  status = 'scheduled',
  flightNumber = generateFlightNumber(),
  airlineCode = 'SU',
  aircraftType = 'Airbus A320',
}: {
  direction?: FlightDirection;
  date?: string;
  cityCode?: string;
  status?: FlightStatus;
  flightNumber?: string;
  airlineCode?: (typeof AIRLINE_CODES)[number];
  aircraftType?: (typeof AIRCRAFT_TYPES)[number];
} = {}): Flight {
  const depCity = CITIES.find((c) => c.code === cityCode) || CITIES[0];
  const arrCity = CITIES.find((c) => c.code !== cityCode) || CITIES[1];

  const depAirport = AIRPORTS.find((a) => a.cityCode === cityCode) || AIRPORTS[0];
  const arrAirport =
    AIRPORTS.find((a) => a.cityCode === arrCity.code && a.code !== depAirport.code) || AIRPORTS[1];

  const depTime = `${Math.floor(Math.random() * 23)}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`;
  const arrTime = `${Math.floor(Math.random() * 23)}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`;

  const flightId = generateFlightId();

  return {
    id: flightId,
    flightNumber,
    airlineCode,
    airlineName: AIRLINE_NAMES[airlineCode as keyof typeof AIRLINE_NAMES],
    aircraftType,
    direction,
    status,
    date,
    departure: {
      airportCode: depAirport.code,
      airportName: depAirport.name,
      cityCode: depCity.code,
      cityName: depCity.name,
      terminal:
        Math.random() > 0.5 ? undefined : ['A', 'B', 'C', 'D'][Math.floor(Math.random() * 4)],
      time: {
        scheduled: `${date}T${depTime}:00+03:00`,
        actual:
          status === 'departed' || status === 'inFlight' || status === 'arrived'
            ? `${date}T${depTime}:00+03:00`
            : undefined,
      },
    },
    arrival: {
      airportCode: arrAirport.code,
      airportName: arrAirport.name,
      cityCode: arrCity.code,
      cityName: arrCity.name,
      terminal: Math.random() > 0.5 ? undefined : ['1', '2', '3'][Math.floor(Math.random() * 3)],
      time: {
        scheduled: `${date}T${arrTime}:00+03:00`,
        actual: status === 'arrived' ? `${date}T${arrTime}:00+03:00` : undefined,
        expected: status === 'delayed' ? `${date}T${arrTime}:00+03:00` : undefined,
      },
    },
    boarding:
      status === 'boarding' || status === 'departed' || status === 'inFlight'
        ? {
            gate: `${Math.floor(Math.random() * 50) + 1}`,
            status: status === 'boarding' ? 'Идёт посадка' : 'Закончена',
            startTime: `${date}T${depTime}:00+03:00`,
            endTime: `${date}T${depTime}:00+03:00`,
          }
        : undefined,
    arrivalInfo:
      status === 'arrived' || status === 'landed'
        ? {
            baggageBelt: `${Math.floor(Math.random() * 10) + 1}`,
            transfer: Math.random() > 0.5 ? 'Тран' : undefined,
          }
        : undefined,
    checkin:
      status === 'checkin' || status === 'boarding' || status === 'departed'
        ? {
            status: status === 'checkin' ? 'В процессе' : 'Закончена',
            startTime: `${date}T${depTime}:00+03:00`,
            endTime: `${date}T${depTime}:00+03:00`,
          }
        : undefined,
    deplaning:
      status === 'arrived' || status === 'landed'
        ? {
            status: 'В процессе',
            startTime: `${date}T${arrTime}:00+03:00`,
            endTime: `${date}T${arrTime}:00+03:00`,
            transfer: Math.random() > 0.5 ? 'Трап' : undefined,
            gate: `${Math.floor(Math.random() * 50) + 1}`,
            baggageBelt: `${Math.floor(Math.random() * 10) + 1}`,
          }
        : undefined,
    aircraft: {
      type: aircraftType,
      name: Math.random() > 0.5 ? `${aircraftType} ${Math.floor(Math.random() * 100)}` : undefined,
      totalSeats: Math.floor(Math.random() * 300) + 100,
      economySeats: Math.floor(Math.random() * 250) + 100,
      businessSeats: Math.floor(Math.random() * 20) + 5,
      previousFlight: Math.random() > 0.5 ? generateFlightNumber() : undefined,
    },
    catering:
      Math.random() > 0.5
        ? {
            economy: true,
            business: true,
          }
        : undefined,
    schedule: {
      scheduledDeparture: `${date}T${depTime}:00+03:00`,
      scheduledArrival: `${date}T${arrTime}:00+03:00`,
      duration: `${Math.floor(Math.random() * 5) + 1}ч. ${Math.floor(Math.random() * 59)}мин.`,
      utcOffset: 'UTC+03:00',
      operatingDays: [1, 2, 3, 4, 5, 6, 7],
      weekRange: `* Расписание на неделю ${date}`,
    },
    lastUpdated:
      status === 'departed' || status === 'arrived'
        ? `${depTime} ${date.replace(/-/g, '.')}`
        : undefined,
  };
}

export function generateFlights(
  count: number = 20,
  options: Partial<Parameters<typeof generateFlight>[0]> = {},
): Flight[] {
  return Array.from({ length: count }, () => generateFlight(options));
}

// ============================================================================
// Schedule Data Generators
// ============================================================================

export function generateScheduleEntry({
  from = 'MOW',
  to = 'AER',
  dateFrom = new Date().toISOString().split('T')[0],
  dateTo = new Date(Date.now() + 7 * 24 * 60 * 60 * 1000).toISOString().split('T')[0],
  direct = true,
}: {
  from?: string;
  to?: string;
  dateFrom?: string;
  dateTo?: string;
  direct?: boolean;
} = {}): ScheduleEntry {
  const depCity = CITIES.find((c) => c.code === from) || CITIES[0];
  const arrCity = CITIES.find((c) => c.code === to) || CITIES[1];

  const depAirport = AIRPORTS.find((a) => a.cityCode === from) || AIRPORTS[0];
  const arrAirport = AIRPORTS.find((a) => a.cityCode === to) || AIRPORTS[1];

  const depTime = `${Math.floor(Math.random() * 23)}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`;
  const arrTime = `${Math.floor(Math.random() * 23)}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}`;

  return {
    id: generateFlightId(),
    flightNumber: generateFlightNumber(),
    airlineCode: 'SU',
    airlineName: 'Aeroflot',
    aircraftType: AIRCRAFT_TYPES[Math.floor(Math.random() * AIRCRAFT_TYPES.length)],
    departureCity: depCity.name,
    departureCityCode: depCity.code,
    departureAirport: depAirport.name,
    departureTime: depTime,
    arrivalCity: arrCity.name,
    arrivalCityCode: arrCity.code,
    arrivalAirport: arrAirport.name,
    arrivalTime: arrTime,
    daysOfWeek: [1, 2, 3, 4, 5, 6, 7],
    effectiveFrom: dateFrom,
    effectiveTo: dateTo,
    direct,
  };
}

export function generateScheduleEntries(
  count: number = 50,
  options: Partial<Parameters<typeof generateScheduleEntry>[0]> = {},
): ScheduleEntry[] {
  return Array.from({ length: count }, () => generateScheduleEntry(options));
}

// ============================================================================
// Destination Data Generators
// ============================================================================

export function generateDestination({
  departureCity = 'MOW',
  arrivalCity = 'AER',
  flightCount = Math.floor(Math.random() * 100) + 1,
  dates = [new Date().toISOString().split('T')[0]],
}: {
  departureCity?: string;
  arrivalCity?: string;
  flightCount?: number;
  dates?: string[];
} = {}): Destination {
  const depCity = CITIES.find((c) => c.code === departureCity) || CITIES[0];
  const arrCity = CITIES.find((c) => c.code === arrivalCity) || CITIES[1];

  return {
    id: `dest-${departureCity}-${arrivalCity}`,
    departureCity: depCity.name,
    departureCityCode: depCity.code,
    arrivalCity: arrCity.name,
    arrivalCityCode: arrCity.code,
    flightCount,
    dates,
  };
}

export function generateDestinations(count: number = 20): Destination[] {
  return Array.from({ length: count }, () => generateDestination());
}

// ============================================================================
// URL Pattern Helpers
// ============================================================================

export function buildRouteParam(cityCode: string, date: string): string {
  return `${cityCode}-${date.replace(/-/g, '')}`;
}

export function buildLocalePath(locale: string, path: string): string {
  return `/${locale}${path}`;
}

export function buildOnlineBoardPath(
  direction: 'departure' | 'arrival',
  cityCode: string,
  date: string,
): string {
  return `/onlineboard/${direction}/${buildRouteParam(cityCode, date)}`;
}

export function buildSchedulePath(): string {
  return '/schedule';
}

export function buildFlightsMapPath(): string {
  return '/flights-map';
}

export function buildFlightDetailsPath(flightNumber: string, date: string): string {
  const slug = `${flightNumber.replace(/\s+/g, '')}-${date.replace(/-/g, '')}`;
  return `/${slug}`;
}

// ============================================================================
// Test Assertion Helpers
// ============================================================================

export async function expectUrlToMatch(page: Page, pattern: RegExp | string): Promise<void> {
  const url = page.url();
  if (typeof pattern === 'string') {
    expect(url).toContain(pattern);
  } else {
    expect(url).toMatch(pattern);
  }
}

export async function expectElementToBeVisible(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeVisible({ timeout: 10000 });
}

export async function expectElementToBeHidden(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeHidden({ timeout: 10000 });
}

export async function expectElementToHaveText(
  locator: Locator,
  text: string | RegExp,
  message?: string,
): Promise<void> {
  await expect(locator).toHaveText(text, { timeout: 10000 });
}

export async function expectElementToContainText(
  locator: Locator,
  text: string,
  message?: string,
): Promise<void> {
  await expect(locator).toContainText(text, { timeout: 10000 });
}

export async function expectElementToHaveAttribute(
  locator: Locator,
  attribute: string,
  value: string,
  message?: string,
): Promise<void> {
  await expect(locator).toHaveAttribute(attribute, value, { timeout: 10000 });
}

export async function expectElementToHaveClass(
  locator: Locator,
  className: string,
  message?: string,
): Promise<void> {
  await expect(locator).toHaveClass(new RegExp(className), { timeout: 10000 });
}

export async function expectElementToBeEnabled(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeEnabled({ timeout: 10000 });
}

export async function expectElementToBeDisabled(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeDisabled({ timeout: 10000 });
}

export async function expectElementToBeChecked(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeChecked({ timeout: 10000 });
}

export async function expectElementToBeUnchecked(
  locator: Locator,
  message?: string,
): Promise<void> {
  await expect(locator).not.toBeChecked({ timeout: 10000 });
}

export async function expectElementToHaveValue(
  locator: Locator,
  value: string,
  message?: string,
): Promise<void> {
  await expect(locator).toHaveValue(value, { timeout: 10000 });
}

export async function expectElementToHaveCount(
  locator: Locator,
  count: number,
  message?: string,
): Promise<void> {
  await expect(locator).toHaveCount(count, { timeout: 10000 });
}

export async function expectElementToBeFocused(locator: Locator, message?: string): Promise<void> {
  await expect(locator).toBeFocused({ timeout: 10000 });
}

export async function expectElementNotToBeFocused(
  locator: Locator,
  message?: string,
): Promise<void> {
  await expect(locator).not.toBeFocused({ timeout: 10000 });
}

// ============================================================================
// Flight Search Helpers
// ============================================================================

export async function searchFlightByNumber(
  page: Page,
  flightNumber: string,
  date?: string,
): Promise<void> {
  const dateParam = date || new Date().toISOString().split('T')[0];
  await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', dateParam)}`);
  await page.waitForLoadState('networkidle');

  const searchInput = page.locator('[data-testid="flight-search-input"]');
  await searchInput.fill(flightNumber);
  await searchInput.press('Enter');
  await page.waitForLoadState('networkidle');
}

export async function searchFlightByRoute(
  page: Page,
  departureCity: string,
  arrivalCity: string,
  date?: string,
): Promise<void> {
  const dateParam = date || new Date().toISOString().split('T')[0];
  await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', dateParam)}`);
  await page.waitForLoadState('networkidle');

  const routeTab = page.locator('[data-testid="route-search-tab"]');
  await routeTab.click();
  await page.waitForTimeout(500);

  const departureInput = page.locator('[data-testid="departure-city-input"]');
  const arrivalInput = page.locator('[data-testid="arrival-city-input"]');

  await departureInput.fill(departureCity);
  await page.waitForTimeout(500);
  await departureInput.press('Enter');
  await page.waitForTimeout(500);

  await arrivalInput.fill(arrivalCity);
  await page.waitForTimeout(500);
  await arrivalInput.press('Enter');
  await page.waitForLoadState('networkidle');
}

export async function searchFlightByDate(page: Page, date: string): Promise<void> {
  await page.goto(`/ru-ru/onlineboard/departure/MOW-${buildRouteParam('MOW', date)}`);
  await page.waitForLoadState('networkidle');
}

export async function openFlightDetails(page: Page, flightIndex: number = 0): Promise<void> {
  const flightCards = page.locator('[data-testid="flight-card"]');
  await expect(flightCards).toHaveCount(flightIndex + 1, { timeout: 10000 });
  await flightCards.nth(flightIndex).click();
  await page.waitForLoadState('networkidle');
}

export async function verifyFlightCard(
  page: Page,
  flight: Flight,
  index: number = 0,
): Promise<void> {
  const flightCards = page.locator('[data-testid="flight-card"]');
  const count = await flightCards.count();
  await expect(flightCards).toHaveCount(count);

  const card = flightCards.nth(index);

  await expect(card.getByText(flight.flightNumber)).toBeVisible();
  await expect(card.getByText(flight.airlineName)).toBeVisible();
  await expect(card.getByText(flight.departure.cityName)).toBeVisible();
  await expect(card.getByText(flight.arrival.cityName)).toBeVisible();

  const depTime = flight.departure.time.scheduled.slice(11, 16);
  await expect(card.getByText(depTime)).toBeVisible();

  const arrTime = flight.arrival.time.scheduled.slice(11, 16);
  await expect(card.getByText(arrTime)).toBeVisible();
}

export async function verifyFlightDetails(page: Page, flight: Flight): Promise<void> {
  await expect(page.getByText(flight.flightNumber)).toBeVisible();
  await expect(page.getByText(flight.airlineName)).toBeVisible();
  await expect(page.getByText(flight.departure.cityName)).toBeVisible();
  await expect(page.getByText(flight.arrival.cityName)).toBeVisible();

  if (flight.aircraft?.type) {
    await expect(page.getByText(flight.aircraft.type)).toBeVisible();
  }

  if (flight.schedule?.duration) {
    await expect(page.getByText(flight.schedule.duration)).toBeVisible();
  }
}

// ============================================================================
// Date Helpers
// ============================================================================

export function formatDateForUrl(date: string | Date): string {
  const d = typeof date === 'string' ? date : date.toISOString().split('T')[0];
  return d.replace(/-/g, '');
}

export function formatDateForDisplay(date: string | Date, locale: string = 'ru'): string {
  const d = typeof date === 'string' ? date : date.toISOString().split('T')[0];
  const dateObj = new Date(d);
  const options: Intl.DateTimeFormatOptions = { day: 'numeric', month: 'short' };
  return new Date(d).toLocaleDateString(locale, options);
}

export function getToday(): string {
  return new Date().toISOString().split('T')[0];
}

export function getTomorrow(): string {
  const d = new Date();
  d.setDate(d.getDate() + 1);
  return d.toISOString().split('T')[0];
}

export function getYesterday(): string {
  const d = new Date();
  d.setDate(d.getDate() - 1);
  return d.toISOString().split('T')[0];
}

export function getFutureDate(days: number): string {
  const d = new Date();
  d.setDate(d.getDate() + days);
  return d.toISOString().split('T')[0];
}

export function getPastDate(days: number): string {
  const d = new Date();
  d.setDate(d.getDate() - days);
  return d.toISOString().split('T')[0];
}

// ============================================================================
// Error Response Generators
// ============================================================================

export function generateNotFoundError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 404,
    body: {
      error: 'Not Found',
      message: 'The requested resource was not found',
    },
  };
}

export function generateBadRequestError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 400,
    body: {
      error: 'Bad Request',
      message: 'Invalid request parameters',
    },
  };
}

export function generateUnauthorizedError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 401,
    body: {
      error: 'Unauthorized',
      message: 'Authentication required',
    },
  };
}

export function generateForbiddenError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 403,
    body: {
      error: 'Forbidden',
      message: 'Access denied',
    },
  };
}

export function generateServerError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 500,
    body: {
      error: 'Internal Server Error',
      message: 'An unexpected error occurred',
    },
  };
}

export function generateTimeoutError(): {
  status: number;
  body: { error: string; message: string };
} {
  return {
    status: 504,
    body: {
      error: 'Gateway Timeout',
      message: 'The request took too long to process',
    },
  };
}

// ============================================================================
// Async Wait Utilities (for complex async operations)
// ============================================================================

/**
 * Wait for an element with an extended timeout for slow async operations.
 * Used for map initialization, calendar loading, etc.
 */
export async function waitForElementExtended(
  page: Page,
  selector: string,
  timeoutMs: number = 20000,
): Promise<void> {
  try {
    await page.locator(selector).first().waitFor({ timeout: timeoutMs });
  } catch (error) {
    // If element doesn't appear, log but don't fail - test will fail naturally if needed
    console.log(`Extended wait for "${selector}" timed out after ${timeoutMs}ms`);
  }
}

/**
 * Wait for a locator with extended timeout.
 */
export async function waitForLocatorExtended(
  locator: Locator,
  timeoutMs: number = 20000,
): Promise<void> {
  try {
    await locator.first().waitFor({ timeout: timeoutMs, state: 'visible' });
  } catch (error) {
    // If element doesn't appear, log but don't fail
    console.log(`Extended wait for locator timed out after ${timeoutMs}ms`);
  }
}

/**
 * Retry an async operation with backoff.
 * Useful for flaky async operations or race conditions.
 */
export async function retryAsync<T>(
  fn: () => Promise<T>,
  maxRetries: number = 3,
  delayMs: number = 500,
): Promise<T> {
  let lastError: Error | undefined;
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      lastError = error as Error;
      if (i < maxRetries - 1) {
        await new Promise((resolve) => setTimeout(resolve, delayMs * (i + 1)));
      }
    }
  }
  throw lastError || new Error('Retry exhausted');
}

// ============================================================================
// Test Data Fixtures
// ============================================================================

export const FIXTURES = {
  flights: {
    departures: generateFlights(20, { direction: 'departure', cityCode: 'MOW' }),
    arrivals: generateFlights(20, { direction: 'arrival', cityCode: 'MOW' }),
    scheduled: generateFlights(20, { status: 'scheduled' }),
    departed: generateFlights(20, { status: 'departed' }),
    delayed: generateFlights(20, { status: 'delayed' }),
    cancelled: generateFlights(20, { status: 'cancelled' }),
  },
  schedule: {
    entries: generateScheduleEntries(50),
  },
  destinations: {
    entries: generateDestinations(20),
  },
  airports: {
    entries: AIRPORTS,
  },
  cities: {
    entries: CITIES,
  },
  errors: {
    notFound: generateNotFoundError(),
    badRequest: generateBadRequestError(),
    unauthorized: generateUnauthorizedError(),
    forbidden: generateForbiddenError(),
    serverError: generateServerError(),
    timeout: generateTimeoutError(),
  },
};

export default FIXTURES;
