import type { Page } from 'playwright';
import { StepId } from '../../../../domain/value-objects/StepId';
import type { AutomationResultDTO } from '../../../../application/dto/AutomationResultDTO';
import type { ClickResultDTO } from '../../../../application/dto/ClickResultDTO';
import type { FormFillResultDTO } from '../../../../application/dto/FormFillResultDTO';
import type { AuthenticationServicePort } from '../../../../application/ports/AuthenticationServicePort';
import type { LoggerPort } from '../../../../application/ports/LoggerPort';
import { CheckoutPrice } from '../../../../domain/value-objects/CheckoutPrice';
import { CheckoutState } from '../../../../domain/value-objects/CheckoutState';
import { CheckoutConfirmation } from '../../../../domain/value-objects/CheckoutConfirmation';
import type { PlaywrightConfig } from './PlaywrightAutomationAdapter';
import { PlaywrightBrowserSession } from './PlaywrightBrowserSession';
import { IRacingDomNavigator } from '../dom/IRacingDomNavigator';
import { IRacingDomInteractor } from '../dom/IRacingDomInteractor';
import { IRACING_SELECTORS } from '../dom/IRacingSelectors';

import type {
  PageStateValidation,
  PageStateValidationResult,
} from '../../../../domain/services/PageStateValidator';
import type { Result } from '@gridpilot/shared/application/Result';

interface WizardStepOrchestratorDeps {
  config: Required<PlaywrightConfig>;
  browserSession: PlaywrightBrowserSession;
  navigator: IRacingDomNavigator;
  interactor: IRacingDomInteractor;
  authService: AuthenticationServicePort;
  logger?: LoggerPort | undefined;
  totalSteps: number;
  getCheckoutConfirmationCallback: () => ((
    price: CheckoutPrice,
    state: CheckoutState,
  ) => Promise<CheckoutConfirmation>) | undefined;
  overlay: {
    updateOverlay(step: number, customMessage?: string): Promise<void>;
    showOverlayComplete(success: boolean, message?: string): Promise<void>;
  };
  debug: {
    saveProactiveDebugInfo(
      step: number,
    ): Promise<{ screenshotPath?: string; htmlPath?: string }>;
    saveDebugInfo(
      stepName: string,
      error: Error,
    ): Promise<{ screenshotPath?: string; htmlPath?: string }>;
  };
  guards: {
    waitIfPaused(): Promise<void>;
    checkAndHandleClose(): Promise<void>;
    dismissModals(): Promise<void>;
    dismissDatetimePickers(): Promise<void>;
  };
  helpers: {
    handleLogin(): Promise<AutomationResultDTO>;
    validatePageState(
      validation: PageStateValidation,
    ): Promise<Result<PageStateValidationResult, Error>>;
    handleCheckoutConfirmation(): Promise<void>;
  };
}

export class WizardStepOrchestrator {
  private readonly config: Required<PlaywrightConfig>;
  private readonly browserSession: PlaywrightBrowserSession;
  private readonly navigator: IRacingDomNavigator;
  private readonly interactor: IRacingDomInteractor;
  private readonly authService: AuthenticationServicePort;
  private readonly logger: LoggerPort | undefined;
  private readonly totalSteps: number;
  private readonly getCheckoutConfirmationCallbackInternal: WizardStepOrchestratorDeps['getCheckoutConfirmationCallback'];
  private readonly overlay: WizardStepOrchestratorDeps['overlay'];
  private readonly debug: WizardStepOrchestratorDeps['debug'];
  private readonly guards: WizardStepOrchestratorDeps['guards'];
  private readonly helpers: WizardStepOrchestratorDeps['helpers'];

  constructor(deps: WizardStepOrchestratorDeps) {
    this.config = deps.config;
    this.browserSession = deps.browserSession;
    this.navigator = deps.navigator;
    this.interactor = deps.interactor;
    this.authService = deps.authService;
    this.logger = deps.logger;
    this.totalSteps = deps.totalSteps;
    this.getCheckoutConfirmationCallbackInternal =
      deps.getCheckoutConfirmationCallback;
    this.overlay = deps.overlay;
    this.debug = deps.debug;
    this.guards = deps.guards;
    this.helpers = deps.helpers;
  }

  private get page(): Page | null {
    return this.browserSession.getPage();
  }

  private isRealMode(): boolean {
    return this.config.mode === 'real';
  }

