<script lang="ts" module>
	// Per-instance id counter so two ConfirmSheets coexisting (e.g. one closing
	// as another opens) don't share the same aria-labelledby target and confuse AT.
	let nextId = 0;
</script>

<script lang="ts">
	import { focusTrap } from '$lib/actions/focus-trap';

	interface Props {
		open: boolean;
		title: string;
		message?: string;
		confirmLabel?: string;
		cancelLabel?: string;
		tone?: 'default' | 'danger';
		onConfirm: () => void | Promise<void>;
		onCancel: () => void;
	}

	let {
		open,
		title,
		message,
		confirmLabel = 'Bestätigen',
		cancelLabel = 'Abbrechen',
		tone = 'default',
		onConfirm,
		onCancel
	}: Props = $props();

	const titleId = `confirm-sheet-title-${++nextId}`;
	let busy = $state(false);

	async function handleConfirm() {
		if (busy) return;
		busy = true;
		try {
			await onConfirm();
		} finally {
			busy = false;
		}
	}
</script>

{#if open}
	<!-- Backdrop is a real <button> so keyboard / switch-control users get parity with the mouse path. -->
	<button
		type="button"
		class="fixed inset-0 z-50 bg-black/40"
		aria-label="Schließen"
		onclick={onCancel}
		tabindex="-1"
	></button>
	<div
		class="fixed inset-x-0 bottom-0 z-50 rounded-t-2xl bg-white px-5 pb-10 pt-6 dark:bg-gray-900"
		style="padding-bottom: calc(env(safe-area-inset-bottom) + 1.5rem)"
		role="dialog"
		aria-modal="true"
		aria-labelledby={titleId}
		data-testid="confirm-sheet"
		use:focusTrap={{ onclose: onCancel }}
	>
		<div class="mb-4 flex justify-center">
			<div class="h-1 w-10 rounded-full bg-gray-300 dark:bg-gray-600"></div>
		</div>
		<h3 id={titleId} class="mb-1 text-center text-lg font-bold text-gray-900 dark:text-gray-100">
			{title}
		</h3>
		{#if message}
			<p class="mb-6 text-center text-sm text-gray-500 dark:text-gray-400">{message}</p>
		{:else}
			<div class="mb-4"></div>
		{/if}
		<button
			type="button"
			onclick={handleConfirm}
			disabled={busy}
			data-testid="confirm-sheet-confirm"
			class="mb-3 w-full rounded-xl py-3 text-sm font-semibold text-white transition disabled:opacity-60 {tone === 'danger'
				? 'bg-red-600 hover:bg-red-700 active:bg-red-700 dark:bg-red-500 dark:hover:bg-red-400 dark:active:bg-red-400'
				: 'bg-blue-600 hover:bg-blue-700 active:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-400 dark:active:bg-blue-400'}"
		>
			{confirmLabel}
		</button>
		<button
			type="button"
			onclick={onCancel}
			data-testid="confirm-sheet-cancel"
			class="w-full rounded-xl border border-gray-200 py-3 text-sm font-medium text-gray-700 transition hover:bg-gray-50 active:bg-gray-100 dark:border-gray-700 dark:text-gray-300 dark:hover:bg-gray-800 dark:active:bg-gray-800"
		>
			{cancelLabel}
		</button>
	</div>
{/if}
