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

afterEach(cleanup);

const baseProps = (overrides: Record<string, unknown> = {}) => ({
	personId: 'p-1',
	familyMember: false,
	relationships: [] as unknown[],
	inferredRelationships: [] as unknown[],
	canWrite: false,
	relationshipError: null as string | null,
	...overrides
});

describe('StammbaumCard', () => {
	it('renders the heading', async () => {
		render(StammbaumCard, { props: baseProps() });

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

	it('renders the family-member toggle when canWrite is true', async () => {
		render(StammbaumCard, { props: baseProps({ canWrite: true }) });

		await expect.element(page.getByRole('switch')).toBeVisible();
	});

	it('omits the family-member toggle when canWrite is false', async () => {
		render(StammbaumCard, { props: baseProps() });

		await expect.element(page.getByRole('switch')).not.toBeInTheDocument();
	});

	it('marks the toggle as aria-checked=true when familyMember is true', async () => {
		render(StammbaumCard, { props: baseProps({ canWrite: true, familyMember: true }) });

		await expect.element(page.getByRole('switch')).toHaveAttribute('aria-checked', 'true');
	});

	it('renders the in-tree banner when familyMember is true', async () => {
		render(StammbaumCard, { props: baseProps({ familyMember: true }) });

		await expect.element(page.getByText('Erscheint im Stammbaum')).toBeVisible();
		await expect
			.element(page.getByRole('link', { name: /ansehen/i }))
			.toHaveAttribute('href', '/stammbaum?focus=p-1');
	});

	it('hides the in-tree banner when familyMember is false', async () => {
		render(StammbaumCard, { props: baseProps() });

		await expect.element(page.getByText('Erscheint im Stammbaum')).not.toBeInTheDocument();
	});

	it('shows the relationshipError alert when set', async () => {
		render(StammbaumCard, {
			props: baseProps({ relationshipError: 'Beziehung konnte nicht gespeichert werden.' })
		});

		await expect
			.element(page.getByText('Beziehung konnte nicht gespeichert werden.'))
			.toBeVisible();
	});

	it('renders the empty placeholder for direct relationships when none exist', async () => {
		render(StammbaumCard, { props: baseProps() });

		await expect.element(page.getByText('Noch keine Beziehungen bekannt.')).toBeVisible();
	});

	it('hides the inferred-relationships disclosure when there are none', async () => {
		render(StammbaumCard, { props: baseProps() });

		await expect.element(page.getByText('Abgeleitete Beziehungen')).not.toBeInTheDocument();
	});

	it('renders the AddRelationshipForm when canWrite is true', async () => {
		render(StammbaumCard, { props: baseProps({ canWrite: true }) });

		// AddRelationshipForm renders interactive elements
		const buttons = document.querySelectorAll('button');
		expect(buttons.length).toBeGreaterThan(1);
	});

	it('renders direct relationships sorted by relationType order', async () => {
		render(StammbaumCard, {
			props: baseProps({
				relationships: [
					{
						id: 'r-friend',
						relationType: 'FRIEND',
						personA: { id: 'p-1', displayName: 'Anna' },
						personB: { id: 'p-friend', displayName: 'Carlos' }
					},
					{
						id: 'r-parent',
						relationType: 'PARENT_OF',
						personA: { id: 'p-1', displayName: 'Anna' },
						personB: { id: 'p-child', displayName: 'Daniel' }
					}
				]
			})
		});

		const items = document.querySelectorAll('ul.divide-y > li, ul.divide-y > *');
		expect(items.length).toBeGreaterThanOrEqual(2);
	});

	it('renders the date range "from – to" for a relationship with both dates', async () => {
		render(StammbaumCard, {
			props: baseProps({
				relationships: [
					{
						id: 'r-1',
						personId: 'p-1',
						relatedPersonId: 'p-x',
						personDisplayName: 'Anna',
						relatedPersonDisplayName: 'Xavier',
						relationType: 'COLLEAGUE',
						fromDate: '1940-01-01',
						fromDatePrecision: 'YEAR',
						toDate: '1945-01-01',
						toDatePrecision: 'YEAR'
					}
				]
			})
		});

		expect(document.body.textContent).toContain('1940');
		expect(document.body.textContent).toContain('1945');
	});

	it('renders only the start date for a relationship with no end date', async () => {
		render(StammbaumCard, {
			props: baseProps({
				relationships: [
					{
						id: 'r-2',
						personId: 'p-1',
						relatedPersonId: 'p-y',
						personDisplayName: 'Anna',
						relatedPersonDisplayName: 'Yvonne',
						relationType: 'NEIGHBOR',
						fromDate: '1935-01-01',
						fromDatePrecision: 'YEAR',
						toDatePrecision: 'UNKNOWN'
					}
				]
			})
		});

		expect(document.body.textContent).toContain('1935');
		expect(document.body.textContent).not.toContain('1935 –');
	});

	it('renders the inferred-relationships disclosure when topDerived has items', async () => {
		render(StammbaumCard, {
			props: baseProps({
				inferredRelationships: [
					{
						label: 'GRANDPARENT_OF',
						person: { id: 'p-grand', displayName: 'Grandma' }
					}
				]
			})
		});

		await expect.element(page.getByText('Abgeleitete Beziehungen')).toBeVisible();
		expect(document.body.textContent).toContain('Grandma');
	});

	it('caps the inferred relationships at 5 items', async () => {
		const inferred = Array.from({ length: 8 }, (_, i) => ({
			label: 'COUSIN_OF',
			person: { id: `p-cousin-${i}`, displayName: `Cousin ${i}` }
		}));

		render(StammbaumCard, {
			props: baseProps({ inferredRelationships: inferred })
		});

		const items = document.querySelectorAll('details ul > li');
		expect(items.length).toBe(5);
	});
});