  private log(
    level: 'debug' | 'info' | 'warn' | 'error',
    message: string,
    context?: Record<string, unknown>,
  ): void {
    if (!this.logger) {
      return;
    }
    const logger = this.logger as Record<
      'debug' | 'info' | 'warn' | 'error',
      (msg: string, ctx?: Record<string, unknown>) => void
    >;
    logger[level](message, context);
  }

  private async waitIfPaused(): Promise<void> {
    await this.guards.waitIfPaused();
  }

  private async checkAndHandleClose(): Promise<void> {
    await this.guards.checkAndHandleClose();
  }

  private async updateOverlay(
    step: number,
    customMessage?: string,
  ): Promise<void> {
    await this.overlay.updateOverlay(step, customMessage);
  }

  private async saveProactiveDebugInfo(
    step: number,
  ): Promise<{ screenshotPath?: string; htmlPath?: string }> {
    return this.debug.saveProactiveDebugInfo(step);
  }

  private async dismissModals(): Promise<void> {
    await this.guards.dismissModals();
  }

  private async handleLogin(): Promise<AutomationResultDTO> {
    return this.helpers.handleLogin();
  }

  private async waitForStep(stepNumber: number): Promise<void> {
    await this.navigator.waitForStep(stepNumber);
  }

  private async clickAction(action: string): Promise<ClickResultDTO> {
    return this.interactor.clickAction(action);
  }

  private async fillFieldWithFallback(
    fieldName: string,
    value: string,
  ): Promise<FormFillResultDTO> {
    return this.interactor.fillFieldWithFallback(fieldName, value);
  }

  private async clickNextButton(nextStepName: string): Promise<void> {
    await this.interactor.clickNextButton(nextStepName);
  }

  private async waitForWizardStep(
    stepName: keyof typeof IRACING_SELECTORS.wizard.stepContainers,
  ): Promise<void> {
    await this.navigator.waitForWizardStep(stepName);
  }

  private async checkWizardDismissed(currentStep: number): Promise<void> {
    await this.navigator.checkWizardDismissed(currentStep);
  }

  private async validatePageState(
    validation: PageStateValidation,
  ): Promise<Result<PageStateValidationResult, Error>> {
    return this.helpers.validatePageState(validation);
  }

  private async detectCurrentWizardPage(): Promise<string | null> {
    return this.navigator.detectCurrentWizardPage();
  }

  private synchronizeStepCounter(
    expectedStep: number,
    actualPage: string | null,
  ): number {
    return this.navigator.synchronizeStepCounter(expectedStep, actualPage);
  }

  private async clickAddCarButton(): Promise<void> {
    await this.interactor.clickAddCarButton();
  }

  private async waitForAddCarModal(): Promise<void> {
    await this.interactor.waitForAddCarModal();
  }

  private async fillField(
    fieldName: string,
    value: string,
  ): Promise<FormFillResultDTO> {
    return this.interactor.fillField(fieldName, value);
  }

  private async selectFirstSearchResult(): Promise<void> {
    await this.interactor.selectFirstSearchResult();
  }

  private async clickAddTrackButton(): Promise<void> {
    await this.interactor.clickAddTrackButton();
  }

  private async waitForAddTrackModal(): Promise<void> {
    await this.interactor.waitForAddTrackModal();
  }

  private async selectDropdown(name: string, value: string): Promise<void> {
    await this.interactor.selectDropdown(name, value);
  }

  private async setToggle(name: string, checked: boolean): Promise<void> {
    await this.interactor.setToggle(name, checked);
  }

  private async setSlider(name: string, value: number): Promise<void> {
    await this.interactor.setSlider(name, value);
  }

  private async dismissDatetimePickers(): Promise<void> {
    await this.guards.dismissDatetimePickers();
  }

  private async selectWeatherType(weatherType: string): Promise<void> {
    await this.interactor.selectWeatherType(weatherType);
  }

  private get checkoutConfirmationCallback():
    | ((
        price: CheckoutPrice,
        state: CheckoutState,
      ) => Promise<CheckoutConfirmation>)
    | undefined {
    return this.getCheckoutConfirmationCallbackInternal();
  }

  private async handleCheckoutConfirmation(): Promise<void> {
    await this.helpers.handleCheckoutConfirmation();
  }

  private async showOverlayComplete(
    success: boolean,
    message?: string,
  ): Promise<void> {
    await this.overlay.showOverlayComplete(success, message);
  }

