import { test, expect, type Page } from '@playwright/test';
import path from 'path';
import { fileURLToPath } from 'url';
import fs from 'fs';
import { AxeBuilder } from '@axe-core/playwright';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const PDF_FIXTURE = path.resolve(__dirname, 'fixtures/minimal.pdf');

/**
 * E2E test for the notification deep-link scroll flow — issue #276.
 *
 * Seeds a document + transcription block + block comment via API, then
 * visits /documents/{id}?commentId=X&annotationId=Y and verifies:
 *   - page enters transcribe mode
 *   - the target comment is visible in the viewport
 *   - focus lands on the comment article
 *   - URL query params are stripped after handling
 */

let docHref: string;
let docId: string;
let annotationId: string;
let commentId: string;

test.describe('Notification deep-link scroll', () => {
	test.beforeAll(async ({ request }) => {
		const createRes = await request.post('/api/documents', {
			multipart: { title: 'E2E Deep-Link Test', documentDate: '1945-05-08' }
		});
		if (!createRes.ok()) throw new Error(`Create document failed: ${createRes.status()}`);
		const doc = await createRes.json();
		docId = doc.id;
		docHref = `/documents/${docId}`;

		const uploadRes = await request.put(`/api/documents/${docId}`, {
			multipart: {
				title: doc.title,
				documentDate: '1945-05-08',
				file: {
					name: 'minimal.pdf',
					mimeType: 'application/pdf',
					buffer: fs.readFileSync(PDF_FIXTURE)
				}
			}
		});
		if (!uploadRes.ok()) throw new Error(`Upload PDF failed: ${uploadRes.status()}`);

		const blockRes = await request.post(`/api/documents/${docId}/transcription-blocks`, {
			data: {
				pageNumber: 1,
				x: 0.1,
				y: 0.1,
				width: 0.3,
				height: 0.1,
				text: 'Seeded line',
				label: null
			}
		});
		if (!blockRes.ok()) throw new Error(`Create block failed: ${blockRes.status()}`);
		const block = await blockRes.json();
		annotationId = block.annotationId;

		const commentRes = await request.post(
			`/api/documents/${docId}/transcription-blocks/${block.id}/comments`,
			{
				data: { content: 'Target comment for deep-link test' }
			}
		);
		if (!commentRes.ok()) throw new Error(`Create comment failed: ${commentRes.status()}`);
		const comment = await commentRes.json();
		commentId = comment.id;
	});

	test.afterAll(async ({ request }) => {
		if (docId) await request.delete(`/api/documents/${docId}`);
	});

	async function openDeepLink(page: Page) {
		const url = `${docHref}?commentId=${commentId}&annotationId=${annotationId}`;
		await page.goto(url);
		await page.waitForSelector('[data-hydrated]');
	}

	for (const viewport of [
		{ width: 320, height: 700, name: 'mobile-320' },
		{ width: 1440, height: 900, name: 'desktop-1440' }
	]) {
		test(`deep-link scrolls comment into view at ${viewport.name}`, async ({ page }) => {
			test.setTimeout(45_000);
			await page.setViewportSize({ width: viewport.width, height: viewport.height });
			await openDeepLink(page);

			// Transcribe mode was auto-entered — Fertig button is visible
			await expect(page.getByRole('button', { name: 'Fertig', exact: true })).toBeVisible({
				timeout: 15_000
			});

			// The target comment article is in the DOM and visible
			const article = page.locator(`#comment-${commentId}`);
			await expect(article).toBeVisible({ timeout: 10_000 });

			// URL query params are stripped after handling
			await expect.poll(() => page.url()).not.toContain('commentId=');
			await expect.poll(() => page.url()).not.toContain('annotationId=');

			await page.screenshot({
				path: `test-results/e2e/notification-deep-link-${viewport.name}.png`
			});
		});
	}

	test('axe accessibility check passes on document detail with deep-link', async ({ page }) => {
		test.setTimeout(45_000);
		await openDeepLink(page);
		await expect(page.locator(`#comment-${commentId}`)).toBeVisible({ timeout: 10_000 });

		const results = await new AxeBuilder({ page }).analyze();
		expect(results.violations).toHaveLength(0);
	});
});

// ── Notification bell — J10 ────────────────────────────────────────────────
//
// Verifies the notification bell in the global header: clicking it opens the
// dropdown and it closes on Escape. Full mark-as-read and navigation flows are
// tracked in a follow-up issue.

test.describe('Notification bell', () => {
	let bellDocId: string;

	test.beforeAll(async ({ request }) => {
		const stamp = Date.now().toString(36);
		// Seed a document + comment to ensure the notification list has content to render.
		const createRes = await request.post('/api/documents', {
			multipart: { title: `E2E Bell Test Doc ${stamp}`, documentDate: '1930-01-01' }
		});
		if (!createRes.ok()) throw new Error(`Create document failed: ${createRes.status()}`);
		const doc = await createRes.json();
		bellDocId = doc.id;

		const commentRes = await request.post(`/api/documents/${bellDocId}/comments`, {
			data: { content: 'Bell test comment' }
		});
		if (!commentRes.ok()) throw new Error(`Create comment failed: ${commentRes.status()}`);
	});

	test.afterAll(async ({ request }) => {
		if (bellDocId) await request.delete(`/api/documents/${bellDocId}`);
	});

	test('bell opens dropdown, shows notifications list', async ({ page }) => {
		test.setTimeout(30_000);

		await page.goto('/');
		await page.waitForSelector('[data-hydrated]');

		// Click the notification bell button.
		const bell = page
			.locator('button[aria-label*="Benachrichtigungen"]')
			.or(page.locator('button[aria-label*="benachrichtigung"]'));
		await expect(bell.first()).toBeVisible({ timeout: 10_000 });
		await bell.first().click();

		// Dropdown / dialog opens.
		const dropdown = page
			.locator('[role="dialog"]')
			.or(page.locator('[data-testid="notification-dropdown"]'));
		await expect(dropdown.first()).toBeVisible({ timeout: 8_000 });

		await page.screenshot({ path: 'test-results/e2e/notification-bell-open.png' });

		// Close the dropdown (press Escape).
		await page.keyboard.press('Escape');
		await expect(dropdown.first()).not.toBeVisible({ timeout: 5_000 });
	});
});
