<script lang="ts" module>
	export type CheckboxState = 'indeterminate' | boolean | undefined;
</script>

<script lang="ts">
	import type { Snippet } from 'svelte';
	import { validate } from '@svelte-toolkit/validate';
	import { generateIdentifier } from './util';
	import type { ClassValue } from 'svelte/elements';

	interface Props {
		name?: string;
		required?: boolean;
		value?: CheckboxState;
		color?: 'default' | 'contrast';
		class?: ClassValue | null | undefined;
		children?: Snippet;
		onchange?: (value: CheckboxState) => void;
	}

	let {
		name,
		required = false,
		value = $bindable(),
		color = 'contrast',
		class: classValue,
		children,
		onchange
	}: Props = $props();

	let id = $derived(generateIdentifier('checkbox', name));

	let valid = $state(true);
</script>

<div class={['flex items-center', classValue]}>
	<input
		type="hidden"
		{name}
		value={value?.toString() ?? 'false'}
		use:validate={{
			valfunc: () => {
				if (required && value !== true) {
					return false;
				}
				return true;
			}
		}}
		onvalidate={(e) => {
			valid = e.detail.valid;
		}}
	/>

	<button
		{id}
		class={[
			'text-sui-text flex size-7 appearance-none items-center',
			'justify-center rounded-lg shadow transition-all hover:opacity-75',
			color === 'default' && 'bg-white',
			color === 'contrast' && 'border-text/40 border bg-white',
			!valid && 'border-sui-accent-400 border'
		]}
		onclick={() => {
			if (value === false || value === 'indeterminate') {
				value = true;
			} else {
				value = false;
			}
			onchange?.(value);
		}}
	>
		{#if value === 'indeterminate'}
			<span class="material-symbols-outlined">remove</span>
		{:else if value === true}
			<span class="material-symbols-outlined">check</span>
		{/if}
	</button>

	{#if children}
		<label
			class={[
				'text-sui-text pl-4 font-medium transition-colors select-none',
				!valid && 'text-sui-accent-400'
			]}
			for={id}
		>
			{@render children()}
			{#if required}
				<span class="text-sui-accent-400">*</span>
			{/if}
		</label>
	{/if}
</div>
