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

const shouldRun = process.env.HOSTED_REAL_E2E === '1';
const describeMaybe = shouldRun ? describe : describe.skip;

describeMaybe('Real-site hosted session – Race Information step (members.iracing.com)', () => {
  let adapter: PlaywrightAutomationAdapter;

  beforeAll(async () => {
    const logger = new PinoLogAdapter();

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

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

    const step1Result = await adapter.executeStep(StepId.create(1), {});
    expect(step1Result.success).toBe(true);

    const step2Result = await adapter.executeStep(StepId.create(2), {});
    expect(step2Result.success).toBe(true);

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

    const createRaceButton = page!
      .locator(IRACING_SELECTORS.hostedRacing.createRaceButton)
      .first();
    await expect(
      createRaceButton.count(),
      'Create Race button should exist on Hosted Racing page',
    ).resolves.toBeGreaterThan(0);

    await createRaceButton.click({ timeout: IRACING_TIMEOUTS.elementWait });

    const raceInfoContainer = page!
      .locator(IRACING_SELECTORS.wizard.stepContainers.raceInformation)
      .first();
    await raceInfoContainer.waitFor({
      state: 'attached',
      timeout: IRACING_TIMEOUTS.elementWait,
    });
    expect(await raceInfoContainer.count()).toBeGreaterThan(0);
  }, 300_000);

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

  it(
    'shows Race Information sidebar text matching fixtures and keeps text inputs writable',
    async () => {
      const page = adapter.getPage();
      expect(page).not.toBeNull();

      const sidebarLink = page!
        .locator(IRACING_SELECTORS.wizard.sidebarLinks.raceInformation)
        .first();
      await sidebarLink.waitFor({
        state: 'attached',
        timeout: IRACING_TIMEOUTS.elementWait,
      });
      const sidebarText = (await sidebarLink.innerText()).trim();
      expect(sidebarText.length).toBeGreaterThan(0);

      let fixtureSidebarText: string | null = null;
      try {
        const fixturePath = path.join(
          process.cwd(),
          'html-dumps-optimized',
          'iracing-hosted-sessions',
          '03-race-information.json',
        );
        const raw = await fs.readFile(fixturePath, 'utf8');
        const items = JSON.parse(raw) as Array<{ i: string; t: string }>;
        const sidebarItem =
          items.find(
            (i) =>
              i.i === 'wizard-sidebar-link-set-session-information' &&
              typeof i.t === 'string',
          ) ?? null;
        if (sidebarItem) {
          fixtureSidebarText = sidebarItem.t;
        }
      } catch {
        fixtureSidebarText = null;
      }

      if (fixtureSidebarText) {
        const expected = fixtureSidebarText.toLowerCase();
        const actual = sidebarText.toLowerCase();
        expect(
          actual.includes('race') || actual.includes(expected.slice(0, 4)),
        ).toBe(true);
      }

      const config = {
        sessionName: 'GridPilot Real – Race Information',
        password: 'real-site-secret',
        description: 'Real-site Race Information writable fields check',
      };

      const result = await adapter.executeStep(StepId.create(3), config);
      expect(result.success).toBe(true);

      const sessionNameInput = page!
        .locator(IRACING_SELECTORS.steps.sessionName)
        .first();
      const passwordInput = page!
        .locator(IRACING_SELECTORS.steps.password)
        .first();
      const descriptionInput = page!
        .locator(IRACING_SELECTORS.steps.description)
        .first();

      await sessionNameInput.waitFor({
        state: 'attached',
        timeout: IRACING_TIMEOUTS.elementWait,
      });
      await passwordInput.waitFor({
        state: 'attached',
        timeout: IRACING_TIMEOUTS.elementWait,
      });
      await descriptionInput.waitFor({
        state: 'attached',
        timeout: IRACING_TIMEOUTS.elementWait,
      });

      const sessionNameValue = await sessionNameInput.inputValue();
      const passwordValue = await passwordInput.inputValue();
      const descriptionValue = await descriptionInput.inputValue();

      expect(sessionNameValue).toBe(config.sessionName);
      expect(passwordValue).toBe(config.password);
      expect(descriptionValue).toBe(config.description);
    },
    300_000,
  );
});