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

vi.mock('$app/navigation', () => ({
	beforeNavigate: () => {},
	afterNavigate: () => {},
	goto: vi.fn(),
	invalidate: vi.fn(),
	invalidateAll: vi.fn(),
	preloadCode: vi.fn(),
	preloadData: vi.fn(),
	pushState: vi.fn(),
	replaceState: vi.fn(),
	disableScrollHandling: vi.fn(),
	onNavigate: () => () => {}
}));

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

const { default: PersonsListPage } = await import('./+page.svelte');

afterEach(cleanup);

const baseData = (overrides: Record<string, unknown> = {}) => ({
	persons: [] as Array<{
		id: string;
		firstName?: string;
		lastName: string;
		displayName: string;
		personType?: string;
		alias?: string;
		birthYear?: number;
		deathYear?: number;
		documentCount?: number;
		provisional?: boolean;
	}>,
	stats: { totalPersons: 0, totalDocuments: 0 },
	totalElements: 0,
	totalPages: 0,
	pageNumber: 0,
	pageSize: 50,
	filters: { type: undefined, familyOnly: false, hasDocuments: false, review: false },
	needsReviewCount: 0,
	canWrite: false,
	q: '',
	...overrides
});

describe('persons/+ page', () => {
	it('renders the heading and stats bar', async () => {
		render(PersonsListPage, {
			props: { data: baseData({ stats: { totalPersons: 5, totalDocuments: 10 } }) }
		});

		await expect.element(page.getByRole('heading', { name: /personen/i })).toBeVisible();
	});

	it('renders the empty state when persons is empty', async () => {
		render(PersonsListPage, { props: { data: baseData() } });

		// PersonsEmptyState renders an empty-state element — verify no person cards
		const personLinks = document.querySelectorAll('a[href^="/persons/"]');
		expect(personLinks.length).toBe(0);
	});

	it('renders a card per person when populated', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON'
						},
						{
							id: 'p2',
							firstName: '',
							lastName: 'Acme',
							displayName: 'Acme',
							personType: 'INSTITUTION'
						}
					]
				})
			}
		});

		await expect.element(page.getByText('Anna Schmidt')).toBeVisible();
		await expect.element(page.getByText('Acme')).toBeVisible();
	});

	it('shows the new-person CTA when canWrite is true', async () => {
		render(PersonsListPage, { props: { data: baseData({ canWrite: true }) } });

		await expect
			.element(page.getByRole('link', { name: /neue person/i }))
			.toHaveAttribute('href', '/persons/new');
	});

	it('hides the new-person CTA when canWrite is false', async () => {
		render(PersonsListPage, { props: { data: baseData({ canWrite: false }) } });

		await expect.element(page.getByRole('link', { name: /neue person/i })).not.toBeInTheDocument();
	});

	it('preselects the search input from data.q', async () => {
		render(PersonsListPage, { props: { data: baseData({ q: 'Schmidt' }) } });

		const search = (await page.getByLabelText(/suche/i).element()) as HTMLInputElement;
		expect(search.value).toBe('Schmidt');
	});

	it('renders the doc-count chip with singular label for documentCount=1', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							documentCount: 1
						}
					]
				})
			}
		});

		await expect.element(page.getByText('1 Dok.')).toBeVisible();
	});

	it('renders the doc-count chip with plural label for documentCount > 1', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							documentCount: 5
						}
					]
				})
			}
		});

		await expect.element(page.getByText('5 Dok.')).toBeVisible();
	});

	it('omits the doc-count chip when documentCount is 0', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							documentCount: 0
						}
					]
				})
			}
		});

		await expect.element(page.getByText(/^\d+ Dok\.$/)).not.toBeInTheDocument();
	});

	it('renders the alias in italic when set', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							alias: 'Anni'
						}
					]
				})
			}
		});

		await expect.element(page.getByText(/Anni/)).toBeVisible();
	});

	it('shows the institution svg icon for INSTITUTION personType', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: '',
							lastName: 'Bundesarchiv',
							displayName: 'Bundesarchiv',
							personType: 'INSTITUTION'
						}
					]
				})
			}
		});

		// SVG icon (not initials text)
		const card = document.querySelector('a[href="/persons/p1"]');
		expect(card?.querySelector('svg')).not.toBeNull();
	});

	it('shows the group svg icon for GROUP personType', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'pg',
							firstName: '',
							lastName: 'Family X',
							displayName: 'Family X',
							personType: 'GROUP'
						}
					]
				})
			}
		});

		const card = document.querySelector('a[href="/persons/pg"]');
		expect(card?.querySelector('svg')).not.toBeNull();
	});

	it('shows the unknown svg icon for UNKNOWN personType', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'pu',
							firstName: '',
							lastName: 'Unknown',
							displayName: 'Unknown',
							personType: 'UNKNOWN'
						}
					]
				})
			}
		});

		const card = document.querySelector('a[href="/persons/pu"]');
		expect(card?.querySelector('svg')).not.toBeNull();
	});

	it('renders only birthYear with em-dash when no death year', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							birthYear: 1899
						}
					]
				})
			}
		});

		expect(document.body.textContent).toContain('1899');
	});

	it('renders only deathYear with em-dash when no birth year', async () => {
		render(PersonsListPage, {
			props: {
				data: baseData({
					persons: [
						{
							id: 'p1',
							firstName: 'Anna',
							lastName: 'Schmidt',
							displayName: 'Anna Schmidt',
							personType: 'PERSON',
							deathYear: 1950
						}
					]
				})
			}
		});

		expect(document.body.textContent).toContain('1950');
	});
});
