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

vi.mock('$env/static/public', () => ({ PUBLIC_NOTIFICATION_POLL_MS: '60000' }));

afterEach(cleanup);

const emptySnippet = createRawSnippet(() => ({ render: () => '<span></span>' }));
import Layout from './+layout.svelte';

const tick = () => new Promise((r) => setTimeout(r, 0));

// Minimal data required by the layout
const makeData = (overrides = {}) => ({
	user: {
		id: '1',
		firstName: 'Max',
		lastName: 'Müller',
		email: 'max@example.com',
		groups: [],
		enabled: true,
		createdAt: ''
	},
	canWrite: true,
	canAnnotate: false,
	canBlogWrite: false,
	...overrides
});

// ─── User avatar ──────────────────────────────────────────────────────────────

describe('Layout – user avatar button', () => {
	it('shows user initials when first and last name are set', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		await expect.element(page.getByRole('button', { name: /MM/ })).toBeInTheDocument();
	});

	it('shows fallback icon button when names are not set', async () => {
		render(Layout, {
			data: makeData({
				user: { id: '1', email: 'fallback@example.com', groups: [], enabled: true, createdAt: '' }
			}),
			children: emptySnippet
		});
		// Button should still exist (with aria-label for accessibility)
		await expect.element(page.getByRole('button', { name: /Profil/i })).toBeInTheDocument();
	});
});

// ─── Upload link ──────────────────────────────────────────────────────────────

describe('Layout – upload link', () => {
	it('has aria-label for screen reader access', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		const link = page.getByRole('link', { name: /Hochladen|Upload|Subir/i });
		await expect.element(link).toHaveAttribute('aria-label');
	});

	it('navigates to /documents/new', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		const link = page.getByRole('link', { name: /Hochladen|Upload|Subir/i });
		await expect.element(link).toHaveAttribute('href', '/documents/new');
	});
});

// ─── Dropdown ─────────────────────────────────────────────────────────────────

describe('Layout – user dropdown', () => {
	it('dropdown is hidden initially', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		await tick();
		await expect.element(page.getByRole('link', { name: /Profil/i })).not.toBeInTheDocument();
	});

	it('opens dropdown on button click', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		await page.getByRole('button', { name: /MM/ }).click();
		await expect.element(page.getByRole('link', { name: /Profil/i })).toBeInTheDocument();
	});

	it('profile link points to /profile', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		await page.getByRole('button', { name: /MM/ }).click();
		await expect
			.element(page.getByRole('link', { name: /Profil/i }))
			.toHaveAttribute('href', '/profile');
	});

	it('logout button is in the dropdown', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		await page.getByRole('button', { name: /MM/ }).click();
		await expect.element(page.getByRole('button', { name: /Abmelden/i })).toBeInTheDocument();
	});

	it('closes dropdown when Escape is pressed', async () => {
		render(Layout, { data: makeData(), children: emptySnippet });
		const btn = page.getByRole('button', { name: /MM/ });
		await btn.click();
		await expect.element(page.getByRole('link', { name: /Profil/i })).toBeInTheDocument();
		await userEvent.keyboard('{Escape}');
		await tick();
		await expect.element(page.getByRole('link', { name: /Profil/i })).not.toBeInTheDocument();
	});
});
