<script lang="ts">
	import type { PreviewChunk } from '$lib/types';
	import * as ToggleGroup from '$lib/components/ui/toggle-group';
	import { Switch } from '$lib/components/ui/switch';
	import { Label } from '$lib/components/ui/label';
	import { cn } from '$lib/utils';
	import SkullIcon from 'phosphor-svelte/lib/SkullIcon';
	import ShieldIcon from 'phosphor-svelte/lib/ShieldIcon';
	import SwordIcon from 'phosphor-svelte/lib/SwordIcon';
	import { formatDuration } from '$lib/utils/format';
	import { playerColor } from '$lib/utils/player-colors';

	interface Props {
		previews: PreviewChunk[];
		currentPlayer: number;
		preloadedPlayers: Set<number>;
		availablePlayers: Set<number>;
		playerDurations: Map<number, number>;
		preloadAll: boolean;
		onSelect: (player: number) => void;
		onPreloadAllChange: (enabled: boolean) => void;
	}
	let {
		previews,
		currentPlayer,
		preloadedPlayers,
		availablePlayers,
		playerDurations,
		preloadAll,
		onSelect,
		onPreloadAllChange
	}: Props = $props();

	type PlayerSummary = {
		player: number;
		side: 'CT' | 'T' | string;
		weapon: string;
		survived: boolean;
		duration: number;
	};

	const players = $derived.by<PlayerSummary[]>(() => {
		const map = new Map<number, PreviewChunk[]>();
		for (const p of previews) {
			if (!map.has(p.player)) map.set(p.player, []);
			map.get(p.player)!.push(p);
		}
		const out: PlayerSummary[] = [];
		for (const [player, chunks] of map.entries()) {
			chunks.sort((a, b) => a.chunk_index - b.chunk_index);
			const last = chunks[chunks.length - 1];
			out.push({
				player,
				side: last.player_side,
				weapon: last.primary_weapon,
				survived: last.survived_chunk,
				duration: playerDurations.get(player) ?? 0
			});
		}
		out.sort((a, b) => a.player - b.player);
		return out;
	});

	const ctPlayers = $derived(players.filter((p) => p.side === 'CT'));
	const tPlayers = $derived(players.filter((p) => p.side === 'T'));
</script>

{#snippet playerItem(p: PlayerSummary)}
	{@const ct = p.side === 'CT'}
	{@const ready = preloadedPlayers.has(p.player)}
	{@const available = availablePlayers.has(p.player)}
	<ToggleGroup.Item
		data-ready={available && ready ? true : undefined}
		data-side={ct ? 'ct' : 't'}
		value={String(p.player)}
		aria-label="Player {p.player} ({p.weapon || 'no weapon'})"
		title={available
			? `Player ${p.player} — ${p.weapon || 'no weapon'}`
			: `Player ${p.player} died at ${formatDuration(p.duration)} — not available at current time`}
		disabled={!available}
		class={cn(
			'group flex h-auto min-w-0 flex-1 basis-0 items-center justify-start gap-2 rounded-md border px-2 py-1.5 text-left text-sm transition',
			'disabled:cursor-not-allowed disabled:opacity-40 data-[state=on]:border-current data-[state=on]:bg-accent data-[state=on]:text-accent-foreground',
			'data-[side=ct]:data-[state=on]:border-sky-500 data-[side=ct]:data-[state=on]:bg-sky-500/10 data-[side=ct]:data-[state=on]:text-foreground',
			'data-[side=t]:data-[state=on]:border-amber-500 data-[side=t]:data-[state=on]:bg-amber-500/10 data-[side=t]:data-[state=on]:text-foreground',
			'data-[ready=true]:ring-2 data-[ready=true]:ring-emerald-500/60 data-[ready=true]:ring-offset-1 data-[ready=true]:ring-offset-background'
		)}
	>
		<span
			class="flex size-7 shrink-0 items-center justify-center rounded-sm font-mono text-xs font-bold text-white/95 shadow-sm ring-1 ring-black/20"
			style="background-color: {playerColor(p.player)};"
		>
			{p.player}
		</span>
		<div class="min-w-0 flex-1">
			<div class="truncate font-medium">Player {p.player}</div>
			{#if !available}
				<div class="text-[10px] text-muted-foreground tabular-nums">
					died · {formatDuration(p.duration)}
				</div>
			{/if}
		</div>
		{#if p.survived}
			<ShieldIcon size={14} weight="duotone" class="text-emerald-500" />
		{:else if !available}
			<SkullIcon size={14} weight="duotone" class="text-rose-500" />
		{/if}
	</ToggleGroup.Item>
{/snippet}

<div class="space-y-2">
	<div class="flex items-center justify-between gap-3">
		<div class="text-xs tracking-wide text-muted-foreground uppercase">Player perspectives</div>
		<div class="flex items-center gap-2">
			<Label
				for="preload-all-players"
				class="text-[11px] tracking-wide text-muted-foreground uppercase"
			>
				Preload all
			</Label>
			<Switch
				id="preload-all-players"
				size="sm"
				checked={preloadAll}
				onCheckedChange={(v) => onPreloadAllChange(!!v)}
			/>
		</div>
	</div>

	<ToggleGroup.Root
		type="single"
		value={String(currentPlayer)}
		onValueChange={(v) => v && onSelect(Number(v))}
		variant="outline"
		spacing={1}
		aria-label="Player perspective"
		class="w-full! flex-col gap-2"
	>
		<div class="w-full">
			<div
				class="mb-1 flex items-center gap-1.5 text-[10px] font-semibold tracking-wide text-sky-700 uppercase dark:text-sky-400"
			>
				<ShieldIcon size={11} weight="duotone" /> Counter-Terrorists
			</div>
			<div class="flex w-full items-stretch gap-1.5">
				{#each ctPlayers as p (p.player)}
					{@render playerItem(p)}
				{/each}
			</div>
		</div>

		<div class="w-full">
			<div
				class="mb-1 flex items-center gap-1.5 text-[10px] font-semibold tracking-wide text-amber-700 uppercase dark:text-amber-400"
			>
				<SwordIcon size={11} weight="duotone" /> Terrorists
			</div>
			<div class="flex w-full items-stretch gap-1.5">
				{#each tPlayers as p (p.player)}
					{@render playerItem(p)}
				{/each}
			</div>
		</div>
	</ToggleGroup.Root>
</div>
