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

afterEach(cleanup);

const sender = { id: 's1', firstName: 'Anna', lastName: 'Schmidt', displayName: 'Anna Schmidt' };
const receiver = (id: string, name: string) => ({
	id,
	firstName: name.split(' ')[0],
	lastName: name.split(' ').slice(1).join(' ') || name,
	displayName: name
});

const baseProps = {
	documentDate: '1923-04-15' as string | null,
	location: 'Berlin' as string | null,
	status: 'UPLOADED',
	sender: null as typeof sender | null,
	receivers: [] as ReturnType<typeof receiver>[],
	tags: [] as { id: string; name: string }[],
	inferredRelationship: null,
	geschichten: [] as {
		id: string;
		title: string;
		publishedAt?: string;
		author?: { firstName?: string; lastName?: string; email: string };
	}[],
	documentId: 'doc-1',
	canBlogWrite: false
};

describe('DocumentMetadataDrawer', () => {
	it('renders the three default section headings', async () => {
		render(DocumentMetadataDrawer, { props: baseProps });

		await expect.element(page.getByRole('heading', { name: 'Details' })).toBeVisible();
		await expect.element(page.getByRole('heading', { name: 'Personen' })).toBeVisible();
		await expect.element(page.getByRole('heading', { name: 'Schlagwörter' })).toBeVisible();
	});

	it('renders the formatted long date when documentDate is provided', async () => {
		render(DocumentMetadataDrawer, { props: baseProps });

		// formatDate default ('long') format is "15. April 1923" in de-DE.
		await expect.element(page.getByText(/1923/)).toBeVisible();
	});

	it('renders an em-dash when documentDate is null', async () => {
		render(DocumentMetadataDrawer, { props: { ...baseProps, documentDate: null } });

		// The dash appears in date AND location AND geschichten — multiple matches expected
		const dashes = document.querySelectorAll('dd, p');
		const dashTexts = Array.from(dashes)
			.map((el) => el.textContent?.trim())
			.filter((t) => t === '—');
		expect(dashTexts.length).toBeGreaterThan(0);
	});

	it('shows an em-dash and never the raw cell for an undated, raw-only document', async () => {
		render(DocumentMetadataDrawer, {
			props: { ...baseProps, documentDate: null, metaDateRaw: 'Sommer 1916' }
		});

		await expect.element(page.getByText('Sommer 1916')).not.toBeInTheDocument();
		const dashTexts = Array.from(document.querySelectorAll('dd, p'))
			.map((el) => el.textContent?.trim())
			.filter((t) => t === '—');
		expect(dashTexts.length).toBeGreaterThan(0);
	});

	it('renders the no-persons placeholder when sender and receivers are empty', async () => {
		render(DocumentMetadataDrawer, { props: baseProps });

		await expect.element(page.getByText('Keine Personen zugeordnet')).toBeVisible();
	});

	it('renders the sender and inferred relationship label when both are present', async () => {
		render(DocumentMetadataDrawer, {
			props: {
				...baseProps,
				sender,
				inferredRelationship: { labelFromA: 'Vater', labelFromB: 'Tochter' }
			}
		});

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

	it('renders the receivers list with up to five visible by default', async () => {
		const receivers = Array.from({ length: 7 }, (_, i) => receiver(`r${i}`, `Person ${i}`));
		render(DocumentMetadataDrawer, {
			props: { ...baseProps, sender, receivers }
		});

		await expect.element(page.getByText('Person 0')).toBeVisible();
		await expect.element(page.getByText('Person 4')).toBeVisible();
		await expect.element(page.getByText('Person 5')).not.toBeInTheDocument();
	});

	it('renders the +N more button when there are more than five receivers', async () => {
		const receivers = Array.from({ length: 8 }, (_, i) => receiver(`r${i}`, `Person ${i}`));
		render(DocumentMetadataDrawer, {
			props: { ...baseProps, sender, receivers }
		});

		await expect.element(page.getByRole('button', { name: /\+3 weitere/i })).toBeVisible();
	});

	it('expands the receiver list when the +N more button is clicked', async () => {
		const receivers = Array.from({ length: 8 }, (_, i) => receiver(`r${i}`, `Person ${i}`));
		render(DocumentMetadataDrawer, {
			props: { ...baseProps, sender, receivers }
		});

		await page.getByRole('button', { name: /\+3 weitere/i }).click();

		await expect.element(page.getByText('Person 7')).toBeVisible();
	});

	it('renders the no-tags placeholder when tags is empty', async () => {
		render(DocumentMetadataDrawer, { props: baseProps });

		await expect.element(page.getByText('Keine Schlagwörter zugeordnet')).toBeVisible();
	});

	it('renders one anchor per tag when tags are present', async () => {
		render(DocumentMetadataDrawer, {
			props: {
				...baseProps,
				tags: [
					{ id: 't1', name: 'Familie' },
					{ id: 't2', name: 'Reise' }
				]
			}
		});

		await expect
			.element(page.getByRole('link', { name: 'Familie' }))
			.toHaveAttribute('href', '/?tag=Familie');
		await expect
			.element(page.getByRole('link', { name: 'Reise' }))
			.toHaveAttribute('href', '/?tag=Reise');
	});

	it('hides the geschichten column when there are no stories and no canBlogWrite', async () => {
		render(DocumentMetadataDrawer, { props: baseProps });

		await expect
			.element(page.getByRole('heading', { name: 'Geschichten' }))
			.not.toBeInTheDocument();
	});

	it('shows the geschichten column when canBlogWrite is true even with no stories', async () => {
		render(DocumentMetadataDrawer, { props: { ...baseProps, canBlogWrite: true } });

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

	it('renders the attach link to the new-geschichte route when canBlogWrite + documentId', async () => {
		render(DocumentMetadataDrawer, {
			props: { ...baseProps, canBlogWrite: true, documentId: 'doc-42' }
		});

		const links = document.querySelectorAll('a[href*="/geschichten/new?documentId="]');
		expect(links.length).toBe(1);
		expect((links[0] as HTMLAnchorElement).href).toContain('documentId=doc-42');
	});

	it('renders the geschichten list when stories are present', async () => {
		render(DocumentMetadataDrawer, {
			props: {
				...baseProps,
				geschichten: [
					{
						id: 'g1',
						title: 'Reise nach Berlin',
						publishedAt: '2026-04-15T10:00:00Z',
						author: { firstName: 'Anna', lastName: 'Schmidt', email: 'anna@x' }
					}
				]
			}
		});

		await expect.element(page.getByRole('link', { name: /reise nach berlin/i })).toBeVisible();
	});

	it('renders the show-all geschichten link when there are at least three stories', async () => {
		render(DocumentMetadataDrawer, {
			props: {
				...baseProps,
				geschichten: Array.from({ length: 3 }, (_, i) => ({
					id: `g${i}`,
					title: `Geschichte ${i}`,
					publishedAt: '2026-04-15T10:00:00Z',
					author: { firstName: 'Anna', lastName: 'Schmidt', email: 'anna@x' }
				}))
			}
		});

		await expect.element(page.getByText(/zeige alle|alle/i)).toBeVisible();
	});

	it('renders the receiver-only inferred relationship pill only when there is exactly one receiver', async () => {
		render(DocumentMetadataDrawer, {
			props: {
				...baseProps,
				sender,
				receivers: [receiver('r1', 'Bert Meier')],
				inferredRelationship: { labelFromA: 'Vater', labelFromB: 'Tochter' }
			}
		});

		// Both labels should be visible — Vater for sender, Tochter for the single receiver
		await expect.element(page.getByText(/vater/i)).toBeVisible();
		await expect.element(page.getByText(/tochter/i)).toBeVisible();
	});
});
