/**
 * SW-series: swipe-to-toggle gestures in Mobile Safari (Fase 9.4).
 *
 * History: pre-Fase 5.10 there were two `.skip` swipe-to-delete tests in
 * `mobile.test.ts` because Chromium's touch emulation misfires the
 * touch* events the gesture handlers expect. That file was removed when
 * swipe was repurposed from delete → check-toggle; the gap stayed open.
 *
 * Fase 9.4 closes the gap by adding a WebKit project to playwright.config
 * and these two specs (the only ones gated on touch fidelity):
 *
 *   SW-01: an unchecked item + swipe right → mark checked.
 *   SW-02: a checked item + swipe left → mark unchecked.
 *
 * The swipe handlers in `apps/web/src/routes/(app)/lists/[id]/+page.svelte`
 * listen to `pointer*` events (unified pointer model), so we synthesise
 * the gesture by dispatching PointerEvents with pointerType:'touch'
 * directly. We chose this over `page.touchscreen.tap` so the same code
 * works whether the project uses `hasTouch: true` (WebKit/iPhone 13) or
 * not — it's the event payload the handler cares about.
 */
import { test, expect, type Page } from '@playwright/test';
import { USERS } from '../fixtures/users.js';
import { loginAs } from '../fixtures/login.js';

const SEED_LIST_PATH = '/lists/bbbbbbbb-bbbb-bbbb-bbbb-bbbbbbbbbbbb';
const ADD_ITEM_PLACEHOLDER = /add item|añadir producto/i;

async function swipeRow(page: Page, itemName: string, dx: number): Promise<void> {
	await page.evaluate(
		({ name, dxLocal }) => {
			const row = document.querySelector(
				`[data-testid="item-row"][data-name="${CSS.escape(name)}"]`
			) as HTMLElement | null;
			if (!row) throw new Error(`row ${name} not found`);
			const r = row.getBoundingClientRect();
			const sx = r.left + r.width / 2;
			const sy = r.top + r.height / 2;
			const makeEvent = (type: string, clientX: number) =>
				new PointerEvent(type, {
					bubbles: true,
					cancelable: true,
					composed: true,
					pointerType: 'touch',
					pointerId: 1,
					isPrimary: true,
					clientX,
					clientY: sy,
					button: type === 'pointerup' || type === 'pointerdown' ? 0 : -1,
					buttons: type === 'pointerdown' || type === 'pointermove' ? 1 : 0
				});
			row.dispatchEvent(makeEvent('pointerdown', sx));
			for (let i = 1; i <= 8; i++) {
				row.dispatchEvent(makeEvent('pointermove', sx + (dxLocal * i) / 8));
			}
			row.dispatchEvent(makeEvent('pointerup', sx + dxLocal));
		},
		{ name: itemName, dxLocal: dx }
	);
}

test.describe('Swipe-to-toggle — Mobile Safari (Fase 9.4)', () => {
	test.beforeEach(async ({ page }) => {
		await loginAs(page, USERS.borja);
		await page.goto(SEED_LIST_PATH);
		await expect(page.getByPlaceholder(ADD_ITEM_PLACEHOLDER)).toBeVisible({ timeout: 15_000 });
	});

	test('SW-01: unchecked item + swipe right → marked checked', async ({ page }) => {
		const itemName = `SW-01-${Date.now()}`;
		const input = page.getByPlaceholder(ADD_ITEM_PLACEHOLDER);
		await input.fill(itemName);
		await input.press('Enter');

		const unchecked = page.locator(
			`[data-testid="item-row"][data-name="${itemName}"][data-checked="false"]`
		);
		await expect(unchecked).toBeVisible({ timeout: 10_000 });

		await swipeRow(page, itemName, 180);

		const checked = page.locator(
			`[data-testid="item-row"][data-name="${itemName}"][data-checked="true"]`
		);
		await expect(checked).toBeVisible({ timeout: 10_000 });
	});

	test('SW-02: checked item + swipe left → marked unchecked', async ({ page }) => {
		const itemName = `SW-02-${Date.now()}`;
		const input = page.getByPlaceholder(ADD_ITEM_PLACEHOLDER);
		await input.fill(itemName);
		await input.press('Enter');

		await expect(
			page.locator(`[data-testid="item-row"][data-name="${itemName}"][data-checked="false"]`)
		).toBeVisible({ timeout: 10_000 });

		// Check it first via a swipe right.
		await swipeRow(page, itemName, 180);
		await expect(
			page.locator(`[data-testid="item-row"][data-name="${itemName}"][data-checked="true"]`)
		).toBeVisible({ timeout: 10_000 });

		// Now swipe left to uncheck.
		await swipeRow(page, itemName, -180);
		await expect(
			page.locator(`[data-testid="item-row"][data-name="${itemName}"][data-checked="false"]`)
		).toBeVisible({ timeout: 10_000 });
	});
});
