import { test, expect } from '@playwright/test';

import { login, apiHeaders, navigateTo, PORT_SLUG } from '../smoke/helpers';
import { IPHONE_DEVICES } from '../fixtures/devices';
import { seedFullyLoadedDeal, changeStage, readStage } from '../fixtures/sales-journey';

/**
 * Mobile parity for the core sales journey.
 *
 * Re-runs the deterministic pipeline walk at a phone viewport
 * (iPhone 15/16, 393×852 — the "common" anchor in
 * `tests/e2e/fixtures/devices.ts`) to confirm the stage transitions and
 * the interest-detail surface behave identically on mobile. Uses the
 * existing device descriptor + `test.use({ viewport, … })` rather than
 * introducing a new Playwright project, since the exhaustive project
 * already runs the rest of the journey on desktop.
 */

const phone = IPHONE_DEVICES.iphone16;

test.use({
  viewport: phone.viewport,
  deviceScaleFactor: phone.deviceScaleFactor,
  isMobile: phone.isMobile,
  hasTouch: phone.hasTouch,
  userAgent: phone.userAgent,
});

test.describe(`exhaustive: sales journey on ${phone.name}`, () => {
  test.beforeEach(async ({ page }) => {
    await login(page, 'super_admin');
  });

  test('pipeline walk reaches contract on a mobile viewport', async ({ page }) => {
    const headers = await apiHeaders(page);
    const deal = await seedFullyLoadedDeal(page, 'Mobile Journey');

    expect(await readStage(page.request, headers, deal.interestId)).toBe('enquiry');

    for (const stage of [
      'qualified',
      'nurturing',
      'eoi',
      'reservation',
      'deposit_paid',
      'contract',
    ] as const) {
      await changeStage(page.request, headers, deal.interestId, stage);
      expect(
        await readStage(page.request, headers, deal.interestId),
        `mobile: interest should be at ${stage}`,
      ).toBe(stage);
    }
  });

  test('interest detail renders its stage on a mobile viewport', async ({ page }) => {
    const headers = await apiHeaders(page);
    const deal = await seedFullyLoadedDeal(page, 'Mobile Detail');
    await changeStage(page.request, headers, deal.interestId, 'qualified');

    await navigateTo(page, `/interests/${deal.interestId}`);
    await page.waitForURL(new RegExp(`/${PORT_SLUG}/interests/${deal.interestId}`), {
      timeout: 10_000,
    });
    await page.waitForLoadState('networkidle');

    // The viewport is genuinely mobile-width.
    expect(page.viewportSize()?.width).toBe(phone.viewport.width);

    // The stage label is present on the mobile-rendered detail page.
    await expect(page.getByText(/qualified/i).first()).toBeVisible({ timeout: 10_000 });
  });

  test('interests list is reachable and renders on a mobile viewport', async ({ page }) => {
    await navigateTo(page, '/interests');
    await page.waitForLoadState('networkidle');

    // The page heading is present regardless of whether the mobile layout
    // shows a table or a card/board view.
    await expect(page.getByText(/interests/i).first()).toBeVisible({ timeout: 15_000 });

    await expect
      .poll(
        async () => {
          const table = await page
            .locator('table')
            .first()
            .isVisible()
            .catch(() => false);
          const cards = await page
            .locator('[data-testid="pipeline-board"], [class*="board"], [class*="card"]')
            .first()
            .isVisible()
            .catch(() => false);
          return table || cards;
        },
        { timeout: 15_000 },
      )
      .toBe(true);
  });
});
