import { describe, it, expect, vi, afterEach } from 'vitest';
import { cleanup, render } from 'vitest-browser-svelte';
import { page } from 'vitest/browser';
import NameHistoryEditCard from './NameHistoryEditCard.svelte';
import { createConfirmService, CONFIRM_KEY } from '$lib/shared/services/confirm.svelte.js';

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

afterEach(cleanup);

const aliases = [
	{ id: 'a1', lastName: 'Müller', firstName: 'Anna', type: 'BIRTH', sortOrder: 0 },
	{ id: 'a2', lastName: 'Schmidt', firstName: null, type: 'MARRIED', sortOrder: 1 }
];

function renderCard(overrides: Record<string, unknown> = {}) {
	const service = createConfirmService();
	const result = render(NameHistoryEditCard, {
		props: { aliases, canWrite: true, ...overrides },
		context: new Map([[CONFIRM_KEY, service]])
	});
	return { ...result, service };
}

// ─── Rendering ────────────────────────────────────────────────────────────────

describe('NameHistoryEditCard — rendering', () => {
	it('renders alias last names', async () => {
		renderCard();
		await expect.element(page.getByText('Müller')).toBeInTheDocument();
		await expect.element(page.getByText('Schmidt')).toBeInTheDocument();
	});

	it('renders delete buttons when canWrite', async () => {
		renderCard();
		const btns = document.querySelectorAll('button[type="button"]');
		expect(btns.length).toBeGreaterThanOrEqual(2);
	});

	it('does not render delete buttons when canWrite is false', async () => {
		renderCard({ canWrite: false });
		const btns = document.querySelectorAll<HTMLButtonElement>('button[type="button"]');
		expect(btns.length).toBe(0);
	});

	it('does not show the inline delete modal (replaced by ConfirmService)', async () => {
		renderCard();
		// The old inline modal div with "fixed inset-0" should not exist
		const modal = document.querySelector('.fixed.inset-0');
		expect(modal).toBeNull();
	});
});

// ─── Delete confirmation ──────────────────────────────────────────────────────

describe('NameHistoryEditCard — delete confirmation', () => {
	it('opens confirm dialog when delete button is clicked', async () => {
		const { service } = renderCard();
		const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
		deleteBtn.click();
		await vi.waitFor(() => expect(service.options).not.toBeNull());
		expect(service.options?.destructive).toBe(true);
		service.settle(false);
	});

	it('submits removeAlias form when user confirms', async () => {
		const { service } = renderCard();
		const requestSubmit = vi
			.spyOn(HTMLFormElement.prototype, 'requestSubmit')
			.mockImplementation(() => {});

		const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
		deleteBtn.click();
		await vi.waitFor(() => expect(service.options).not.toBeNull());
		service.settle(true);

		// Wait for the async handleDelete callback to call requestSubmit
		await vi.waitFor(() => expect(requestSubmit).toHaveBeenCalledOnce());
		requestSubmit.mockRestore();
	});

	it('does not submit form when user cancels', async () => {
		const { service } = renderCard();
		const requestSubmit = vi
			.spyOn(HTMLFormElement.prototype, 'requestSubmit')
			.mockImplementation(() => {});

		const deleteBtn = document.querySelector<HTMLButtonElement>('button[type="button"]')!;
		deleteBtn.click();
		await vi.waitFor(() => expect(service.options).not.toBeNull());
		service.settle(false);
		await vi.waitFor(() => expect(service.options).toBeNull());

		// Allow pending microtasks to flush before asserting
		await Promise.resolve();
		expect(requestSubmit).not.toHaveBeenCalled();
		requestSubmit.mockRestore();
	});

	it('submits with the correct aliasId when second alias is deleted', async () => {
		const { service } = renderCard();
		const requestSubmit = vi
			.spyOn(HTMLFormElement.prototype, 'requestSubmit')
			.mockImplementation(() => {});

		// Click delete button for the second alias (Schmidt)
		const deleteBtns = document.querySelectorAll<HTMLButtonElement>('button[type="button"]');
		deleteBtns[1].click();
		await vi.waitFor(() => expect(service.options).not.toBeNull());
		service.settle(true);

		await vi.waitFor(() => expect(requestSubmit).toHaveBeenCalledOnce());
		const submittedForm = requestSubmit.mock.instances[0] as HTMLFormElement;
		const aliasIdInput = submittedForm.querySelector<HTMLInputElement>('input[name="aliasId"]');
		expect(aliasIdInput?.value).toBe('a2');
		requestSubmit.mockRestore();
	});
});
