import { describe, it, expect, beforeEach, afterEach } from 'vitest';
import { DIContainer } from '../../../..//apps/companion/main/di-container';
import type { HostedSessionConfig } from 'apps/companion/main/automation/domain/types/HostedSessionConfig';
import { StepId } from 'apps/companion/main/automation/domain/value-objects/StepId';
import { PlaywrightAutomationAdapter } from '../../../../apps/companion/main/automation/infrastructure/automation';

describe('companion start automation - browser mode refresh wiring', () => {
  const originalEnv = { ...process.env };
  let originalTestLauncher: unknown;

  beforeEach(() => {
    process.env = { ...originalEnv, NODE_ENV: 'development' };
 
    originalTestLauncher = (PlaywrightAutomationAdapter as typeof PlaywrightAutomationAdapter & {
      testLauncher?: unknown;
    }).testLauncher;

    const mockLauncher = {
      launch: async (_opts: unknown) => ({
        newContext: async () => ({
          newPage: async () => ({ setDefaultTimeout: () => {}, close: async () => {} }),
          close: async () => {},
        }),
        newPage: async () => ({ setDefaultTimeout: () => {}, close: async () => {} }),
        close: async () => {},
      }),
      launchPersistentContext: async (_userDataDir: string, _opts: unknown) => ({
        pages: () => [{ setDefaultTimeout: () => {}, close: async () => {} }],
        newPage: async () => ({ setDefaultTimeout: () => {}, close: async () => {} }),
        close: async () => {},
      }),
    };

    (PlaywrightAutomationAdapter as typeof PlaywrightAutomationAdapter & {
      testLauncher?: typeof mockLauncher;
    }).testLauncher = mockLauncher;

    DIContainer.resetInstance();
  });

  afterEach(async () => {
    const container = DIContainer.getInstance();
    await container.shutdown();
    DIContainer.resetInstance();
    (PlaywrightAutomationAdapter as typeof PlaywrightAutomationAdapter & {
      testLauncher?: unknown;
    }).testLauncher = originalTestLauncher;
    process.env = originalEnv;
  });

  it('uses refreshed browser automation for connection and step execution after mode change', async () => {
    const container = DIContainer.getInstance();

    const loader = container.getBrowserModeConfigLoader();
    expect(loader.getDevelopmentMode()).toBe('headed');

    const preStart = container.getStartAutomationUseCase();
    const preEngine = container.getAutomationEngine();
    const preAutomation = container.getBrowserAutomation();

    expect(preAutomation).toBe(preEngine.browserAutomation);

    loader.setDevelopmentMode('headless');
    container.refreshBrowserAutomation();

    const postStart = container.getStartAutomationUseCase();
    const postEngine = container.getAutomationEngine();
    const postAutomation = container.getBrowserAutomation();

    expect(postAutomation).toBe(postEngine.browserAutomation);
    expect(postAutomation).not.toBe(preAutomation);
    expect(postStart).not.toBe(preStart);

    const connectionResult = await container.initializeBrowserConnection();
    expect(connectionResult.success).toBe(true);

    const config: HostedSessionConfig = {
      sessionName: 'Companion browser-mode refresh wiring',
      trackId: 'test-track',
      carIds: ['car-1'],
    };

    const dto = await postStart.execute(config);

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

    const sessionRepository = container.getSessionRepository();
    const session = await sessionRepository.findById(dto.sessionId);

    expect(session).toBeDefined();

    const state = session!.state.value as string;
    const errorMessage = session!.errorMessage as string | undefined;

    if (errorMessage) {
      expect(errorMessage).not.toContain('Browser not connected');
    }

    const automationFromConnection = container.getBrowserAutomation();
    const automationFromEngine = (container.getAutomationEngine() as { browserAutomation: unknown })
      .browserAutomation;

    expect(automationFromConnection).toBe(automationFromEngine);
    expect(automationFromConnection).toBe(postAutomation);
  });
});