import { afterEach, describe, it, expect, vi } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import EntityNav from './EntityNav.svelte';

vi.mock('$app/state', () => ({
	page: { url: { pathname: '/admin/users' } }
}));

afterEach(cleanup);

const props = {
	userCount: 5,
	groupCount: 3,
	tagCount: 8,
	inviteCount: 2,
	canManageUsers: true,
	canManageTags: true,
	canManagePermissions: true,
	canRunMaintenance: true
};

describe('EntityNav — flyout', () => {
	it('flyout dialog is not visible initially', async () => {
		render(EntityNav, props);
		await expect.element(page.getByRole('dialog')).not.toBeInTheDocument();
	});

	it('clicking a flyout trigger opens the dialog', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
	});

	it('flyout dialog has aria-modal="true"', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toHaveAttribute('aria-modal', 'true');
	});

	it('flyout dialog has an aria-label', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
		const dialog = document.querySelector('[role="dialog"]')!;
		expect(dialog.getAttribute('aria-label')).toBeTruthy();
	});

	it('flyout contains navigation links to each entity', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
		const dialog = document.querySelector('[role="dialog"]')!;
		const links = dialog.querySelectorAll('a[href^="/admin/"]');
		expect(links.length).toBeGreaterThanOrEqual(3);
	});

	it('pressing Escape closes the flyout', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
		document.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }));
		await expect.element(page.getByRole('dialog')).not.toBeInTheDocument();
	});

	it('clicking the backdrop closes the flyout', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
		document.querySelector<HTMLElement>('[data-flyout-backdrop]')!.click();
		await expect.element(page.getByRole('dialog')).not.toBeInTheDocument();
	});

	it('clicking a flyout link closes the flyout', async () => {
		render(EntityNav, props);
		document.querySelector<HTMLButtonElement>('[data-flyout-trigger]')!.click();
		await expect.element(page.getByRole('dialog')).toBeInTheDocument();
		const dialog = document.querySelector('[role="dialog"]')!;
		const link = dialog.querySelector<HTMLAnchorElement>('a[href^="/admin/"]')!;
		// Prevent the browser from navigating the test iframe to /admin/... (which
		// would redirect to /login and kill the iframe connection).  preventDefault()
		// on the capture phase suppresses navigation while still letting the Svelte
		// onclick handler (closeFlyout) run on the bubbling phase.
		link.addEventListener('click', (e) => e.preventDefault(), { capture: true, once: true });
		link.click();
		await expect.element(page.getByRole('dialog')).not.toBeInTheDocument();
	});
});

describe('EntityNav — OCR entry', () => {
	it('renders OCR link when canRunMaintenance is true', async () => {
		render(EntityNav, props);
		await expect.element(page.getByRole('link', { name: /OCR/i })).toBeInTheDocument();
	});

	it('does not render OCR link when canRunMaintenance is false', async () => {
		render(EntityNav, { ...props, canRunMaintenance: false });
		const links = document.querySelectorAll('a[href="/admin/ocr"]');
		expect(links.length).toBe(0);
	});
});
