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

const makeStory = (id: string, title: string, body: string | undefined = '<p>Body</p>') => ({
	id,
	title,
	body,
	status: 'PUBLISHED' as const,
	type: 'STORY' as const,
	publishedAt: '2024-04-01T12:00:00',
	createdAt: '2024-03-01T12:00:00',
	updatedAt: '2024-04-01T12:00:00',
	persons: [],
	items: [],
	author: {
		id: 'u1',
		firstName: 'Marcel',
		lastName: 'Raddatz',
		enabled: true,
		notifyOnReply: false,
		notifyOnMention: false,
		groups: [],
		createdAt: '2024-01-01T00:00:00',
		color: '#000'
	}
});

afterEach(() => cleanup());

describe('GeschichtenCard', () => {
	it('renders nothing when geschichten is empty', async () => {
		render(GeschichtenCard, {
			geschichten: [],
			personId: 'p1',
			personName: 'Franz',
			canWrite: true
		});
		// No heading, no list — the entire <section> should not exist
		expect(
			document.querySelector('section[aria-labelledby="geschichten-card-heading"]')
		).toBeNull();
	});

	it('renders the section heading and stories when geschichten is non-empty', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'Erinnerung an Franz')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		await expect.element(page.getByText('Geschichten')).toBeInTheDocument();
		// The whole row is one link to the story; matching on the title text via
		// a partial regex tolerates trailing author/date metadata in the
		// accessible name.
		const link = await page
			.getByRole('link', { name: /Erinnerung an Franz/ })
			.first()
			.element();
		expect(link.getAttribute('href')).toBe('/geschichten/g1');
	});

	it('makes the entire story row a single clickable link', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'A title', '<p>Some body excerpt text</p>')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		// The body-excerpt text is inside the same <a> as the title.
		const links = await page.getByRole('link', { name: /A title/ }).all();
		expect(links.length).toBeGreaterThan(0);
		const linkEl = await links[0].element();
		expect(linkEl.tagName).toBe('A');
		expect(linkEl.textContent).toContain('Some body excerpt text');
	});

	it('hides the "+ Geschichte schreiben" link when canWrite is false', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'A story')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		const writeLinks = await page.getByText(/Geschichte schreiben/).all();
		expect(writeLinks).toHaveLength(0);
	});

	it('shows the write-action link only when canWrite is true', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'A story')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: true
		});
		const link = await page.getByRole('link', { name: /Geschichte schreiben/ }).element();
		expect(link.getAttribute('href')).toBe('/geschichten/new?personId=p1');
	});

	it('hides the "Alle Geschichten zu …" footer link below the 3-story threshold', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'A'), makeStory('g2', 'B')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		const overflow = await page.getByText(/Alle Geschichten zu/).all();
		expect(overflow).toHaveLength(0);
	});

	it('shows the footer link at the 3-story threshold (>= 3)', async () => {
		render(GeschichtenCard, {
			geschichten: [makeStory('g1', 'A'), makeStory('g2', 'B'), makeStory('g3', 'C')],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		const link = await page.getByRole('link', { name: /Alle Geschichten zu Franz/ }).element();
		expect(link.getAttribute('href')).toBe('/geschichten?personId=p1');
	});

	it('JOURNEY type does not bleed a REISE badge into the person-sidebar card', async () => {
		render(GeschichtenCard, {
			geschichten: [{ ...makeStory('g1', 'Reise Berlin'), type: 'JOURNEY' as const }],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		expect(document.querySelector('[data-testid="journey-badge"]')).toBeNull();
	});

	it('renders a plain-text excerpt without HTML markup', async () => {
		render(GeschichtenCard, {
			geschichten: [
				makeStory(
					'g1',
					'Mit HTML',
					'<p>Plain <strong>bold</strong> story</p><script>alert(1)</script>'
				)
			],
			personId: 'p1',
			personName: 'Franz',
			canWrite: false
		});
		// Body excerpt appears once as plain text — no <strong> rendered, no script
		await expect.element(page.getByText(/Plain bold story/)).toBeInTheDocument();
		expect(document.body.innerHTML).not.toContain('<script>');
	});
});
