<script lang="ts">
    import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList } from "@components/ui/command";
    import { Popover, PopoverContent, PopoverTrigger } from "@components/ui/popover";
    import { Button } from "@components/ui/button";
    import { Check, ChevronsUpDown } from "lucide-svelte";
    import { cn } from "@components/utils";
    import { dataRepo } from "@repo/data";
    import type { Player } from "@type/data";

    let {
        value = $bindable(null),
        multiple = false,
        placeholder = "Select player...",
        onSelect,
    }: {
        value?: number | number[] | null;
        multiple?: boolean;
        placeholder?: string;
        onSelect?: (player: Player) => void;
    } = $props();

    let open = $state(false);
    let search = $state("");
    let players: Player[] = $state([]);
    let loading = $state(false);

    let debounceTimer: NodeJS.Timeout;

    function fetchPlayers(searchTerm: string) {
        clearTimeout(debounceTimer);
        debounceTimer = setTimeout(async () => {
            loading = true;
            try {
                const res = await $dataRepo.queryPlayers(searchTerm || undefined, undefined, undefined, 50, 0, false, true);
                players = res.entries;
            } finally {
                loading = false;
            }
        }, 300);
    }

    $effect(() => {
        fetchPlayers(search);
    });

    function handleSelect(player: Player) {
        if (onSelect) {
            onSelect(player);
        }

        if (multiple) {
            if (Array.isArray(value)) {
                if (value.includes(player.id!)) {
                    value = value.filter((v) => v !== player.id);
                } else {
                    value = [...value, player.id!];
                }
            } else {
                value = [player.id!];
            }
        } else {
            if (value === player.id) {
                value = null; // Deselect
            } else {
                value = player.id;
                open = false;
            }
        }
    }

    function isSelected(id: number) {
        if (multiple) {
            return Array.isArray(value) && value.includes(id);
        }
        return value === id;
    }

    let triggerLabel = $derived.by(() => {
        if (multiple) {
            if (Array.isArray(value) && value.length > 0) {
                return `${placeholder} (${value.length})`;
            }
            return placeholder;
        } else {
            // We might need to fetch the selected player's name if it's not in the current list
            // For now, let's just show the placeholder or "Selected"
            // Ideally we would have a way to resolve the name from the UUID if it's not in `players`
            // But `players` only contains search results.
            // If we want to show the name, we might need to fetch it or pass it in.
            // Given the context of AuditLog, it shows "Spieler Filter (count)".
            // Given RefereesList, it's a button "Hinzufügen".
            return placeholder;
        }
    });
</script>

<Popover bind:open>
    <PopoverTrigger>
        {#snippet child({ props })}
            <Button variant="outline" class={cn("justify-between", Array.isArray(value) && !value?.length && "text-muted-foreground")} {...props} role="combobox" aria-expanded={open}>
                {triggerLabel}
                <ChevronsUpDown class="ml-2 size-4 shrink-0 opacity-50" />
            </Button>
        {/snippet}
    </PopoverTrigger>
    <PopoverContent class="p-0">
        <Command shouldFilter={false}>
            <CommandInput bind:value={search} placeholder="Search players..." />
            <CommandList>
                <CommandEmpty>No players found.</CommandEmpty>
                <CommandGroup>
                    {#each players as player (player.uuid)}
                        <CommandItem value={player.id?.toString()} onSelect={() => handleSelect(player)}>
                            <Check class={cn("mr-2 size-4", isSelected(player.id!) ? "opacity-100" : "opacity-0")} />
                            {player.name}
                        </CommandItem>
                    {/each}
                </CommandGroup>
            </CommandList>
        </Command>
    </PopoverContent>
</Popover>
