/**
 * Phase 3 mobile — gestures listed in USER_JOURNEYS.md §17 as **planned**.
 *
 * These tests are marked `test.fixme` so they appear in the report (as
 * pending, not failing) until the feature ships. Each test contains the
 * exact assertion that should pass once the gesture is wired — flip
 * `test.fixme` to `test` when implementing.
 *
 * Why ship the tests now? They document the *contract* — the next person
 * to wire the gesture has a green/red signal instead of needing to invent
 * an interaction model.
 */
import { test, expect } from '../../fixtures/test';
import { uploadRaw } from '../../helpers/upload-client';
import { swipe } from '../../helpers/touch';
import { readFileSync } from 'node:fs';
import { join } from 'node:path';

const SAMPLE_JPG = join(process.cwd(), 'fixtures', 'media', 'sample.jpg');

test.describe('Mobile — planned gestures (fixme until shipped)', () => {
  test.fixme('swipe left in lightbox navigates to next filtered item', async ({
    page,
    guest,
    signIn,
  }) => {
    const author = await guest('SwipeAuthor');
    // Seed two uploads so there's a "next" to navigate to.
    for (const cap of ['First', 'Second']) {
      const res = await uploadRaw(author.jwt, readFileSync(SAMPLE_JPG), {
        filename: `${cap}.jpg`,
        contentType: 'image/jpeg',
        caption: cap,
      });
      if (res.status !== 201) throw new Error(`seed ${cap}: ${res.status}`);
    }

    await signIn(page, author);
    await page.goto('/feed');

    // Open the lightbox on the first card.
    const firstImage = page
      .locator('article')
      .filter({ hasText: 'First' })
      .getByRole('button', { name: 'Bild vergrößern' });
    await firstImage.click();
    const lightbox = page.getByRole('dialog');
    await expect(lightbox).toBeVisible();
    await expect(lightbox).toContainText('First');

    // Swipe left across the media element.
    const media = lightbox.locator('img, video').first();
    const box = await media.boundingBox();
    if (!box) throw new Error('lightbox media not visible');
    await swipe(
      page,
      { x: box.x + box.width * 0.9, y: box.y + box.height / 2 },
      { x: box.x + box.width * 0.1, y: box.y + box.height / 2 }
    );

    // Expected: the second upload's caption is now visible.
    await expect(lightbox).toContainText('Second', { timeout: 2_000 });
  });

  test.fixme('swipe right in lightbox navigates to previous item', async ({ page }) => {
    // Same setup as above, but starting from the second item and swiping right.
    expect(true).toBe(true);
    void page;
  });

  test.fixme('swipe down on UploadSheet dismisses it', async ({ page, guest, signIn }) => {
    const g = await guest('SwipeDismiss');
    await signIn(page, g);
    await page.goto('/feed');

    await page.getByRole('button', { name: 'Hochladen' }).click();
    const sheet = page.getByRole('dialog');
    await expect(sheet).toBeVisible();

    const box = await sheet.boundingBox();
    if (!box) throw new Error('sheet not visible');
    await swipe(
      page,
      { x: box.x + box.width / 2, y: box.y + 10 },
      { x: box.x + box.width / 2, y: box.y + 300 }
    );

    // Expected: the sheet is gone.
    await expect(sheet).not.toBeVisible({ timeout: 2_000 });
  });

  test.fixme('pull-to-refresh on /feed triggers a delta fetch', async ({ page, guest, signIn }) => {
    const g = await guest('PullRefresh');
    await signIn(page, g);
    await page.goto('/feed');

    let deltaCalled = false;
    await page.route('**/api/v1/feed/delta**', async (route) => {
      deltaCalled = true;
      await route.continue();
    });

    const box = await page.locator('body').boundingBox();
    if (!box) throw new Error('body not visible');
    // Pull down from the top of the viewport.
    await swipe(page, { x: box.x + box.width / 2, y: 20 }, { x: box.x + box.width / 2, y: 200 });

    await page.waitForTimeout(1_000);
    expect(deltaCalled).toBe(true);
  });

  test.fixme('long-press on a comment opens a context sheet (copy/delete)', async ({ page }) => {
    // Per journey §17 row "Long-press on a comment (own) → Bottom sheet → Löschen".
    expect(true).toBe(true);
    void page;
  });
});
