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

const personFactory = (id: string, displayName: string) => ({
	id,
	firstName: displayName.split(' ')[0],
	lastName: displayName.split(' ').slice(1).join(' ') || displayName,
	displayName,
	personType: 'PERSON' as const
});

const docFactory = (id: string, title: string, date = '1882-01-01') => ({
	id,
	title,
	documentDate: date,
	originalFilename: `${title}.pdf`,
	status: 'UPLOADED' as const,
	metadataComplete: false,
	scriptType: 'UNKNOWN' as const,
	createdAt: '2024-01-01T00:00:00',
	updatedAt: '2024-01-01T00:00:00'
});

const draftFactory = (overrides: Record<string, unknown> = {}) => ({
	id: 'g1',
	title: 'Existing draft',
	body: '<p>Hello world</p>',
	status: 'DRAFT' as const,
	persons: [],
	documents: [],
	createdAt: '2024-01-01T00:00:00',
	updatedAt: '2024-01-01T00:00:00',
	...overrides
});

afterEach(() => cleanup());

describe('GeschichteEditor — title-required guard', () => {
	it('disables both DRAFT save buttons when the title is empty', async () => {
		const onSubmit = vi.fn().mockResolvedValue(undefined);
		render(GeschichteEditor, { onSubmit });

		const draft = await page.getByRole('button', { name: 'Entwurf speichern' }).element();
		const publish = await page.getByRole('button', { name: 'Veröffentlichen' }).element();
		expect(draft).toHaveProperty('disabled', true);
		expect(publish).toHaveProperty('disabled', true);
	});

	it('shows the inline error after the title field is blurred while empty', async () => {
		const onSubmit = vi.fn();
		render(GeschichteEditor, { onSubmit });

		await userEvent.click(page.getByPlaceholder('Titel der Geschichte'));
		await userEvent.tab(); // blur
		await expect.element(page.getByText('Bitte gib einen Titel ein.')).toBeInTheDocument();
	});
});

describe('GeschichteEditor — save bar adapts to status', () => {
	it('renders DRAFT mode buttons when no geschichte prop is supplied', async () => {
		render(GeschichteEditor, { onSubmit: vi.fn() });
		await expect
			.element(page.getByRole('button', { name: 'Entwurf speichern' }))
			.toBeInTheDocument();
		await expect.element(page.getByRole('button', { name: 'Veröffentlichen' })).toBeInTheDocument();
	});

	it('renders PUBLISHED mode buttons when geschichte.status is PUBLISHED', async () => {
		render(GeschichteEditor, {
			geschichte: draftFactory({ status: 'PUBLISHED', publishedAt: '2024-04-01T12:00:00' }),
			onSubmit: vi.fn()
		});
		await expect.element(page.getByRole('button', { name: 'Speichern' })).toBeInTheDocument();
		await expect
			.element(page.getByRole('button', { name: 'Zurück zu Entwurf' }))
			.toBeInTheDocument();
	});
});

describe('GeschichteEditor — pre-fill', () => {
	it('renders initial persons as chips', async () => {
		render(GeschichteEditor, {
			initialPersons: [personFactory('p1', 'Franz Raddatz')],
			onSubmit: vi.fn()
		});
		await expect.element(page.getByText('Franz Raddatz')).toBeInTheDocument();
	});

	it('renders initial documents as chips', async () => {
		render(GeschichteEditor, {
			initialDocuments: [docFactory('d1', 'Brief von Eugenie')],
			onSubmit: vi.fn()
		});
		await expect.element(page.getByText(/Brief von Eugenie/)).toBeInTheDocument();
	});

	it('populates the title input from a geschichte prop', async () => {
		render(GeschichteEditor, {
			geschichte: draftFactory({ title: 'My existing story' }),
			onSubmit: vi.fn()
		});
		const input = await page.getByPlaceholder('Titel der Geschichte').element();
		expect((input as HTMLInputElement).value).toBe('My existing story');
	});
});

describe('GeschichteEditor — onSubmit payload', () => {
	it('passes the trimmed title and DRAFT status when "Entwurf speichern" is clicked', async () => {
		const onSubmit = vi.fn().mockResolvedValue(undefined);
		render(GeschichteEditor, { onSubmit });

		await userEvent.fill(page.getByPlaceholder('Titel der Geschichte'), '  My title  ');
		await userEvent.click(page.getByRole('button', { name: 'Entwurf speichern' }));

		expect(onSubmit).toHaveBeenCalledTimes(1);
		const payload = onSubmit.mock.calls[0][0];
		expect(payload.title).toBe('My title');
		expect(payload.status).toBe('DRAFT');
	});

	it('passes status=PUBLISHED when "Veröffentlichen" is clicked', async () => {
		const onSubmit = vi.fn().mockResolvedValue(undefined);
		render(GeschichteEditor, { onSubmit });

		await userEvent.fill(page.getByPlaceholder('Titel der Geschichte'), 'Story');
		await userEvent.click(page.getByRole('button', { name: 'Veröffentlichen' }));

		expect(onSubmit).toHaveBeenCalledTimes(1);
		expect(onSubmit.mock.calls[0][0].status).toBe('PUBLISHED');
	});

	it('passes the personIds and documentIds from initial props through onSubmit', async () => {
		const onSubmit = vi.fn().mockResolvedValue(undefined);
		render(GeschichteEditor, {
			initialPersons: [personFactory('p1', 'Franz Raddatz')],
			initialDocuments: [docFactory('d1', 'Brief A')],
			onSubmit
		});

		await userEvent.fill(page.getByPlaceholder('Titel der Geschichte'), 'Story');
		await userEvent.click(page.getByRole('button', { name: 'Entwurf speichern' }));

		expect(onSubmit).toHaveBeenCalledTimes(1);
		const payload = onSubmit.mock.calls[0][0];
		expect(payload.personIds).toEqual(['p1']);
		expect(payload.documentIds).toEqual(['d1']);
	});
});
