<script lang="ts">
	import { getMdiPath, getAllMdiNames } from '$lib/mdi-lookup.svelte';
	import { portal } from '$lib/portal';

	let { value = '', onselect } = $props<{
		value: string;
		onselect: (icon: string) => void;
	}>();

	let open = $state(false);
	let search = $state('');
	let buttonEl: HTMLButtonElement;
	let dropdownStyle = $state('');

	const popular = [
		'mdiServer', 'mdiCamera', 'mdiImage', 'mdiVideo', 'mdiBell', 'mdiSend',
		'mdiRobot', 'mdiHome', 'mdiStar', 'mdiHeart', 'mdiAccount', 'mdiFolder',
		'mdiFolderImage', 'mdiAlbum', 'mdiImageMultiple', 'mdiCloudUpload',
		'mdiEye', 'mdiCog', 'mdiTelegram', 'mdiWebhook', 'mdiMessageText',
		'mdiCalendar', 'mdiClock', 'mdiMapMarker', 'mdiTag', 'mdiFilter',
		'mdiSort', 'mdiMagnify', 'mdiPencil', 'mdiDelete', 'mdiPlus',
		'mdiCheck', 'mdiClose', 'mdiAlert', 'mdiInformation', 'mdiShield',
		'mdiLink', 'mdiDownload', 'mdiUpload', 'mdiRefresh', 'mdiPlay',
		'mdiPause', 'mdiStop', 'mdiSkipNext', 'mdiMusic', 'mdiMovie',
		'mdiFileDocument', 'mdiEmail', 'mdiPhone', 'mdiChat', 'mdiShare',
	];

	const filtered = $derived.by(() => {
		const allIcons = getAllMdiNames();
		if (!search) return popular.filter(p => allIcons.includes(p));
		const q = search.toLowerCase();
		return allIcons.filter(k => k.toLowerCase().includes(q)).slice(0, 60);
	});

	function toggleOpen() {
		if (!open && buttonEl) {
			const rect = buttonEl.getBoundingClientRect();
			const popupWidth = 320; // 20rem
			const popupHeight = 320;
			const spaceBelow = window.innerHeight - rect.bottom;
			const top = spaceBelow > popupHeight + 16
				? rect.bottom + 4
				: Math.max(8, rect.top - popupHeight - 4);
			const left = Math.min(rect.left, window.innerWidth - popupWidth - 16);
			dropdownStyle = `position:fixed; z-index:9999; top:${top}px; left:${Math.max(8, left)}px;`;
		}
		open = !open;
		if (!open) search = '';
	}

	function select(iconName: string) {
		onselect(iconName);
		open = false;
		search = '';
	}

	function handleKeydown(e: KeyboardEvent) {
		if (e.key === 'Escape' && open) {
			open = false;
			search = '';
		}
	}
</script>

<svelte:window onkeydown={open ? handleKeydown : undefined} />

