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

test.describe('buyer flow: browse → detail → cart → checkout', () => {
  test('user can add an item to cart and reach the payment step', async ({ page }) => {
    // Block external Stripe assets so the test isn't flaky on network egress.
    // We only need to verify we transitioned past the address step, not that
    // Stripe Elements actually mounts a payment iframe.
    await page.route('**/*stripe*/**', (route) => route.abort());
    await page.route('https://js.stripe.com/**', (route) => route.abort());
    await page.route('https://api.stripe.com/**', (route) => route.abort());

    // 1. Browse: items page lists the item
    await page.goto('/items');
    await expect(page.getByRole('heading', { name: 'Browse' })).toBeVisible();
    await expect(page.getByText('Vintage Levis Tee').first()).toBeVisible({
      timeout: 10_000,
    });

    // 2. Click into item detail.
    // The rebuilt product page states the condition three times — the buy-box
    // badge, the spec grid and the confidence card — and mounts a second
    // Add-to-Cart button in a sticky bar once the buy box scrolls out of view.
    // Both assertions are therefore scoped to the buy box, which the page
    // already exposes as a named region, rather than to the whole document.
    await page.getByText('Vintage Levis Tee').first().click();
    const buyBox = page.getByRole('region', {
      name: 'Vintage Levis Tee purchase options',
    });
    await expect(
      buyBox.getByRole('heading', { name: 'Vintage Levis Tee' }),
    ).toBeVisible();
    await expect(buyBox.getByText('Excellent Used Condition')).toBeVisible();

    // 3. Add to cart
    await buyBox.getByRole('button', { name: /Add to Cart/ }).click();
    await expect(page.getByText('Added to cart!')).toBeVisible();

    // 4. Navigate to cart
    await page.goto('/cart');
    await expect(page.getByRole('heading', { name: /Shopping Cart/ })).toBeVisible();
    await expect(page.getByText('Vintage Levis Tee')).toBeVisible();
    await expect(page.getByText('$33.00')).toBeVisible();

    // 5. Proceed to checkout
    await page.getByRole('button', { name: /Proceed to Checkout/ }).click();
    await expect(page).toHaveURL(/\/checkout$/);
    await expect(page.getByRole('heading', { name: 'Checkout' })).toBeVisible();

    // 6. Fill the address form (labels aren't htmlFor-wired; use input order)
    const inputs = page.getByRole('textbox');
    await inputs.nth(0).fill('Jane');
    await inputs.nth(1).fill('Doe');
    await inputs.nth(2).fill('1 Main St');
    await inputs.nth(3).fill('Portland');
    await inputs.nth(4).fill('OR');
    await inputs.nth(5).fill('97201');

    // 7. Submit address → expect we leave the address step.
    // The address form heading "Shipping Address" is gone in payment step.
    await page.getByRole('button', { name: /Continue to Payment/ }).click();
    await expect(page.getByText('Shipping Address')).toBeHidden({
      timeout: 10_000,
    });
    // Payment step shows a "Cancel Checkout" button
    await expect(
      page.getByRole('button', { name: /Cancel Checkout/ }),
    ).toBeVisible();
  });

  test('cart shows empty state when nothing has been added', async ({
    page,
  }) => {
    // The mock server's cart starts empty for this worker if it hasn't been
    // mutated yet. Since we run with workers, this test is independent of the
    // happy-path test only if it runs first or in a fresh state. Instead of
    // relying on order, we directly intercept this page's cart fetch.
    await page.route('**/v1/cart', (route) =>
      route.fulfill({
        status: 200,
        contentType: 'application/json',
        body: JSON.stringify({
          data: { item_count: 0, subtotal: 0, shipping_total: 0, total: 0, stores: [] },
        }),
      }),
    );

    await page.goto('/cart');
    await expect(
      page.getByRole('heading', { name: 'Your cart is empty' }),
    ).toBeVisible();
    await expect(page.getByRole('link', { name: /Browse Items/ })).toHaveAttribute(
      'href',
      '/items',
    );
  });
});
