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

afterEach(cleanup);

const basePerson = {
	id: 'p-1',
	firstName: 'Anna',
	lastName: 'Schmidt',
	displayName: 'Anna Schmidt',
	personType: 'PERSON' as const
};

const baseData = (overrides: Record<string, unknown> = {}) => ({
	person: basePerson,
	canWrite: false,
	canBlogWrite: false,
	aliases: [] as { name: string; from: string; to: string }[],
	relationships: [],
	inferredRelationships: [],
	sentDocuments: [] as Array<{
		id: string;
		title: string;
		status: string;
		receivers?: { id: string; displayName: string }[];
	}>,
	receivedDocuments: [] as Array<{
		id: string;
		title: string;
		status: string;
		sender?: { id: string; displayName: string };
	}>,
	geschichten: undefined,
	...overrides
});

describe('persons/[id] page', () => {
	it('renders the person heading via PersonCard', async () => {
		render(PersonDetailPage, { props: { data: baseData() } });

		await expect.element(page.getByRole('heading', { name: 'Anna Schmidt' })).toBeVisible();
	});

	it('renders both document section headings', async () => {
		render(PersonDetailPage, { props: { data: baseData() } });

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

	it('renders empty messages when no documents are present', async () => {
		render(PersonDetailPage, { props: { data: baseData() } });

		await expect
			.element(page.getByText('Diese Person ist noch nicht als Absender verknüpft.'))
			.toBeVisible();
		await expect
			.element(page.getByText('Diese Person ist noch nicht als Empfänger verknüpft.'))
			.toBeVisible();
	});

	it('does not render the GeschichtenCard when there are no geschichten', async () => {
		render(PersonDetailPage, { props: { data: baseData({ geschichten: [] }) } });

		const geschichteHeadings = Array.from(document.querySelectorAll('h2'))
			.map((h) => h.textContent ?? '')
			.filter((t) => /geschichte/i.test(t));
		expect(geschichteHeadings.length).toBe(0);
	});

	it('renders co-correspondents derived from sent documents receivers', async () => {
		const data = baseData({
			sentDocuments: [
				{
					id: 'd1',
					title: 'B1',
					status: 'UPLOADED',
					receivers: [{ id: 'r1', displayName: 'Bert Meier' }]
				},
				{
					id: 'd2',
					title: 'B2',
					status: 'UPLOADED',
					receivers: [{ id: 'r1', displayName: 'Bert Meier' }]
				}
			]
		});
		render(PersonDetailPage, { props: { data } });

		await expect.element(page.getByText(/häufige korrespondenten/i)).toBeVisible();
	});

	it('shows the edit button via PersonCard when canWrite is true', async () => {
		render(PersonDetailPage, { props: { data: baseData({ canWrite: true }) } });

		await expect
			.element(page.getByRole('link', { name: /bearbeiten/i }))
			.toHaveAttribute('href', '/persons/p-1/edit');
	});

	it('renders co-correspondents derived from received documents senders', async () => {
		const data = baseData({
			receivedDocuments: [
				{
					id: 'd-r1',
					title: 'R1',
					status: 'UPLOADED',
					sender: { id: 's1', displayName: 'Carl Brandt' }
				},
				{
					id: 'd-r2',
					title: 'R2',
					status: 'UPLOADED',
					sender: { id: 's1', displayName: 'Carl Brandt' }
				}
			]
		});
		render(PersonDetailPage, { props: { data } });

		expect(document.body.textContent).toContain('Carl Brandt');
	});

	it('skips the sender when sender id equals the current person id (loops cleanly)', async () => {
		const data = baseData({
			receivedDocuments: [
				{
					id: 'd-self',
					title: 'Self-letter',
					status: 'UPLOADED',
					sender: { id: 'p-1', displayName: 'Anna Schmidt' }
				}
			]
		});
		// Self-skip branch: the self-letter is rendered without re-rendering the sender chip.
		render(PersonDetailPage, { props: { data } });
		expect(document.body.textContent).toContain('Self-letter');
	});

	it('renders the GeschichtenCard when geschichten array has items', async () => {
		render(PersonDetailPage, {
			props: {
				data: baseData({
					geschichten: [
						{
							id: 'g1',
							title: 'Reise',
							body: '<p>...</p>',
							publishedAt: '2026-04-15T10:00:00Z'
						}
					]
				})
			}
		});

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

	it('caps the co-correspondents list at 5 entries', async () => {
		const sent = Array.from({ length: 8 }, (_, i) => ({
			id: `d-${i}`,
			title: `Brief ${i}`,
			status: 'UPLOADED',
			receivers: [{ id: `r-${i}`, displayName: `Person ${i}` }]
		}));
		render(PersonDetailPage, { props: { data: baseData({ sentDocuments: sent }) } });

		const correspondentsCard = Array.from(document.querySelectorAll('h2')).find((h) =>
			/korrespondenten/i.test(h.textContent ?? '')
		)?.parentElement;
		const links = correspondentsCard?.querySelectorAll('a[href^="/persons/"]') ?? [];
		// At most 5 person links inside the card
		expect(links.length).toBeLessThanOrEqual(5);
	});
});
