import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import { StepId } from 'apps/companion/main/automation/domain/value-objects/StepId';
import {
  FixtureServer,
  PlaywrightAutomationAdapter,
} from 'core/automation/infrastructure//automation';
import { IRACING_SELECTORS } from 'core/automation/infrastructure//automation/dom/IRacingSelectors';
import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter';

describe('Real Playwright hosted-session smoke (fixtures, steps 2–7)', () => {
  let server: FixtureServer;
  let adapter: PlaywrightAutomationAdapter;
  let baseUrl: string;

  beforeAll(async () => {
    server = new FixtureServer();
    const info = await server.start();
    baseUrl = info.url;

    const logger = new PinoLogAdapter();

    adapter = new PlaywrightAutomationAdapter(
      {
        headless: true,
        timeout: 8000,
        mode: 'real',
        baseUrl,
        userDataDir: '',
      },
      logger,
    );

    const result = await adapter.connect(false);
    expect(result.success).toBe(true);
    expect(adapter.isConnected()).toBe(true);
    expect(adapter.getPage()).not.toBeNull();
  });

  afterAll(async () => {
    if (adapter) {
      await adapter.disconnect();
    }
    if (server) {
      await server.stop();
    }
  });

  async function expectContextOpen(stepLabel: string) {
    const page = adapter.getPage();
    expect(page, `${stepLabel}: page should exist`).not.toBeNull();
    const closed = await page!.isClosed();
    expect(closed, `${stepLabel}: page should be open`).toBe(false);
    expect(adapter.isConnected(), `${stepLabel}: adapter stays connected`).toBe(true);
  }

  async function navigateToFixtureStep(
    stepNumber: number,
    label: string,
    stepKey?: keyof typeof IRACING_SELECTORS.wizard.stepContainers,
  ) {
    const page = adapter.getPage();
    expect(page).not.toBeNull();

    await adapter.navigateToPage(server.getFixtureUrl(stepNumber));
    await page!.waitForLoadState('domcontentloaded');
    await expectContextOpen(`after navigate step ${stepNumber} (${label})`);

    if (stepKey) {
      const selector = IRACING_SELECTORS.wizard.stepContainers[stepKey];
      const container = page!.locator(selector).first();
      const count = await container.count();
      expect(
        count,
        `${label}: expected container ${selector} to exist on fixture HTML`,
      ).toBeGreaterThan(0);
    }
  }

  it(
    'keeps browser context open and reaches Time Limits using real adapter against fixtures',
    async () => {
      await navigateToFixtureStep(2, 'Create a Race');

      const step2Result = await adapter.executeStep(
        StepId.create(2),
        {} as Record<string, unknown>,
      );
      expect(step2Result.success).toBe(true);
      await expectContextOpen('after step 2');

      await navigateToFixtureStep(3, 'Race Information', 'raceInformation');

      const step3Result = await adapter.executeStep(
        StepId.create(3),
        {
          sessionName: 'GridPilot Smoke Session',
          password: 'smokepw',
          description: 'Real Playwright smoke path using fixtures',
        } as Record<string, unknown>,
      );
      expect(step3Result.success).toBe(true);
      await expectContextOpen('after step 3');

      await navigateToFixtureStep(4, 'Server Details', 'serverDetails');

      const step4Result = await adapter.executeStep(
        StepId.create(4),
        {
          region: 'US',
          startNow: true,
        } as Record<string, unknown>,
      );
      expect(step4Result.success).toBe(true);
      await expectContextOpen('after step 4');

      await navigateToFixtureStep(5, 'Set Admins', 'admins');

      const step5Result = await adapter.executeStep(
        StepId.create(5),
        {} as Record<string, unknown>,
      );
      expect(step5Result.success).toBe(true);
      await expectContextOpen('after step 5');

      await navigateToFixtureStep(6, 'Admins drawer', 'admins');

      const step6Result = await adapter.executeStep(
        StepId.create(6),
        {
          adminSearch: 'Marc',
        } as Record<string, unknown>,
      );
      expect(step6Result.success).toBe(true);
      await expectContextOpen('after step 6');

      await navigateToFixtureStep(7, 'Time Limits', 'timeLimit');

      const step7Result = await adapter.executeStep(
        StepId.create(7),
        {
          practice: 10,
          qualify: 10,
          race: 20,
        } as Record<string, unknown>,
      );
      expect(step7Result.success).toBe(true);
      await expectContextOpen('after step 7');

      const page = adapter.getPage();
      expect(page).not.toBeNull();

      const footerText = await page!.textContent('.wizard-footer');
      expect(footerText || '').toMatch(/Cars/i);

      const overlay = await page!.$('#gridpilot-overlay');
      expect(overlay, 'overlay should be present in real mode').not.toBeNull();
    },
    60000,
  );
});
