import { describe, it, expect, vi, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page, userEvent } from 'vitest/browser';
import CommentMessage from './CommentMessage.svelte';
import type { FlatMessage } from '$lib/shared/types';

afterEach(cleanup);

const baseMsg: FlatMessage = {
	id: 'msg-1',
	authorId: 'user-1',
	authorName: 'Anna Müller',
	content: 'Hello world',
	createdAt: new Date(Date.now() - 5 * 60_000).toISOString(),
	updatedAt: new Date(Date.now() - 5 * 60_000).toISOString()
};

function defaultProps(overrides: Partial<Parameters<typeof render>[1]> = {}) {
	return {
		message: baseMsg,
		isOwn: false,
		isEditing: false,
		editText: '',
		onEdit: vi.fn(),
		onDelete: vi.fn(),
		onEditTextChange: vi.fn(),
		onEditKeydown: vi.fn(),
		...overrides
	};
}

describe('CommentMessage', () => {
	it('renders author name', async () => {
		render(CommentMessage, defaultProps());
		await expect.element(page.getByText('Anna Müller')).toBeInTheDocument();
	});

	it('renders initials in avatar', async () => {
		render(CommentMessage, defaultProps());
		await expect.element(page.getByText('AM')).toBeInTheDocument();
	});

	it('renders message body', async () => {
		render(CommentMessage, defaultProps());
		await expect.element(page.getByText('Hello world')).toBeInTheDocument();
	});

	it('renders quoted section when content contains a quote', async () => {
		render(
			CommentMessage,
			defaultProps({
				message: { ...baseMsg, content: '> "Interesting passage"\n\nMy reply' }
			})
		);
		await expect.element(page.getByText(/Interesting passage/)).toBeInTheDocument();
		await expect.element(page.getByText('My reply')).toBeInTheDocument();
	});

	it('does not show delete button for messages not owned by current user', async () => {
		render(CommentMessage, defaultProps({ isOwn: false }));
		await expect.element(page.getByRole('button')).not.toBeInTheDocument();
	});

	it('shows delete button for own messages', async () => {
		render(CommentMessage, defaultProps({ isOwn: true }));
		await expect.element(page.getByRole('button')).toBeInTheDocument();
	});

	it('calls onDelete when delete button is clicked', async () => {
		const onDelete = vi.fn();
		render(CommentMessage, defaultProps({ isOwn: true, onDelete }));
		await userEvent.click(page.getByRole('button'));
		expect(onDelete).toHaveBeenCalled();
	});

	it('shows edit textarea when isEditing is true', async () => {
		render(
			CommentMessage,
			defaultProps({ isOwn: true, isEditing: true, editText: 'current edit text' })
		);
		const textarea = page.getByRole('textbox');
		await expect.element(textarea).toBeInTheDocument();
		await expect.element(textarea).toHaveValue('current edit text');
	});

	it('exposes id="comment-{message.id}" on the article wrapper for deep-link scroll', async () => {
		render(CommentMessage, defaultProps());
		const article = page.getByRole('article').element();
		expect(article.getAttribute('id')).toBe('comment-msg-1');
	});

	it('is focusable but not in tab order (tabindex="-1")', async () => {
		render(CommentMessage, defaultProps());
		const article = page.getByRole('article').element();
		expect(article.getAttribute('tabindex')).toBe('-1');
	});

	it('shows a focus-visible ring when focused via keyboard', async () => {
		render(CommentMessage, defaultProps());
		const article = page.getByRole('article').element();
		const classes = article.className;
		expect(classes).toMatch(/focus-visible:ring-2/);
		expect(classes).toMatch(/focus-visible:ring-brand-navy/);
		expect(classes).toMatch(/outline-none/);
	});
});
