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

vi.mock('$app/forms', () => ({ enhance: () => () => {} }));

beforeEach(() => {
	vi.useFakeTimers();
});

afterEach(() => {
	cleanup();
	vi.unstubAllGlobals();
	vi.useRealTimers();
});

const tag = { id: 't1', name: 'Familie', documentCount: 3 };
const allTags = [
	{ id: 't1', name: 'Familie', documentCount: 3 },
	{ id: 't2', name: 'Reise', documentCount: 1 },
	{ id: 't3', name: 'Urlaub', documentCount: 0, parentId: 't1' }
];

describe('TagMergeZone – rendering', () => {
	it('renders the merge heading', async () => {
		render(TagMergeZone, { tag, allTags, form: null });
		await expect.element(page.getByText(/Zusammenführen/i)).toBeInTheDocument();
	});

	it('renders a TagParentPicker (combobox) for target selection', async () => {
		render(TagMergeZone, { tag, allTags, form: null });
		await expect.element(page.getByRole('combobox')).toBeInTheDocument();
	});

	it('combobox has merge-specific placeholder text', async () => {
		render(TagMergeZone, { tag, allTags, form: null });
		const input = await page.getByRole('combobox').element();
		expect(input.getAttribute('placeholder')).toBe('Ziel-Schlagwort suchen …');
	});
});

describe('TagMergeZone – step flow', () => {
	it('step 2 is not shown before a target is selected', async () => {
		const { container } = render(TagMergeZone, { tag, allTags, form: null });
		expect(container.querySelector('[data-testid="merge-step2"]')).toBeFalsy();
	});

	it('shows step 2 confirm button after target is selected', async () => {
		vi.stubGlobal(
			'fetch',
			vi.fn().mockResolvedValue({
				ok: true,
				json: vi.fn().mockResolvedValue([{ id: 't2', name: 'Reise' }])
			})
		);
		render(TagMergeZone, { tag, allTags, form: null });

		const input = page.getByRole('combobox');
		await input.fill('R');
		await vi.advanceTimersByTimeAsync(300);
		await page.getByRole('option', { name: 'Reise' }).click();
		await vi.advanceTimersByTimeAsync(0);

		await expect.element(page.getByTestId('merge-step2')).toBeInTheDocument();
	});
});

describe('TagMergeZone – preview uses the direct document count (characterization, #698)', () => {
	it('shows the tag direct documentCount in the merge preview, not a subtree rollup', async () => {
		vi.stubGlobal(
			'fetch',
			vi.fn().mockResolvedValue({
				ok: true,
				json: vi.fn().mockResolvedValue([{ id: 't2', name: 'Reise' }])
			})
		);
		// documentCount (direct) = 3; a stray subtree rollup of 99 must NOT leak into the preview —
		// merge re-tags only direct documents, so the preview has to stay the direct count.
		const mergeTag = { id: 't1', name: 'Familie', documentCount: 3, subtreeDocumentCount: 99 };
		render(TagMergeZone, { tag: mergeTag, allTags, form: null });

		const input = page.getByRole('combobox');
		await input.fill('R');
		await vi.advanceTimersByTimeAsync(300);
		await page.getByRole('option', { name: 'Reise' }).click();
		await vi.advanceTimersByTimeAsync(0);

		await expect.element(page.getByTestId('merge-step2')).toBeInTheDocument();
		expect(document.body.textContent).toContain('3 Dokumente');
		expect(document.body.textContent).not.toContain('99');
	});
});

describe('TagMergeZone – stale state reset', () => {
	it('resets target selection when tag prop changes', async () => {
		vi.stubGlobal(
			'fetch',
			vi.fn().mockResolvedValue({
				ok: true,
				json: vi.fn().mockResolvedValue([{ id: 't2', name: 'Reise' }])
			})
		);
		const { rerender } = render(TagMergeZone, { tag, allTags, form: null });

		const input = page.getByRole('combobox');
		await input.fill('R');
		await vi.advanceTimersByTimeAsync(300);
		await page.getByRole('option', { name: 'Reise' }).click();
		await vi.advanceTimersByTimeAsync(0);

		await expect.element(page.getByTestId('merge-step2')).toBeInTheDocument();

		// Navigate to a different tag
		await rerender({ tag: { id: 't2', name: 'Reise', documentCount: 1 }, allTags, form: null });
		await vi.advanceTimersByTimeAsync(0);

		// step 2 should be gone — targetId was reset
		expect(document.querySelector('[data-testid="merge-step2"]')).toBeFalsy();
	});
});
