<script lang="ts">
	import { Select as SelectPrimitive } from 'bits-ui';
	import { writable } from 'svelte/store';
	import { setContext } from 'svelte';
	import { selectSearchContextKey, type SelectSearchContext } from './select-search-context';
	import { type WithoutChild } from '$lib/utils.js';

	// SelectPrimitive.RootProps is a discriminated union (single | multiple).
	// Spreading a discriminated union collapses conflicting members (e.g. onValueChange) to `never`.
	// We widen the props type so callers can pass either variant without hitting `never`.
	// eslint-disable-next-line @typescript-eslint/no-explicit-any
	type SelectRootProps = Omit<WithoutChild<SelectPrimitive.RootProps>, 'value' | 'onValueChange'> & {
		type?: 'single' | 'multiple';
		value?: string | string[];
		onValueChange?: (value: any) => void;
	};

	let {
		children,
		value = $bindable(),
		type = 'single',
		onValueChange,
		...restProps
	}: SelectRootProps = $props();

	let open = $state(false);
	const query = writable('');
	const openStore = writable(false);
	const triggerRef = writable<HTMLElement | null>(null);
	const selectedValue = writable<string | string[] | undefined>(undefined);
	const selectionType = writable<'single' | 'multiple'>('single');

	function clearValue() {
		if ((type ?? 'single') === 'multiple') {
			value = [] as any;
			onValueChange?.([]);
		} else {
			value = '' as any;
			onValueChange?.('');
		}
	}

	const context: SelectSearchContext = {
		query,
		open: openStore,
		triggerRef,
		setOpen: (next) => {
			open = next;
		},
		selectedValue,
		selectionType,
		clearValue
	};

	setContext(selectSearchContextKey, context);

	$effect(() => {
		openStore.set(open);
		if (!open) {
			query.set('');
		}
	});

	$effect(() => {
		selectedValue.set(value);
		selectionType.set((type ?? 'single') as 'single' | 'multiple');
	});
</script>

<SelectPrimitive.Root
	bind:open
	bind:value={value as any}
	type={type as any}
	onValueChange={onValueChange}
	{...restProps}
>
	{@render children?.()}
</SelectPrimitive.Root>
