<script lang="ts">
	import CheckIcon from "@lucide/svelte/icons/check";
	import { Select as SelectPrimitive } from "bits-ui";
	import { cn, type WithoutChild } from "$lib/utils.js";
	import { getContext } from "svelte";
	import { get } from "svelte/store";
	import { selectSearchContextKey, type SelectSearchContext } from "./select-search-context";

	let {
		ref = $bindable(null),
		class: className,
		value,
		label,
		searchText,
		children: childrenProp,
		...restProps
	}: WithoutChild<SelectPrimitive.ItemProps> & { searchText?: string } = $props();

	// Get search context
	const searchContext = getContext<SelectSearchContext | undefined>(selectSearchContextKey);
	let query = $state('');

	$effect(() => {
		if (!searchContext) return;
		const unsubscribe = searchContext.query.subscribe((value) => {
			query = value;
		});
		return unsubscribe;
	});
	
	// Determine if item should be visible based on search
	const isVisible = $derived(() => {
		if (!searchContext) return true;
		const normalizedQuery = query.toLowerCase();
		if (!normalizedQuery) return true;
		
		const itemLabel = (searchText || label || value || '').toString().toLowerCase();
		return itemLabel.includes(normalizedQuery);
	});

	function isSameAsSelected(): boolean {
		if (!searchContext) return false;
		if (get(searchContext.selectionType) !== 'single') return false;
		const current = get(searchContext.selectedValue);
		if (Array.isArray(current)) return false;
		return String(value ?? '') === String(current ?? '');
	}

	function handlePointerDownCapture(e: PointerEvent) {
		if (!isSameAsSelected()) return;
		e.preventDefault();
		e.stopImmediatePropagation();
		searchContext?.clearValue();
		searchContext?.setOpen(false);
	}

	function handleKeyDownCapture(e: KeyboardEvent) {
		if (e.key !== 'Enter' && e.key !== ' ') return;
		if (!isSameAsSelected()) return;
		e.preventDefault();
		e.stopImmediatePropagation();
		searchContext?.clearValue();
		searchContext?.setOpen(false);
	}
</script>

{#if isVisible()}
	<SelectPrimitive.Item
		bind:ref
		{value}
		data-slot="select-item"
		tabindex="0"
		onpointerdowncapture={handlePointerDownCapture}
		onkeydowncapture={handleKeyDownCapture}
		class={cn(
			"data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground outline-hidden *:[span]:last:flex *:[span]:last:items-center *:[span]:last:gap-2 relative flex w-full cursor-default select-none items-center gap-2 rounded-sm py-1.5 pl-2 pr-8 text-sm data-[disabled]:pointer-events-none data-[disabled]:opacity-50 [&_svg:not([class*='size-'])]:size-4 [&_svg]:pointer-events-none [&_svg]:shrink-0",
			"focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
			className
		)}
		{...restProps}
	>
		{#snippet children({ selected, highlighted })}
			<span class="absolute right-2 flex size-3.5 items-center justify-center">
				{#if selected}
					<CheckIcon class="size-4" />
				{/if}
			</span>
			{#if childrenProp}
				{@render childrenProp({ selected, highlighted })}
			{:else}
				{label || value}
			{/if}
		{/snippet}
	</SelectPrimitive.Item>
{/if}