<div class="inline-block">
	<button type="button" bind:this={buttonEl} onclick={toggleOpen}
		class="icon-picker-trigger">
		{#if value && getMdiPath(value)}
			<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d={getMdiPath(value)} /></svg>
		{:else}
			<span class="icon-picker-placeholder">Icon</span>
		{/if}
		<span class="icon-picker-caret">▾</span>
	</button>
</div>

{#if open}
	<!-- Portal popup so it escapes any backdrop-filter / transform ancestor
	     that would otherwise act as the containing block for position:fixed. -->
	<div use:portal class="ip-portal-root">
		<div class="ip-backdrop"
			role="presentation"
			onclick={() => { open = false; search = ''; }}></div>

		<div style={dropdownStyle} class="ip-popup">
			<input type="text" bind:value={search} placeholder="Search icons..."
				class="ip-search" autocomplete="off" />
			<div class="ip-grid">
				<button type="button" onclick={() => select('')}
					class="ip-cell ip-cell--clear"
					title="No icon">✕</button>
				{#each filtered as iconName}
					<button type="button" onclick={() => select(iconName)}
						class="ip-cell {value === iconName ? 'is-active' : ''}"
						title={iconName.replace('mdi', '')}>
						<svg viewBox="0 0 24 24" width="18" height="18" fill="currentColor"><path d={getMdiPath(iconName)} /></svg>
					</button>
				{/each}
			</div>
		</div>
	</div>
{/if}

<style>
	.icon-picker-trigger {
		display: inline-flex;
		align-items: center;
		gap: 0.35rem;
		padding: 0.45rem 0.7rem;
		border-radius: 0.625rem;
		border: 1px solid var(--color-border);
		background: var(--color-input-bg);
		color: var(--color-foreground);
		font-size: 0.85rem;
		font-family: inherit;
		cursor: pointer;
		transition: all 0.15s;
	}
	.icon-picker-trigger:hover {
		background: var(--color-glass-strong);
		border-color: var(--color-rule-strong);
	}
	.icon-picker-placeholder {
		color: var(--color-muted-foreground);
		font-size: 0.78rem;
	}
	.icon-picker-caret {
		color: var(--color-muted-foreground);
		font-size: 0.7rem;
	}

	/* Portal root — drains the popup out of any backdrop-filter ancestor */
	.ip-portal-root {
		position: fixed;
		inset: 0;
		z-index: 9998;
		pointer-events: none;
	}
	.ip-backdrop {
		position: absolute;
		inset: 0;
		pointer-events: auto;
	}
	.ip-popup {
		pointer-events: auto;
		width: 20rem;
		--ip-solid-bg: #131520;
		background: var(--ip-solid-bg);
		border: 1px solid var(--color-rule-strong);
		border-radius: 14px;
		box-shadow: var(--shadow-card), 0 24px 48px -16px rgba(0, 0, 0, 0.55);
		padding: 0.65rem;
		position: relative;
	}
	:global([data-theme="light"]) .ip-popup { --ip-solid-bg: #fafafe; }
	.ip-popup::after {
		content: '';
		position: absolute; inset: 0;
		border-radius: inherit;
		pointer-events: none;
		background: linear-gradient(180deg, var(--color-highlight), transparent 30%);
		opacity: 0.4;
	}
	.ip-search {
		width: 100%;
		padding: 0.45rem 0.6rem;
		margin-bottom: 0.5rem;
		border: 1px solid var(--color-border);
		border-radius: 8px;
		background: var(--color-glass-strong);
		color: var(--color-foreground);
		font-size: 0.82rem;
		outline: none;
		font-family: inherit;
		position: relative;
		z-index: 1;
	}
	.ip-search:focus {
		border-color: var(--color-primary);
		box-shadow: 0 0 0 2px var(--color-glow);
	}
	.ip-grid {
		display: grid;
		grid-template-columns: repeat(8, 1fr);
		gap: 0.25rem;
		max-height: 14rem;
		overflow-y: auto;
		overflow-x: hidden;
		scrollbar-width: thin;
		position: relative;
		z-index: 1;
	}
	.ip-cell {
		display: flex;
		align-items: center;
		justify-content: center;
		aspect-ratio: 1;
		border-radius: 8px;
		border: 1px solid transparent;
		background: transparent;
		color: var(--color-foreground);
		cursor: pointer;
		transition: all 0.15s;
	}
	.ip-cell:hover {
		background: var(--color-glass-strong);
		border-color: var(--color-border);
	}
	.ip-cell.is-active {
		background: linear-gradient(135deg,
			color-mix(in srgb, var(--color-primary) 18%, transparent),
			color-mix(in srgb, var(--color-orchid) 18%, transparent));
		border-color: var(--color-primary);
		color: var(--color-primary);
		box-shadow: inset 0 1px 0 var(--color-highlight);
	}
	.ip-cell--clear {
		color: var(--color-muted-foreground);
		font-size: 0.75rem;
	}
</style>
