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

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

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

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

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

	let valid = $state(true);
	let Icon = $derived(
		resolveGetter(value) === 'indeterminate' ? Minus : resolveGetter(value) ? Check : undefined
	);
</script>

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

	<button
		type="button"
		{id}
		{disabled}
		class={[
			'text-sui-text flex size-7 shrink-0 appearance-none items-center',
			'justify-center rounded-lg shadow transition-all',
			color === 'default' && 'bg-white',
			color === 'contrast' && 'border-text/40 border bg-white',
			!valid && 'border border-red-500',
			disabled ? 'cursor-not-allowed opacity-50' : 'hover:opacity-75'
		]}
		onclick={() => {
			const resolved = resolveGetter(value);
			if (resolved === false || resolved === undefined || resolved === 'indeterminate') {
				value = true;
			} else {
				value = false;
			}
			onchange?.(value);
		}}
	>
		{#if Icon}
			<Icon weight="bold" size="1.1em"></Icon>
		{/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()}
		</label>
	{/if}
</div>
