/**
 * lists.spec.ts — TEST-01
 *
 * Route-specific state assertions for /lists (UI-SPEC Rules 4/5):
 *   - Populated state: seeded 'E2E Grocery List' card visible, ListsEmptyState absent
 *   - Empty state (network-simulated): 'No lists yet' + 'Tap + to create' visible
 *   - No horizontal overflow in both states (Rule 2)
 *
 * The seeded populated state comes from global-setup (Plan 02):
 *   - 'E2E Grocery List' (owner_id=1, is_shared=true) + list_shares row for user_id=1
 *   - Items: 'Milk' (rank 'a0'), 'Eggs' (rank 'a1')
 *
 * The empty state is simulated by routing /api/lists to return [] BEFORE navigation —
 * this keeps the seeded DB intact (T-07-11 / D-06 deterministic seed).
 *
 * Runs on all three device profiles automatically (playwright.config.ts matrix):
 *   iphone:  iPhone 14 / WebKit / 390×844
 *   pixel:   Pixel 7 / Chromium / 412×915
 *   desktop: Desktop Chrome / Chromium / 1280×720 (all tests pass unchanged)
 *
 * Run:
 *   pnpm --filter @familysync/pwa test:e2e
 *   pnpm --filter @familysync/pwa exec playwright test --project=pixel lists.spec.ts
 */
import { test, expect } from '@playwright/test';

// ── Rule 5: Populated state ───────────────────────────────────────────────────

test.describe('Rule 5 — populated lists state', () => {
  test.beforeEach(async ({ page }) => {
    await page.goto('/lists');
    // Wait for auth (DEV_AUTH_BYPASS) and lists content to load
    await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();
  });

  test('seeded "E2E Grocery List" card is visible', async ({ page }) => {
    // ListCard renders a button with aria-label="Open list: <name>" (ListCard.tsx).
    // This is the primary stable locator — prefer role+name over text content.
    const listCard = page.getByRole('button', { name: 'Open list: E2E Grocery List' });
    await expect(listCard).toBeVisible();
  });

  test('at least one list item is present in the populated state', async ({ page }) => {
    // The content area has role="list" (ListsIndex.tsx) with ListCard children
    // that each have role="listitem". Assert ≥1 listitem when seeded.
    const listitems = page.getByRole('listitem');
    await expect(listitems).not.toHaveCount(0);
  });

  test('ListsEmptyState "No lists yet" is NOT present when lists are seeded', async ({ page }) => {
    // With the seeded list, the empty state must not appear.
    await expect(page.getByText('No lists yet')).toHaveCount(0);
  });

  test('no horizontal overflow on populated /lists (Rule 2)', async ({ page }) => {
    const overflow = await page.evaluate(() => ({
      scrollWidth: document.documentElement.scrollWidth,
      clientWidth: document.documentElement.clientWidth,
    }));
    expect(
      overflow.scrollWidth,
      `scrollWidth (${overflow.scrollWidth}) must be ≤ clientWidth (${overflow.clientWidth}) on populated /lists`,
    ).toBeLessThanOrEqual(overflow.clientWidth);
  });
});

// ── Rule 5: Empty state (network-simulated) ───────────────────────────────────

test.describe('Rule 5 — lists empty state (network-simulated, seeded DB untouched)', () => {
  test('empty-state heading and body visible when /api/lists returns []', async ({ page }) => {
    // Route /api/lists to return an empty list BEFORE goto (Pattern 5).
    // This keeps the seeded DB intact — no DB mutation from the spec (T-07-11 / D-06).
    await page.route('/api/lists', (route) =>
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ lists: [] }),
      }),
    );

    await page.goto('/lists');
    await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();

    // ListsEmptyState renders "No lists yet" heading (ListsEmptyState.tsx)
    await expect(page.getByText('No lists yet')).toBeVisible();

    // Body contains "Tap + to create your first shared list" — use partial match
    await expect(page.getByText(/Tap \+ to create/)).toBeVisible();
    // No manual unroute (WR-05): Playwright gives each test a fresh page/context, so route
    // handlers do not leak across tests; a trailing unroute also never runs if an `expect`
    // above throws.
  });

  test('no horizontal overflow in empty lists state (Rule 2)', async ({ page }) => {
    await page.route('/api/lists', (route) =>
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({ lists: [] }),
      }),
    );

    await page.goto('/lists');
    await expect(page.getByRole('navigation', { name: 'Main navigation' })).toBeVisible();

    // Wait for empty state to render before measuring overflow
    await expect(page.getByText('No lists yet')).toBeVisible();

    const overflow = await page.evaluate(() => ({
      scrollWidth: document.documentElement.scrollWidth,
      clientWidth: document.documentElement.clientWidth,
    }));
    expect(
      overflow.scrollWidth,
      `scrollWidth (${overflow.scrollWidth}) must be ≤ clientWidth (${overflow.clientWidth}) in empty lists state`,
    ).toBeLessThanOrEqual(overflow.clientWidth);
    // No manual unroute (WR-05): per-test context isolation handles route cleanup.
  });
});
