<script lang="ts" module>
	import type { Snippet } from 'svelte';

	export type SelectFieldOption = {
		value: string;
		label: string;
	};

	export type SelectFieldProps = {
		id: string;
		label: string;
		options: SelectFieldOption[];
		value?: string | string[];
		type?: 'single' | 'multiple';
		triggerLabel: string;
		containerClass?: string;
		triggerClass?: string;
		contentClass?: string;
		showLabel?: boolean;
		separatorAfterValue?: string;
		onValueChange?: ((value: string) => void) | ((value: string[]) => void);
		item?: Snippet<[SelectFieldOption]>;
	};
</script>

<script lang="ts">
	import * as Select from '$lib/components/ui/select';

	let {
		id,
		label,
		options,
		value = $bindable(),
		type = 'single',
		triggerLabel,
		containerClass = 'min-w-0 space-y-2',
		triggerClass = 'w-full',
		contentClass,
		showLabel = true,
		separatorAfterValue,
		onValueChange,
		item
	}: SelectFieldProps = $props();

	function getSingleValue() {
		return typeof value === 'string' ? value : undefined;
	}

	function setSingleValue(nextValue: string | undefined) {
		if (nextValue === undefined) return;
		value = nextValue;
		(onValueChange as ((value: string) => void) | undefined)?.(nextValue);
	}

	function getMultipleValue() {
		return Array.isArray(value) ? value : undefined;
	}

	function setMultipleValue(nextValue: string[] | undefined) {
		if (nextValue === undefined) return;
		value = nextValue;
		(onValueChange as ((value: string[]) => void) | undefined)?.(nextValue);
	}
</script>

<div class={containerClass}>
	{#if showLabel}
		<span {id} class="block text-xs font-semibold tracking-wider text-muted-foreground uppercase">
			{label}
		</span>
	{/if}
	{#if type === 'multiple'}
		<Select.Root type="multiple" bind:value={getMultipleValue, setMultipleValue} items={options}>
			<Select.Trigger aria-labelledby={id} class={triggerClass}>
				<span data-slot="select-value">{triggerLabel}</span>
			</Select.Trigger>
			<Select.Content preventScroll={false} class={contentClass}>
				<Select.Group>
					{#each options as option (option.value)}
						{#if item}
							<Select.Item value={option.value} label={option.label}>
								{@render item(option)}
							</Select.Item>
						{:else}
							<Select.Item value={option.value} label={option.label} />
						{/if}
						{#if option.value === separatorAfterValue}
							<Select.Separator />
						{/if}
					{/each}
				</Select.Group>
			</Select.Content>
		</Select.Root>
	{:else}
		<Select.Root type="single" bind:value={getSingleValue, setSingleValue} items={options}>
			<Select.Trigger aria-labelledby={id} class={triggerClass}>
				<span data-slot="select-value">{triggerLabel}</span>
			</Select.Trigger>
			<Select.Content preventScroll={false} class={contentClass}>
				<Select.Group>
					{#each options as option (option.value)}
						{#if item}
							<Select.Item value={option.value} label={option.label}>
								{@render item(option)}
							</Select.Item>
						{:else}
							<Select.Item value={option.value} label={option.label} />
						{/if}
						{#if option.value === separatorAfterValue}
							<Select.Separator />
						{/if}
					{/each}
				</Select.Group>
			</Select.Content>
		</Select.Root>
	{/if}
</div>
