<script lang="ts">
	interface Props {
		/** Display name — used to generate initials and background colour. */
		name: string;
		/** Avatar type. Defaults to initials. */
		type?: 'initials' | 'emoji' | 'upload';
		/** Emoji character when type = 'emoji'. */
		emoji?: string | null;
		/** Image URL when type = 'upload'. */
		src?: string | null;
		/** Diameter in px. */
		size?: number;
	}

	let { name, type = 'initials', emoji = null, src = null, size = 36 }: Props = $props();

	let imgError = $state(false);

	// Two initials from display name
	const initials = $derived(
		name
			.split(/\s+/)
			.slice(0, 2)
			.map((w) => w[0]?.toUpperCase() ?? '')
			.join('')
	);

	// Deterministic background colour from name (one of 8 slate-adjacent tones)
	const COLOURS = [
		'bg-slate-400',
		'bg-blue-400',
		'bg-violet-400',
		'bg-emerald-400',
		'bg-amber-400',
		'bg-rose-400',
		'bg-cyan-400',
		'bg-pink-400'
	];
	const colourClass = $derived(
		COLOURS[
			name.split('').reduce((acc, ch) => acc + ch.charCodeAt(0), 0) % COLOURS.length
		]
	);

	const fontSize = $derived(Math.round(size * 0.38));
</script>

<div
	class="flex flex-shrink-0 items-center justify-center overflow-hidden rounded-full"
	style="width: {size}px; height: {size}px;"
>
	{#if type === 'upload' && src && !imgError}
		<img
			{src}
			alt={name}
			class="h-full w-full object-cover"
			onerror={() => (imgError = true)}
		/>
	{:else if type === 'emoji' && emoji}
		<span
			class="flex h-full w-full items-center justify-center bg-slate-100 dark:bg-slate-700"
			style="font-size: {fontSize * 1.4}px;"
		>
			{emoji}
		</span>
	{:else}
		<!-- Initials fallback (also used when upload fails) -->
		<span
			class="flex h-full w-full items-center justify-center font-semibold text-white {colourClass}"
			style="font-size: {fontSize}px;"
		>
			{initials || '?'}
		</span>
	{/if}
</div>
