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

const mockPage = { url: new URL('http://localhost/admin/users') };

vi.mock('$app/state', () => ({
	get page() {
		return mockPage;
	}
}));

beforeEach(() => {
	localStorage.clear();
});

afterEach(cleanup);

async function loadComponent() {
	return (await import('./UsersListPanel.svelte')).default;
}

const baseUsers = [
	{
		id: 'u1',
		email: 'anna@example.com',
		firstName: 'Anna',
		lastName: 'Schmidt',
		groups: [{ id: 'g1', name: 'Familie', permissions: [] }]
	},
	{
		id: 'u2',
		email: 'no-name@example.com',
		firstName: null,
		lastName: null,
		groups: []
	}
];

describe('UsersListPanel', () => {
	it('renders the expanded list with header and search input', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		await expect.element(browserPage.getByText('Alle Benutzer')).toBeVisible();
		await expect.element(browserPage.getByPlaceholder(/benutzer suchen/i)).toBeVisible();
	});

	it('renders one row per user with email + fullName when both names are set', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		await expect.element(browserPage.getByText('anna@example.com')).toBeVisible();
		await expect.element(browserPage.getByText('Anna Schmidt')).toBeVisible();
	});

	it('omits the fullName line when both first and last names are null', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		await expect.element(browserPage.getByText('no-name@example.com')).toBeVisible();
	});

	it('renders group chips when the user has groups', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		await expect.element(browserPage.getByText('Familie')).toBeVisible();
	});

	it('filters the list by the search query', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		const search = (await browserPage
			.getByPlaceholder(/benutzer suchen/i)
			.element()) as HTMLInputElement;
		search.value = 'Anna';
		search.dispatchEvent(new Event('input', { bubbles: true }));

		await expect.element(browserPage.getByText('anna@example.com')).toBeVisible();
		await expect.element(browserPage.getByText('no-name@example.com')).not.toBeInTheDocument();
	});

	it('renders the empty placeholder when filter matches nothing', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		const search = (await browserPage
			.getByPlaceholder(/benutzer suchen/i)
			.element()) as HTMLInputElement;
		search.value = 'NoMatch12345';
		search.dispatchEvent(new Event('input', { bubbles: true }));

		await expect.element(browserPage.getByText('Keine Benutzer vorhanden.')).toBeVisible();
	});

	it('marks the active user with aria-current=page', async () => {
		mockPage.url = new URL('http://localhost/admin/users/u2');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers } });

		const links = Array.from(
			document.querySelectorAll('a[href^="/admin/users/"]')
		) as HTMLAnchorElement[];
		const u2 = links.find((a) => a.href.endsWith('/admin/users/u2'));
		expect(u2?.getAttribute('aria-current')).toBe('page');
	});

	it('renders collapsed view when autocollapse is true', async () => {
		mockPage.url = new URL('http://localhost/admin/users');
		const Panel = await loadComponent();
		render(Panel, { props: { users: baseUsers, autocollapse: true } });

		await expect
			.element(browserPage.getByRole('button', { name: /liste ausklappen/i }))
			.toBeVisible();
	});
});