  private async saveDebugInfo(
    stepName: string,
    error: Error,
  ): Promise<{ screenshotPath?: string; htmlPath?: string }> {
    return this.debug.saveDebugInfo(stepName, error);
  }

  async executeStep(
    stepId: StepId,
    config: Record<string, unknown>,
  ): Promise<AutomationResultDTO> {
    if (!this.page) {
      return { success: false, error: 'Browser not connected' };
    }

    const step = stepId.value;
    this.log('info', 'Executing step', { step, mode: this.config.mode });

    try {
      if (this.isRealMode()) {
        await this.waitIfPaused();
        await this.checkAndHandleClose();
      }

      if (this.isRealMode()) {
        await this.updateOverlay(step);
      }

      const beforeDebugPaths = await this.saveProactiveDebugInfo(step);
      if (beforeDebugPaths.screenshotPath || beforeDebugPaths.htmlPath) {
        this.log('info', `Pre-step debug snapshot saved for step ${step}`, {
          screenshot: beforeDebugPaths.screenshotPath,
          html: beforeDebugPaths.htmlPath,
        });
      }

      await this.dismissModals();

      if (step === 1 && this.isRealMode()) {
        return this.handleLogin();
      }

      if (!this.isRealMode()) {
        await this.waitForStep(step);
      }

      switch (step) {
        case 1:
          break;

        case 2:
          if (!this.isRealMode()) {
            break;
          }
          await this.clickAction('create');
          break;

        case 3:
          if (this.isRealMode()) {
            await this.interactor.clickNewRaceInModal();
            const raceInfoFallback =
              IRACING_SELECTORS.wizard.stepContainers.raceInformation;
            const raceInfoNav =
              IRACING_SELECTORS.wizard.sidebarLinks.raceInformation;
            try {
              try {
                await this.page!.click(raceInfoNav);
                this.log('debug', 'Clicked wizard nav for Race Information', {
                  selector: raceInfoNav,
                });
              } catch (e) {
                this.log(
                  'debug',
                  'Wizard nav for Race Information not present (continuing)',
                  { error: String(e) },
                );
              }
              await this.page!.waitForSelector(raceInfoFallback, {
                state: 'attached',
                timeout: 5000,
              });
              this.log('info', 'Race Information panel found', {
                selector: raceInfoFallback,
              });
            } catch (err) {
              this.log(
                'warn',
                'Race Information panel not found with fallback selector, dumping #create-race-wizard innerHTML',
                { selector: raceInfoFallback },
              );
              const inner = await this.page!.evaluate(() => {
                const doc = (globalThis as { document?: Document }).document;
                return (
                  doc?.querySelector('#create-race-wizard')?.innerHTML || ''
                );
              });
              this.log(
                'debug',
                'create-race-wizard innerHTML (truncated)',
                { html: inner ? inner.substring(0, 2000) : '' },
              );
              try {
                await this.page!.click(raceInfoNav);
              } catch {
              }
              await this.page!.waitForSelector(raceInfoFallback, {
                state: 'attached',
                timeout: 10000,
              });
            }
          }

          if (config.sessionName) {
            await this.fillFieldWithFallback(
              'sessionName',
              String(config.sessionName),
            );
          }
          if (config.password) {
            await this.fillFieldWithFallback(
              'password',
              String(config.password),
            );
          }
          if (config.description) {
            await this.fillFieldWithFallback(
              'description',
              String(config.description),
            );
          }

          await this.clickNextButton('Server Details');
          break;

        case 4:
          if (this.isRealMode()) {
            await this.waitForWizardStep('serverDetails');
            await this.checkWizardDismissed(step);
          }
          if (config.region) {
            await this.selectDropdown('region', String(config.region));
          }
          if (config.startNow !== undefined) {
            await this.setToggle('startNow', Boolean(config.startNow));
          }
          await this.clickNextButton('Admins');
          break;

        case 5:
          if (this.isRealMode()) {
            await this.waitForWizardStep('admins');
            await this.checkWizardDismissed(step);
          } else {
            const adminSearch =
              (config.adminSearch ?? config.admin) as string | undefined;
            if (adminSearch) {
              await this.fillField('adminSearch', String(adminSearch));
            }
          }
          await this.clickNextButton('Time Limit');
          break;
 
        case 6:
          if (this.isRealMode()) {
            await this.waitForWizardStep('admins');
            await this.checkWizardDismissed(step);
          } else {
            const adminSearch =
              (config.adminSearch ?? config.admin) as string | undefined;
            if (adminSearch) {
              await this.fillField('adminSearch', String(adminSearch));
              const page = this.page;
              if (page) {
                await page.evaluate((term) => {
                  const doc = (globalThis as { document?: Document }).document;
                  if (!doc) {
                    return;
                  }
                  const root =
                    (doc.querySelector('#set-admins') as HTMLElement | null) ?? doc.body;
                  if (!root) {
                    return;
                  }
                  const rows = Array.from(
                    root.querySelectorAll<HTMLTableRowElement>(
                      'tbody[data-testid="admin-display-name-list"] tr',
                    ),
                  );
                  if (rows.length === 0) {
                    return;
                  }
                  const needle = String(term).toLowerCase();
                  for (const r of rows) {
                    const text = String(r.textContent || '').toLowerCase();
                    if (text.includes(needle)) {
                      r.setAttribute('data-selected-admin', 'true');
                      return;
                    }
                  }
                  rows[0]?.setAttribute('data-selected-admin', 'true');
                }, String(adminSearch));
              }
            }
          }
          await this.clickNextButton('Time Limit');
          break;

        case 7:
          if (this.isRealMode()) {
            await this.waitForWizardStep('timeLimit');
            await this.checkWizardDismissed(step);
          }
          if (config.practice !== undefined) {
            await this.setSlider('practice', Number(config.practice));
          }
          if (config.qualify !== undefined) {
            await this.setSlider('qualify', Number(config.qualify));
          }
          if (config.race !== undefined) {
            await this.setSlider('race', Number(config.race));
          }
          await this.clickNextButton('Cars');
          break;

        case 8:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              if (this.config.baseUrl) {
                const errorMsg = `Step 8 FAILED validation: Wizard auto-skip detected (expected "cars" but on "${actualPage}")`;
                this.log('error', errorMsg, { actualPage, skipOffset });
                throw new Error(errorMsg);
              }
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skipOffset,
              });
              return { success: true };
            }

