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

const mockPage = {
	status: 500,
	error: { message: 'Internal Error', errorId: undefined } as {
		message: string;
		errorId?: string;
	} | null
};

vi.mock('$app/state', () => ({
	get page() {
		return mockPage;
	}
}));

vi.mock('$lib/paraglide/messages.js', () => ({
	m: {
		page_title_error: () => 'Es ist etwas schiefgelaufen.',
		error_internal_error: () => 'Ein unerwarteter Fehler ist aufgetreten.',
		error_page_id_label: () => 'Fehler-ID',
		error_copy_id_label: () => 'ID kopieren',
		error_copied: () => 'Kopiert!'
	}
}));

afterEach(cleanup);

async function loadComponent() {
	return (await import('./+error.svelte')).default;
}

describe('+error.svelte', () => {
	it('renders the page status code', async () => {
		mockPage.status = 404;
		mockPage.error = { message: 'Not Found' };

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect.element(browserPage.getByText('404')).toBeVisible();
	});

	it('renders the error message text from page.error.message', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Database unavailable' };

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect.element(browserPage.getByText('Database unavailable')).toBeVisible();
	});

	it('falls back to error_internal_error message when page.error is null', async () => {
		mockPage.status = 500;
		mockPage.error = null;

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect
			.element(browserPage.getByText('Ein unerwarteter Fehler ist aufgetreten.'))
			.toBeVisible();
	});

	it('shows errorId when page.error.errorId is set', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Something broke', errorId: 'abc-123-def' };

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect.element(browserPage.getByText('abc-123-def')).toBeVisible();
	});

	it('shows copy button when errorId is present', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Something broke', errorId: 'abc-123-def' };

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect.element(browserPage.getByRole('button', { name: 'ID kopieren' })).toBeVisible();
	});

	it('does not render errorId section when errorId is absent', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Something broke' };

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await expect.element(browserPage.getByText('Fehler-ID')).not.toBeInTheDocument();
	});

	it('shows "Kopiert!" after clicking the copy button', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Something broke', errorId: 'abc-123-def' };

		Object.defineProperty(navigator, 'clipboard', {
			value: { writeText: vi.fn().mockResolvedValue(undefined) },
			configurable: true,
			writable: true
		});

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await browserPage.getByRole('button', { name: 'ID kopieren' }).click();
		await expect.element(browserPage.getByText('Kopiert!')).toBeVisible();
	});

	it('does not show "Kopiert!" when clipboard write is rejected', async () => {
		mockPage.status = 500;
		mockPage.error = { message: 'Something broke', errorId: 'abc-123-def' };

		Object.defineProperty(navigator, 'clipboard', {
			value: { writeText: vi.fn().mockRejectedValue(new Error('denied')) },
			configurable: true,
			writable: true
		});

		const ErrorPage = await loadComponent();
		render(ErrorPage);

		await browserPage.getByRole('button', { name: 'ID kopieren' }).click();
		await expect.element(browserPage.getByText('Kopiert!')).not.toBeInTheDocument();
	});
});
