import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page as browserPage } from 'vitest/browser';
import { goto } from '$app/navigation';
import { page } from '$app/state';
import PersonFilterBar from './PersonFilterBar.svelte';

vi.mock('$app/navigation', () => ({ goto: vi.fn() }));
vi.mock('$app/state', () => ({ page: { url: new URL('http://localhost/persons') } }));

const gotoMock = vi.mocked(goto);

function setUrl(search: string) {
	(page as unknown as { url: URL }).url = new URL(`http://localhost/persons${search}`);
}

beforeEach(() => {
	gotoMock.mockClear();
	setUrl('');
});
afterEach(cleanup);

const baseProps = {
	type: undefined,
	familyOnly: false,
	hasDocuments: false,
	review: false,
	needsReviewCount: 12,
	canWrite: true
};

describe('PersonFilterBar — chip activation', () => {
	it('activating a type chip sets type and resets page', async () => {
		setUrl('?page=3&q=Anna');
		render(PersonFilterBar, { props: baseProps });

		await browserPage.getByRole('button', { name: 'Institution' }).click();

		expect(gotoMock).toHaveBeenCalled();
		const target = gotoMock.mock.calls.at(-1)![0] as string;
		const url = new URL(target, 'http://localhost');
		expect(url.searchParams.get('type')).toBe('INSTITUTION');
		expect(url.searchParams.get('q')).toBe('Anna'); // preserved
		expect(url.searchParams.get('page')).toBeNull(); // reset
	});

	it('activating "Nur Familie" sets familyOnly=true', async () => {
		render(PersonFilterBar, { props: baseProps });

		await browserPage.getByRole('button', { name: 'Nur Familie' }).click();

		const target = gotoMock.mock.calls.at(-1)![0] as string;
		const url = new URL(target, 'http://localhost');
		expect(url.searchParams.get('familyOnly')).toBe('true');
	});

	it('deactivating an already-active chip removes the param', async () => {
		render(PersonFilterBar, { props: { ...baseProps, hasDocuments: true } });

		await browserPage.getByRole('button', { name: 'Mit Dokumenten' }).click();

		const target = gotoMock.mock.calls.at(-1)![0] as string;
		const url = new URL(target, 'http://localhost');
		expect(url.searchParams.get('hasDocuments')).toBeNull();
	});
});

describe('PersonFilterBar — review toggle', () => {
	it('renders a switch with the needs-review count in its accessible name', async () => {
		render(PersonFilterBar, { props: baseProps });
		await expect
			.element(browserPage.getByRole('switch', { name: /Zu prüfen \(12\)/ }))
			.toBeVisible();
	});

	it('is hidden for users without write permission', async () => {
		render(PersonFilterBar, { props: { ...baseProps, canWrite: false } });
		await expect.element(browserPage.getByRole('switch')).not.toBeInTheDocument();
	});

	it('toggling on sets review=true', async () => {
		render(PersonFilterBar, { props: baseProps });

		await browserPage.getByRole('switch').click();

		const target = gotoMock.mock.calls.at(-1)![0] as string;
		const url = new URL(target, 'http://localhost');
		expect(url.searchParams.get('review')).toBe('true');
	});
});