            const carsFallbackSelector =
              IRACING_SELECTORS.wizard.stepContainers.cars;
            const carsNav = IRACING_SELECTORS.wizard.sidebarLinks.cars;
            try {
              this.log('debug', 'nav-click attempted for Cars', {
                navSelector: carsNav,
              });
              await this.page!.click(carsNav).catch(() => {});
              this.log('debug', 'Primary nav-click attempted', {
                selector: carsNav,
              });

              try {
                this.log(
                  'debug',
                  'Waiting for Cars panel using primary selector',
                  { selector: carsFallbackSelector },
                );
                await this.page!.waitForSelector(carsFallbackSelector, {
                  state: 'attached',
                  timeout: 5000,
                });
                this.log('info', 'Cars panel found', {
                  selector: carsFallbackSelector,
                });
              } catch (err) {
                this.log(
                  'warn',
                  'Cars panel not found with primary selector, capturing wizard HTML and retrying',
                  { selector: carsFallbackSelector },
                );
                const html = await this.page!
                  .innerHTML('#create-race-wizard')
                  .catch(() => '');
                this.log(
                  'debug',
                  'captured #create-race-wizard innerHTML (truncated)',
                  { html: html ? html.slice(0, 2000) : '' },
                );
                this.log('info', 'retry attempted for Cars nav-click', {
                  attempt: 1,
                });
                await this.page!.click(carsNav).catch(() => {});
                await this.page!.waitForSelector(carsFallbackSelector, {
                  state: 'attached',
                  timeout: 10000,
                });
                this.log('info', 'Cars panel found after retry', {
                  selector: carsFallbackSelector,
                });
              }
            } catch (e) {
              this.log('error', 'Failed waiting for Cars panel', {
                error: String(e),
                selector: carsFallbackSelector,
              });
            }
            await this.checkWizardDismissed(step);
          }

          this.log('info', 'Step 8: Validating page state before proceeding');
          const step8Validation = await this.validatePageState({
            expectedStep: 'cars',
            requiredSelectors: this.isRealMode()
              ? [IRACING_SELECTORS.wizard.stepContainers.cars]
              : ['#set-cars, .wizard-step[id*="cars"], .cars-panel'],
            forbiddenSelectors: [
              IRACING_SELECTORS.wizard.stepContainers.track,
            ],
          });

          if (step8Validation.isErr()) {
            const errorMsg = `Step 8 validation error: ${
              step8Validation.error?.message ?? 'unknown error'
            }`;
            this.log('error', errorMsg);
            throw new Error(errorMsg);
          }

          const step8ValidationResult = step8Validation.unwrap();
          this.log('info', 'Step 8 validation result', {
            isValid: step8ValidationResult.isValid,
            message: step8ValidationResult.message,
            missingSelectors: step8ValidationResult.missingSelectors,
            unexpectedSelectors: step8ValidationResult.unexpectedSelectors,
          });

          if (!step8ValidationResult.isValid) {
            const errorMsg = `Step 8 FAILED validation: ${step8ValidationResult.message}`;
            this.log('error', errorMsg, {
              missing: step8ValidationResult.missingSelectors,
              unexpected: step8ValidationResult.unexpectedSelectors,
            });
            throw new Error(errorMsg);
          }

          this.log('info', 'Step 8 validation passed - on Cars page');
          break;

        case 9:
          this.log('info', 'Step 9: Validating we are still on Cars page');

          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              if (this.config.baseUrl) {
                const errorMsg = `Step 9 FAILED validation: Wizard auto-skip detected (expected "cars" but on "${actualPage}")`;
                this.log('error', errorMsg, { actualPage, skipOffset });
                throw new Error(errorMsg);
              }
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skipOffset,
              });
              return { success: true };
            }

            const wizardFooter = await this.page!
              .locator('.wizard-footer')
              .innerText()
              .catch(() => '');
            this.log('info', 'Step 9: Current wizard footer', {
              footer: wizardFooter,
            });

            const onTrackPage =
              wizardFooter.includes('Track Options') ||
              (await this.page!
                .locator(IRACING_SELECTORS.wizard.stepContainers.track)
                .isVisible()
                .catch(() => false));

            if (onTrackPage) {
              const errorMsg = `Step 9 FAILED validation: Wizard footer indicates Track page while executing Cars-add-car step. Wizard footer: "${wizardFooter}"`;
              this.log('error', errorMsg);
              throw new Error(errorMsg);
            }
          }

          const validation = await this.validatePageState({
            expectedStep: 'cars',
            requiredSelectors: this.isRealMode()
              ? [
                  IRACING_SELECTORS.wizard.stepContainers.cars,
                  IRACING_SELECTORS.steps.addCarButton,
                ]
              : ['#set-cars, .wizard-step[id*="cars"], .cars-panel'],
            forbiddenSelectors: [
              IRACING_SELECTORS.wizard.stepContainers.track,
            ],
          });

          if (validation.isErr()) {
            const errorMsg = `Step 9 FAILED validation: ${
              validation.error?.message ?? 'unknown error'
            }`;
            this.log('error', errorMsg);
            throw new Error(errorMsg);
          }

          const validationResult = validation.unwrap();
          this.log('info', 'Step 9 validation result', {
            isValid: validationResult.isValid,
            message: validationResult.message,
            missingSelectors: validationResult.missingSelectors,
            unexpectedSelectors: validationResult.unexpectedSelectors,
          });

          if (!validationResult.isValid) {
            const errorMsg = `Step 9 FAILED validation: ${
              validationResult.message
            }. Browser is ${
              validationResult.unexpectedSelectors?.includes(
                IRACING_SELECTORS.wizard.stepContainers.track,
              )
                ? '3 steps ahead on Track page'
                : 'on wrong page'
            }`;
            this.log('error', errorMsg, {
              missing: validationResult.missingSelectors,
              unexpected: validationResult.unexpectedSelectors,
            });
            throw new Error(errorMsg);
          }

          this.log('info', 'Step 9 validation passed - confirmed on Cars page');
 
          const carIds = config.carIds as string[] | undefined;
          const carSearchTerm =
            (config.carSearch as string | undefined) ||
            (config.car as string | undefined) ||
            carIds?.[0];
 
          if (this.isRealMode()) {
            const isFixtureHost =
              this.config.baseUrl &&
              !this.config.baseUrl.includes('members.iracing.com');
 
            if (isFixtureHost) {
              this.log('info', 'Step 9: fixture host detected, skipping Add Car interactions (DOM already has cars table)', {
                baseUrl: this.config.baseUrl,
                carSearchTerm,
              });
              return { success: true };
            }
 
            if (carSearchTerm) {
              await this.clickAddCarButton();
              await this.waitForAddCarModal();
              await this.fillField('carSearch', String(carSearchTerm));
              await this.page!.waitForTimeout(500);
              await this.selectFirstSearchResult();
              this.log('info', 'Added car to session', {
                car: carSearchTerm,
              });
            }
 
            await this.clickNextButton('Car Classes');
          } else {
            if (carSearchTerm) {
              const page = this.page;
              if (page) {
                await this.clickAddCarButton();
                await this.waitForAddCarModal();
                await this.fillField('carSearch', String(carSearchTerm));
                await page.waitForTimeout(200);
                try {
                  await this.selectFirstSearchResult();
                } catch (e) {
                  this.log('debug', 'Step 9 mock mode: selectFirstSearchResult failed (non-fatal)', {
                    error: String(e),
                  });
                }

                this.log('info', 'Step 9 mock mode: selected car from JSON-backed list', {
                  carSearch: String(carSearchTerm),
                });
              }
            } else {
              this.log(
                'debug',
                'Step 9 mock mode: no carSearch provided, skipping car addition',
              );
            }
          }
          break;

        case 10:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skipOffset,
              });
              return { success: true };
            }
          }

          await this.clickNextButton('Track');
          break;

        case 11:
          this.log('info', 'Step 11: Validating page state before proceeding');
          const step11Validation = await this.validatePageState({
            expectedStep: 'track',
            requiredSelectors: [
              IRACING_SELECTORS.wizard.stepContainers.track,
            ],
            forbiddenSelectors: this.isRealMode()
              ? [IRACING_SELECTORS.steps.addCarButton]
              : [],
          });

          if (step11Validation.isErr()) {
            const errorMsg = `Step 11 validation error: ${
              step11Validation.error?.message ?? 'unknown error'
            }`;
            this.log('error', errorMsg);
            throw new Error(errorMsg);
          }

          const step11ValidationResult = step11Validation.unwrap();
          this.log('info', 'Step 11 validation result', {
            isValid: step11ValidationResult.isValid,
            message: step11ValidationResult.message,
            missingSelectors: step11ValidationResult.missingSelectors,
            unexpectedSelectors: step11ValidationResult.unexpectedSelectors,
          });

          if (!step11ValidationResult.isValid) {
            const errorMsg = `Step 11 FAILED validation: ${step11ValidationResult.message}`;
            this.log('error', errorMsg, {
              missing: step11ValidationResult.missingSelectors,
              unexpected: step11ValidationResult.unexpectedSelectors,
            });
            throw new Error(errorMsg);
          }

          this.log('info', 'Step 11 validation passed - on Track page');

          if (this.isRealMode()) {
            await this.waitForWizardStep('track');
            await this.checkWizardDismissed(step);
          }
          break;

        case 12:
          if (this.isRealMode()) {
            await this.waitForWizardStep('track');
          }
          await this.clickNextButton('Track Options');
          break;

        case 13:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skippedSteps: Array.from(
                  { length: skipOffset },
                  (_, i) => step + i,
                ),
              });
              return { success: true };
            }

            await this.waitForWizardStep('trackOptions');
            await this.checkWizardDismissed(step);

            const isFixtureHost =
              this.config.baseUrl &&
              !this.config.baseUrl.includes('members.iracing.com');

            const trackSearchTerm =
              config.trackSearch || config.track || config.trackId;

            if (isFixtureHost) {
              this.log(
                'info',
                'Step 13: fixture host detected, skipping Add Track interactions (track already present in fixture)',
                { baseUrl: this.config.baseUrl, trackSearchTerm },
              );
            } else if (trackSearchTerm) {
              await this.clickAddTrackButton();
              await this.waitForAddTrackModal();
              await this.fillField('trackSearch', String(trackSearchTerm));
              await this.page!.waitForTimeout(500);
              await this.selectFirstSearchResult();
              const modalClosed = await this.page!
                .waitForSelector('.modal.fade.in', {
                  state: 'hidden',
                  timeout: 5000,
                })
                .then(() => true)
                .catch(() => false);
              if (!modalClosed) {
                this.log(
                  'warn',
                  'Track selection modal did not close, attempting dismiss',
                );
                await this.dismissModals();
                await this.page!.waitForTimeout(300);
              }
              await this.page!.waitForTimeout(300);
              this.log('info', 'Selected track for session', {
                track: trackSearchTerm,
              });
            } else {
              this.log(
                'debug',
                'Step 13: No track search term provided, skipping track addition',
              );
            }
          } else {
            if (config.trackSearch) {
              await this.fillField('trackSearch', String(config.trackSearch));
              await this.clickAction('confirm');
            }
          }
          if (this.isRealMode()) {
            await this.waitForWizardStep('trackOptions');
          }
          break;

        case 14:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skippedSteps: Array.from(
                  { length: skipOffset },
                  (_, i) => step + i,
                ),
              });
              return { success: true };
            }

            await this.waitForWizardStep('timeOfDay');
            await this.checkWizardDismissed(step);

            if (config.timeOfDay !== undefined) {
              await this.setSlider('timeOfDay', Number(config.timeOfDay));
            }
            if (config.trackConfig) {
              await this.selectDropdown('trackConfig', String(config.trackConfig));
            }

            await this.clickNextButton('Time of Day');
            await this.waitForWizardStep('timeOfDay');
          } else {
            if (config.timeOfDay !== undefined) {
              await this.setSlider('timeOfDay', Number(config.timeOfDay));
            }
            if (config.trackConfig) {
              await this.selectDropdown('trackConfig', String(config.trackConfig));
            }
          }
          break;

        case 15:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skippedSteps: Array.from(
                  { length: skipOffset },
                  (_, i) => step + i,
                ),
              });
              return { success: true };
            }

            const weatherFallbackSelector =
              IRACING_SELECTORS.wizard.stepContainers.weather;
            const weatherNav =
              IRACING_SELECTORS.wizard.sidebarLinks.weather;
            try {
              try {
                await this.page!.click(weatherNav);
                this.log('debug', 'Clicked wizard nav for Weather', {
                  selector: weatherNav,
                });
              } catch (e) {
                this.log(
                  'debug',
                  'Wizard nav for Weather not present (continuing)',
                  { error: String(e) },
                );
              }

              try {
                await this.page!.waitForSelector(weatherFallbackSelector, {
                  state: 'attached',
                  timeout: 5000,
                });
                this.log('info', 'Weather panel found', {
                  selector: weatherFallbackSelector,
                });
              } catch (err) {
                this.log(
                  'warn',
                  'Weather panel not found with fallback selector, dumping #create-race-wizard innerHTML',
                  { selector: weatherFallbackSelector },
                );
                const inner = await this.page!.evaluate(() => {
                  const doc = (globalThis as { document?: Document }).document;
                  return (
                    doc?.querySelector('#create-race-wizard')?.innerHTML || ''
                  );
                });
                this.log(
                  'debug',
                  'create-race-wizard innerHTML (truncated)',
                  { html: inner ? inner.substring(0, 2000) : '' },
                );
                try {
                  await this.page!.click(weatherNav);
                } catch {
                }
                await this.page!.waitForSelector(weatherFallbackSelector, {
                  state: 'attached',
                  timeout: 10000,
                });
              }
            } catch (e) {
              this.log('error', 'Failed waiting for Weather panel', {
                error: String(e),
                selector: weatherFallbackSelector,
              });
            }
            await this.checkWizardDismissed(step);

            if (config.timeOfDay !== undefined) {
              await this.setSlider('timeOfDay', Number(config.timeOfDay));
            }
          } else {
            if (config.weatherType) {
              await this.selectDropdown('weatherType', String(config.weatherType));
            }
            if (config.temperature !== undefined && this.page) {
              const tempSelector = IRACING_SELECTORS.steps.temperature;
              const tempExists =
                (await this.page
                  .locator(tempSelector)
                  .first()
                  .count()
                  .catch(() => 0)) > 0;
              if (tempExists) {
                await this.setSlider('temperature', Number(config.temperature));
              }
            }
          }

          if (this.isRealMode()) {
            await this.dismissDatetimePickers();
            await this.clickNextButton('Weather');
          }
          break;

        case 16:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skippedSteps: Array.from(
                  { length: skipOffset },
                  (_, i) => step + i,
                ),
              });
              return { success: true };
            }

            await this.waitForWizardStep('raceOptions');
            await this.checkWizardDismissed(step);
          }
          if (config.weatherType && this.isRealMode()) {
            await this.selectWeatherType(String(config.weatherType));
          } else if (config.weatherType && !this.isRealMode()) {
            await this.selectDropdown(
              'weatherType',
              String(config.weatherType),
            );
          }
          if (config.temperature !== undefined) {
            const tempSelector = IRACING_SELECTORS.steps.temperature;
            const tempExists =
              (await this.page!.locator(tempSelector).first().count()) > 0;
            if (tempExists) {
              await this.setSlider('temperature', Number(config.temperature));
            } else {
              this.log('debug', 'Temperature slider not found, skipping');
            }
          }
          await this.clickNextButton('Track Conditions');
          break;

        case 17:
          if (this.isRealMode()) {
            const actualPage = await this.detectCurrentWizardPage();
            const skipOffset = this.synchronizeStepCounter(step, actualPage);

            if (skipOffset > 0) {
              this.log('info', `Step ${step} was auto-skipped by wizard`, {
                actualPage,
                skippedSteps: Array.from(
                  { length: skipOffset },
                  (_, i) => step + i,
                ),
              });
              return { success: true };
            }

            await this.waitForWizardStep('trackConditions');
            await this.checkWizardDismissed(step);
          }

          if (config.trackState) {
            if (this.isRealMode()) {
              try {
                const trackStateSelector = IRACING_SELECTORS.steps.trackState;
                const exists =
                  (await this.page!
                    .locator(trackStateSelector)
                    .first()
                    .count()) > 0;
                if (exists) {
                  await this.selectDropdown(
                    'trackState',
                    String(config.trackState),
                  );
                } else {
                  this.log(
                    'debug',
                    'Track state dropdown not found, skipping',
                  );
                }
              } catch (e) {
                this.log('debug', 'Could not set track state (non-critical)', {
                  error: String(e),
                });
              }
            } else {
              const trackStateSelector = IRACING_SELECTORS.steps.trackState;
              const selectorExists =
                (await this.page!
                  .locator(trackStateSelector)
                  .first()
                  .count()
                  .catch(() => 0)) > 0;
              if (selectorExists) {
                await this.selectDropdown(
                  'trackState',
                  String(config.trackState),
                );
              } else {
                const valueStr = String(config.trackState);
                await this.page!.evaluate((trackStateValue) => {
                  const doc = (globalThis as { document?: Document }).document;
                  if (!doc) {
                    return;
                  }
                  const map: Record<string, number> = {
                    'very-low': 10,
                    low: 25,
                    'moderately-low': 40,
                    medium: 50,
                    'moderately-high': 60,
                    high: 75,
                    'very-high': 90,
                  };
                  const numeric = map[trackStateValue] ?? null;
                  const inputs = Array.from(
                    doc.querySelectorAll<HTMLInputElement>(
                      'input[id*="starting-track-state"], input[id*="track-state"], input[data-value]',
                    ),
                  );
                  if (numeric !== null && inputs.length > 0) {
                    for (const inp of inputs) {
                      try {
                        inp.value = String(numeric);
                        inp.dataset.value = String(numeric);
                        inp.setAttribute(
                          'data-value',
                          String(numeric),
                        );
                        inp.dispatchEvent(
                          new Event('input', { bubbles: true }),
                        );
                        inp.dispatchEvent(
                          new Event('change', { bubbles: true }),
                        );
                      } catch {
                      }
                    }
                  }
                }, valueStr);
              }
            }
          }

          if (this.checkoutConfirmationCallback) {
            await this.handleCheckoutConfirmation();
          }
          return { success: true };

        default:
          return { success: false, error: `Unknown step: ${step}` };
      }

      if (step === this.totalSteps && this.isRealMode()) {
        await this.showOverlayComplete(true);
      }

      return { success: true };
    } catch (error) {
      const err = error instanceof Error ? error : new Error(String(error));
      this.log('error', 'Step execution failed', { step, error: err.message });

      if (this.isRealMode()) {
        await this.showOverlayComplete(false, `❌ Failed at step ${step}`);
      }

      const debugPaths = await this.saveDebugInfo(`step-${step}`, err);

      let errorMessage = err.message;
      if (debugPaths.screenshotPath || debugPaths.htmlPath) {
        const paths: string[] = [];
        if (debugPaths.screenshotPath) {
          paths.push(`Screenshot: ${debugPaths.screenshotPath}`);
        }
        if (debugPaths.htmlPath) {
          paths.push(`HTML: ${debugPaths.htmlPath}`);
        }
        errorMessage = `${err.message}\n\nDebug files:\n${paths.join('\n')}`;
      }

      if (
        errorMessage.includes('validation') ||
        errorMessage.includes('FAILED validation')
      ) {
        throw new Error(errorMessage);
      }

      return { success: false, error: errorMessage };
    }
  }
}