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

afterEach(cleanup);

function makeAnnotation(id = 'ann-1') {
	return {
		id,
		documentId: 'doc-1',
		pageNumber: 1,
		x: 0.1,
		y: 0.1,
		width: 0.3,
		height: 0.2,
		color: '#00C7B1',
		createdAt: new Date().toISOString()
	};
}

describe('AnnotationShape', () => {
	it('renders the annotation element', async () => {
		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: false,
			isActive: false,
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		await expect.element(page.getByTestId('annotation-ann-1')).toBeInTheDocument();
	});

	it('does not show delete button when showDelete is false', async () => {
		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: true,
			isActive: false,
			showDelete: false,
			onDeleteRequest: vi.fn(),
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		await expect.element(page.getByTestId('annotation-delete-ann-1')).not.toBeInTheDocument();
	});

	it('does not show delete button when showDelete is true but neither hovered nor active', async () => {
		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: false,
			isActive: false,
			showDelete: true,
			onDeleteRequest: vi.fn(),
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		await expect.element(page.getByTestId('annotation-delete-ann-1')).not.toBeInTheDocument();
	});

	it('shows delete button when showDelete is true and isHovered is true', async () => {
		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: true,
			isActive: false,
			showDelete: true,
			onDeleteRequest: vi.fn(),
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		await expect.element(page.getByTestId('annotation-delete-ann-1')).toBeInTheDocument();
	});

	it('shows delete button when showDelete is true and isActive is true', async () => {
		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: false,
			isActive: true,
			showDelete: true,
			onDeleteRequest: vi.fn(),
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		await expect.element(page.getByTestId('annotation-delete-ann-1')).toBeInTheDocument();
	});

	it('calls onDeleteRequest when delete button is clicked', async () => {
		const onDeleteRequest = vi.fn();

		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: true,
			isActive: false,
			showDelete: true,
			onDeleteRequest,
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		const deleteBtn = page.getByTestId('annotation-delete-ann-1');
		await deleteBtn.click();

		expect(onDeleteRequest).toHaveBeenCalledOnce();
	});

	it('does not call onclick when delete button is clicked', async () => {
		const onclick = vi.fn();
		const onDeleteRequest = vi.fn();

		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: true,
			isActive: false,
			showDelete: true,
			onDeleteRequest,
			onclick,
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		const deleteBtn = page.getByTestId('annotation-delete-ann-1');
		await deleteBtn.click();

		expect(onclick).not.toHaveBeenCalled();
		expect(onDeleteRequest).toHaveBeenCalledOnce();
	});

	it('calls onDeleteRequest when Delete key is pressed on the annotation', async () => {
		const onDeleteRequest = vi.fn();

		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: false,
			isActive: true,
			showDelete: true,
			onDeleteRequest,
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		const annotationEl = page.getByTestId('annotation-ann-1').element() as HTMLElement;
		annotationEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', bubbles: true }));

		expect(onDeleteRequest).toHaveBeenCalledOnce();
	});

	it('does not call onDeleteRequest on Delete key when showDelete is false', async () => {
		const onDeleteRequest = vi.fn();

		render(AnnotationShape, {
			annotation: makeAnnotation(),
			isHovered: false,
			isActive: true,
			showDelete: false,
			onDeleteRequest,
			onclick: () => {},
			onpointerenter: () => {},
			onpointerleave: () => {}
		});

		const annotationEl = page.getByTestId('annotation-ann-1').element() as HTMLElement;
		annotationEl.dispatchEvent(new KeyboardEvent('keydown', { key: 'Delete', bubbles: true }));

		expect(onDeleteRequest).not.toHaveBeenCalled();
	});
});
