import { describe, it, expect, beforeAll, afterAll } from 'vitest';
import {
  PlaywrightAutomationAdapter,
  FixtureServer,
} from 'core/automation/infrastructure//automation';
import { InMemorySessionRepository } from 'apps/companion/main/automation/infrastructure/repositories/InMemorySessionRepository';
import { AutomationEngineAdapter } from 'core/automation/infrastructure//automation/engine/AutomationEngineAdapter';
import { StartAutomationSessionUseCase } from 'apps/companion/main/automation/application/use-cases/StartAutomationSessionUseCase';
import { StepId } from 'apps/companion/main/automation/domain/value-objects/StepId';
import { PinoLogAdapter } from 'core/automation/infrastructure//logging/PinoLogAdapter';

describe('Workflow – hosted session end-to-end (fixture-backed, real stack)', () => {
  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: 10_000,
        baseUrl,
        mode: 'real',
        userDataDir: '',
      },
      logger,
    );
    const connectResult = await adapter.connect(false);
    expect(connectResult.success).toBe(true);
    expect(adapter.isConnected()).toBe(true);
  });

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

  function createRealEngine() {
    const repository = new InMemorySessionRepository();
    const engine = new AutomationEngineAdapter(adapter, repository);
    const useCase = new StartAutomationSessionUseCase(engine, adapter, repository);
    return { repository, engine, useCase };
  }

  it(
    'runs 1–17 from use case and stops automation at manual Track Conditions (STOPPED_AT_STEP_18)',
    async () => {
      const { repository, engine, useCase } = createRealEngine();

      const config: any = {
        sessionName: 'Fixture E2E – full workflow (real stack)',
        trackId: 'spa',
        carIds: ['dallara-f3'],
      };

      const dto = await useCase.execute(config);

      expect(dto.state).toBe('PENDING');
      expect(dto.currentStep).toBe(1);

      await adapter.navigateToPage(server.getFixtureUrl(1));

      await engine.executeStep(StepId.create(1), config);

      const deadline = Date.now() + 60_000;
      let finalSession = null;

      // eslint-disable-next-line no-constant-condition
      while (true) {
        const sessions = await repository.findAll();
        finalSession = sessions[0] ?? null;

        if (finalSession && finalSession.state.isStoppedAtStep18()) {
          break;
        }

        if (Date.now() > deadline) {
          throw new Error('Timed out waiting for automation workflow to complete');
        }

        await new Promise((resolve) => setTimeout(resolve, 250));
      }

      expect(finalSession).not.toBeNull();
      expect(finalSession!.state.isStoppedAtStep18()).toBe(true);
      expect(finalSession!.currentStep.value).toBe(17);
      expect(finalSession!.startedAt).toBeInstanceOf(Date);
      expect(finalSession!.completedAt).toBeInstanceOf(Date);
      expect(finalSession!.errorMessage).toBeUndefined();
    },
  );
});