<script lang="ts">
	/**
	 * Free-text chip input. Bind a string[] of values; commit a new chip on
	 * Enter, comma, or blur. Backspace on empty input deletes the last chip
	 * for parity with native chip-input UX.
	 *
	 * Used by ProviderDescriptor.userFilters with inputMode === 'tags' for
	 * free-text filter keys like Home Assistant's entity_glob and
	 * domain_allowlist. Distinct from MultiEntitySelect, which renders a
	 * picker dropdown sourced from an enumerable list.
	 */
	import MdiIcon from './MdiIcon.svelte';

	interface Props {
		values: string[];
		onchange: (values: string[]) => void;
		placeholder?: string;
		icon?: string;
		/** Strip / reject anything matching this regex on each entry. */
		sanitize?: (raw: string) => string | null;
	}

	let { values, onchange, placeholder = '', icon, sanitize }: Props = $props();

	let draft = $state('');

	function addRaw(raw: string): void {
		const trimmed = raw.trim();
		if (!trimmed) return;
		const cleaned = sanitize ? sanitize(trimmed) : trimmed;
		if (!cleaned) return;
		if (values.includes(cleaned)) return;
		onchange([...values, cleaned]);
	}

	function commitDraft(): void {
		if (!draft.trim()) return;
		// Allow comma-separated paste — split on commas and add each.
		for (const piece of draft.split(',')) {
			addRaw(piece);
		}
		draft = '';
	}

	function removeAt(index: number): void {
		onchange(values.filter((_, i) => i !== index));
	}

	function onKey(e: KeyboardEvent): void {
		if (e.key === 'Enter' || e.key === ',') {
			e.preventDefault();
			commitDraft();
		} else if (e.key === 'Backspace' && draft === '' && values.length > 0) {
			e.preventDefault();
			removeAt(values.length - 1);
		}
	}
</script>

<div class="tag-input">
	{#each values as value, i (`${i}-${value}`)}
		<span class="tag-chip">
			{#if icon}<MdiIcon name={icon} size={12} />{/if}
			<span class="tag-text">{value}</span>
			<button
				type="button"
				aria-label="Remove"
				class="tag-remove"
				onclick={() => removeAt(i)}
			>×</button>
		</span>
	{/each}
	<input
		type="text"
		bind:value={draft}
		onkeydown={onKey}
		onblur={commitDraft}
		placeholder={values.length === 0 ? placeholder : ''}
		class="tag-draft"
		autocomplete="off"
		spellcheck="false"
	/>
</div>

<style>
	.tag-input {
		display: flex;
		flex-wrap: wrap;
		align-items: center;
		gap: 0.375rem;
		padding: 0.375rem 0.5rem;
		min-height: 2.5rem;
		border: 1px solid var(--color-border);
		border-radius: 0.375rem;
		background: var(--color-background);
		cursor: text;
	}

	.tag-input:focus-within {
		border-color: var(--color-primary);
	}

	.tag-chip {
		display: inline-flex;
		align-items: center;
		gap: 0.25rem;
		padding: 0.1875rem 0.5rem;
		background: var(--color-muted);
		border-radius: 9999px;
		font-size: 0.75rem;
		line-height: 1;
		color: var(--color-foreground);
	}

	.tag-text {
		font-family: var(--font-mono, monospace);
	}

	.tag-remove {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		width: 1rem;
		height: 1rem;
		padding: 0;
		font-size: 0.875rem;
		line-height: 1;
		background: transparent;
		border: none;
		color: var(--color-muted-foreground);
		cursor: pointer;
		border-radius: 9999px;
	}

	.tag-remove:hover {
		background: var(--color-border);
		color: var(--color-foreground);
	}

	.tag-draft {
		flex: 1;
		min-width: 8rem;
		border: none;
		outline: none;
		background: transparent;
		font-size: 0.875rem;
		color: var(--color-foreground);
		padding: 0.125rem 0;
	}

	.tag-draft::placeholder {
		color: var(--color-muted-foreground);
	}
</style>
