import { Check, ChevronDown, Loader2, Search } from "lucide-react";
import { useEffect, useRef, useState } from "react";

import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import { cn } from "@/lib/utils";

export interface SearchableCoinItem {
    symbol: string;
    name: string;
}

interface SearchableCoinSelectProps {
    value: string;
    items: SearchableCoinItem[];
    search: string;
    onSearchChange: (value: string) => void;
    onValueChange: (value: string) => void;
    loading?: boolean;
    hasMore?: boolean;
    onLoadMore?: () => void;
    error?: string | null;
    placeholder?: string;
}

export default function SearchableCoinSelect({
    value,
    items,
    search,
    onSearchChange,
    onValueChange,
    loading = false,
    hasMore = false,
    onLoadMore,
    error = null,
    placeholder = "Select coin",
}: SearchableCoinSelectProps) {
    const [open, setOpen] = useState(false);
    const rootRef = useRef<HTMLDivElement>(null);
    const triggerRef = useRef<HTMLButtonElement>(null);
    const [dropdownStyles, setDropdownStyles] = useState<{
        top: number;
        left: number;
        width: number;
    }>({ top: 0, left: 0, width: 280 });

    const selected = items.find((item) => item.symbol === value);

    // Hitung posisi secara akurat menggunakan getBoundingClientRect agar keluar dari batasan card/overflow layout
    useEffect(() => {
        if (!open || !triggerRef.current) return;

        const updatePosition = () => {
            if (!triggerRef.current) return;
            const rect = triggerRef.current.getBoundingClientRect();
            setDropdownStyles({
                top: rect.bottom + 6,
                left: rect.left,
                width: Math.max(rect.width, 300), // Minimal lebar 300px agar leluasa menampilkan nama koin
            });
        };

        updatePosition();
        window.addEventListener("resize", updatePosition);
        window.addEventListener("scroll", updatePosition, true);

        return () => {
            window.removeEventListener("resize", updatePosition);
            window.removeEventListener("scroll", updatePosition, true);
        };
    }, [open]);

    useEffect(() => {
        if (!open) return;
        const handlePointerDown = (event: MouseEvent) => {
            if (!rootRef.current?.contains(event.target as Node))
                setOpen(false);
        };
        const handleKeyDown = (event: KeyboardEvent) => {
            if (event.key === "Escape") setOpen(false);
        };
        document.addEventListener("mousedown", handlePointerDown);
        document.addEventListener("keydown", handleKeyDown);
        return () => {
            document.removeEventListener("mousedown", handlePointerDown);
            document.removeEventListener("keydown", handleKeyDown);
        };
    }, [open]);

    return (
        <div ref={rootRef} className="relative w-full">
            <Button
                ref={triggerRef}
                type="button"
                variant="outline"
                role="combobox"
                aria-expanded={open}
                onClick={() => setOpen((current) => !current)}
                className="h-10 w-full justify-between rounded-xl px-3 text-sm font-semibold"
            >
                <span className="min-w-0 truncate text-left">
                    {selected
                        ? `${selected.symbol} · ${selected.name}`
                        : placeholder}
                </span>
                <ChevronDown className="size-4 shrink-0 opacity-50" />
            </Button>

            {open && (
                <div
                    style={{
                        position: "fixed",
                        top: `${dropdownStyles.top}px`,
                        left: `${dropdownStyles.left}px`,
                        width: `${dropdownStyles.width}px`,
                    }}
                    className="z-[99999] overflow-hidden rounded-xl border border-border bg-popover text-popover-foreground shadow-2xl animate-in fade-in-0 zoom-in-95"
                >
                    <div className="border-b border-border/60 p-2 bg-popover">
                        <div className="relative">
                            <Search className="pointer-events-none absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                            <Input
                                autoFocus
                                value={search}
                                onChange={(event) =>
                                    onSearchChange(event.target.value)
                                }
                                placeholder="Search coin..."
                                className="h-9 rounded-lg pl-9"
                            />
                        </div>
                    </div>

                    <div className="max-h-72 overflow-y-auto p-1 bg-popover">
                        {items.length === 0 && !loading ? (
                            <div className="px-3 py-8 text-center text-xs text-muted-foreground">
                                {error ?? "No coins found."}
                            </div>
                        ) : (
                            items.map((item) => {
                                const active = item.symbol === value;
                                return (
                                    <button
                                        key={item.symbol}
                                        type="button"
                                        onClick={() => {
                                            onValueChange(item.symbol);
                                            setOpen(false);
                                        }}
                                        className={cn(
                                            "flex w-full items-center gap-2 rounded-lg px-3 py-2.5 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground",
                                            active && "bg-accent/70",
                                        )}
                                    >
                                        <span className="min-w-0 flex-1">
                                            <span className="block font-medium">
                                                {item.symbol}
                                            </span>
                                            <span className="block truncate text-xs text-muted-foreground">
                                                {item.name}
                                            </span>
                                        </span>
                                        {active && (
                                            <Check className="size-4 shrink-0 text-primary" />
                                        )}
                                    </button>
                                );
                            })
                        )}

                        {loading && (
                            <div className="flex items-center justify-center gap-2 px-3 py-3 text-xs text-muted-foreground">
                                <Loader2 className="size-3.5 animate-spin" />{" "}
                                Loading...
                            </div>
                        )}

                        {!loading && hasMore && (
                            <Button
                                type="button"
                                variant="ghost"
                                size="sm"
                                className="mt-1 w-full rounded-lg text-xs"
                                onClick={onLoadMore}
                            >
                                Load more · 25
                            </Button>
                        )}
                    </div>
                </div>
            )}
        </div>
    );
}
