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

const mockPage = { url: new URL('http://localhost/admin/tags/t1') };

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

import { createConfirmService, CONFIRM_KEY } from '$lib/shared/services/confirm.svelte.js';

vi.mock('$app/navigation', () => ({
	beforeNavigate: () => {},
	afterNavigate: () => {},
	goto: vi.fn(),
	invalidate: vi.fn(),
	invalidateAll: vi.fn(),
	preloadCode: vi.fn(),
	preloadData: vi.fn(),
	pushState: vi.fn(),
	replaceState: vi.fn(),
	disableScrollHandling: vi.fn(),
	onNavigate: () => () => {}
}));

const { default: AdminTagEditPage } = await import('./+page.svelte');

afterEach(cleanup);

const baseTag = (overrides: Record<string, unknown> = {}) => ({
	id: 't1',
	name: 'Personen',
	color: 'sage' as string | null,
	parentId: null as string | null,
	...overrides
});

const baseData = (overrides: Record<string, unknown> = {}) => ({
	tag: baseTag(),
	tags: [baseTag(), baseTag({ id: 't2', name: 'Orte', color: 'sienna' })],
	mergeSuccess: null,
	...overrides
});

describe('admin/tags/[id] page', () => {
	it('renders the edit heading with the tag name', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: undefined }
		});

		await expect.element(page.getByRole('heading', { name: /personen/i })).toBeVisible();
	});

	it('hydrates the name input from data.tag.name', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData({ tag: baseTag({ name: 'Reisen' }) }), form: undefined }
		});

		const input = document.querySelector('input[name="name"]') as HTMLInputElement;
		expect(input.value).toBe('Reisen');
	});

	it('renders the color picker for top-level tags (no parentId)', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: undefined }
		});

		const colorPicker = document.querySelector('[data-testid="color-picker"]');
		expect(colorPicker).not.toBeNull();
	});

	it('renders one color swatch per palette entry', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: undefined }
		});

		const swatches = document.querySelectorAll('[data-testid^="color-swatch-"]');
		expect(swatches.length).toBeGreaterThanOrEqual(10);
	});

	it('marks the active color swatch as aria-pressed', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData({ tag: baseTag({ color: 'amber' }) }), form: undefined }
		});

		const amberSwatch = document.querySelector('[data-testid="color-swatch-amber"]') as HTMLElement;
		expect(amberSwatch.getAttribute('aria-pressed')).toBe('true');
	});

	it('shows the form-success banner when form.success is true', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: { success: true } }
		});

		const banners = document.querySelectorAll('.bg-green-50');
		expect(banners.length).toBeGreaterThan(0);
	});

	it('shows the form-error banner when form.error is set', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: { error: 'Tag name already in use' } }
		});

		const errors = document.querySelectorAll('.bg-red-50');
		expect(errors.length).toBeGreaterThan(0);
	});

	it('shows the merge-success banner when data.mergeSuccess is set', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData({ mergeSuccess: 'old-id' }), form: undefined }
		});

		const banners = document.querySelectorAll('[role="status"]');
		expect(banners.length).toBeGreaterThan(0);
	});

	it('hides the color picker for child tags (parentId set)', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: {
				data: baseData({ tag: baseTag({ parentId: 't-parent' }) }),
				form: undefined
			}
		});

		const colorPicker = document.querySelector('[data-testid="color-picker"]');
		expect(colorPicker).toBeNull();
	});

	it('does not show form-success banner when form is undefined', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData(), form: undefined }
		});

		const banners = document.querySelectorAll('.bg-green-50');
		// Some other green elements may exist, but the form-success specifically
		// — accept that the banner may not be present
		const formSuccessBanner = Array.from(banners).filter((b) =>
			(b.textContent ?? '').match(/gespeichert|aktualisiert|saved/i)
		);
		expect(formSuccessBanner.length).toBe(0);
	});

	it('hides the merge-success banner when mergeSuccess is null', async () => {
		render(AdminTagEditPage, {
			context: new Map([[CONFIRM_KEY, createConfirmService()]]),
			props: { data: baseData({ mergeSuccess: null }), form: undefined }
		});

		// The merge-success banner has a distinct testid; mergeSuccess=null keeps it absent.
		expect(document.querySelector('[data-testid="tag-merge-success"]')).toBeNull();
	});
});
