<script lang="ts">
	import { AlertCircle, AlertTriangle, ChevronDown, ChevronUp, X } from 'lucide-svelte';
	import { cn } from '$lib/utils';

	export type ErrorPanelNoticeRow = {
		field: string;
		message: string;
	};

	export type ErrorPanelNoticeVariant = 'error' | 'warning';

	export type ErrorPanelNoticeLabels = {
		clear: string;
		columnType: string;
		columnField: string;
		columnMessage: string;
		emptyField: string;
		dismissRowAria: string;
		toggleDetailsAria: string;
	};

	let {
		open,
		variant = 'error',
		title,
		rows = [],
		durationMs = 12000,
		labels,
		dismissibleRows = true,
		class: className = '',
		onClose,
		onDismissRow
	}: {
		open: boolean;
		variant?: ErrorPanelNoticeVariant;
		title: string;
		rows: ErrorPanelNoticeRow[];
		durationMs?: number;
		labels: ErrorPanelNoticeLabels;
		dismissibleRows?: boolean;
		class?: string;
		onClose?: () => void;
		onDismissRow?: (index: number) => void;
	} = $props();

	let expanded = $state(true);

	const isWarning = $derived(variant === 'warning');

	/** Re-expand the table when the panel opens or when errors/warnings change (new batch). */
	$effect(() => {
		if (!open) return;
		void title;
		void variant;
		void JSON.stringify(rows);
		expanded = true;
	});

	$effect(() => {
		if (!open || durationMs <= 0) return;
		void rows.length;
		const t = setTimeout(() => onClose?.(), durationMs);
		return () => clearTimeout(t);
	});

	function toggleExpanded() {
		expanded = !expanded;
	}
</script>

{#if open}
	<div
		data-partida-notice-layer
		role={isWarning ? 'status' : 'alert'}
		class={cn(
			// Above sonner; inset-left keeps the panel aligned with empty space in Partidas
			'pointer-events-auto fixed top-4 left-0 z-[1000000000] flex w-[min(100vw-2rem,30rem)] max-h-[min(72vh,calc(100vh-2rem))] flex-col overflow-hidden rounded-lg border bg-background text-foreground shadow-xl sm:left-1',
			isWarning ? 'border-amber-400/40' : 'border-border',
			className
		)}
	>
		<!-- Header -->
		<div
			class={cn(
				'flex shrink-0 items-center gap-2 border-b px-3 py-2.5',
				isWarning
					? 'border-amber-400/30 bg-amber-500/10 dark:bg-amber-500/15'
					: 'border-destructive/20 bg-destructive/10 dark:bg-destructive/15'
			)}
		>
			<span
				class={cn(
					'flex size-7 shrink-0 items-center justify-center rounded-full',
					isWarning
						? 'bg-amber-500 text-white'
						: 'bg-destructive text-destructive-foreground'
				)}
				aria-hidden="true"
			>
				{#if isWarning}
					<AlertTriangle class="size-4" />
				{:else}
					<AlertCircle class="size-4" />
				{/if}
			</span>
			<p class="min-w-0 flex-1 text-sm font-semibold text-foreground">{title}</p>

			<button
				type="button"
				class="inline-flex h-7 cursor-pointer items-center rounded-md px-2 text-xs text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
				onclick={() => onClose?.()}
			>
				{labels.clear}
			</button>

			<button
				type="button"
				class="inline-flex size-7 cursor-pointer items-center justify-center rounded-md text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
				onclick={toggleExpanded}
				aria-expanded={expanded}
				aria-label={labels.toggleDetailsAria}
			>
				{#if expanded}
					<ChevronUp class="size-4" />
				{:else}
					<ChevronDown class="size-4" />
				{/if}
			</button>
		</div>

		{#if expanded && rows.length > 0}
			<div class="min-h-0 flex-1 overflow-y-auto">
				<table class="w-full border-collapse text-sm">
					<thead>
						<tr class="border-b border-border bg-muted/30">
							<th
								class="w-10 px-2 py-1.5 text-center text-[10px] font-semibold tracking-widest text-muted-foreground uppercase"
							>
								{labels.columnType}
							</th>
							<th
								class="w-[38%] px-2 py-1.5 text-center text-[10px] font-semibold tracking-widest text-muted-foreground uppercase"
							>
								{labels.columnField}
							</th>
							<th
								class="px-2 py-1.5 text-left text-[10px] font-semibold tracking-widest text-muted-foreground uppercase"
							>
								{labels.columnMessage}
							</th>
							{#if dismissibleRows && onDismissRow}
								<th class="w-8"></th>
							{/if}
						</tr>
					</thead>
					<tbody>
						{#each rows as row, i (i)}
							<tr class="border-b border-border/50 hover:bg-muted/20">
								<td class="px-2 py-2.5 text-center align-middle">
									<span
										class={cn(
											'inline-flex size-5 items-center justify-center rounded-full text-[11px] font-bold leading-none',
											isWarning
												? 'bg-amber-500 text-white'
												: 'bg-destructive text-destructive-foreground'
										)}
										aria-hidden="true"
									>
										{#if isWarning}
											<AlertTriangle class="size-3" />
										{:else}
											×
										{/if}
									</span>
								</td>
								<td
									class="break-words px-2 py-2.5 align-middle text-center font-semibold text-foreground"
								>
									{row.field || labels.emptyField}
								</td>
								<td class="break-words px-2 py-2.5 align-top text-left leading-relaxed text-muted-foreground">
									{row.message}
								</td>
								{#if dismissibleRows && onDismissRow}
									<td class="px-1 py-2 text-center align-middle">
										<button
											type="button"
											class="inline-flex size-6 cursor-pointer items-center justify-center rounded text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
											onclick={() => onDismissRow!(i)}
											aria-label={labels.dismissRowAria}
										>
											<X class="size-3" />
										</button>
									</td>
								{/if}
							</tr>
						{/each}
					</tbody>
				</table>
			</div>
		{/if}
	</div>
{/if}
