import { router, usePage } from "@inertiajs/react";
import type { PageProps } from "@inertiajs/core";
import {
    ArrowDownRight,
    ArrowUpRight,
    Search,
    Star,
    TrendingUp,
    X, // Ditambahkan untuk ikon clear
} from "lucide-react";
import {
    useCallback,
    useDeferredValue,
    useEffect,
    useMemo,
    useRef,
    useState,
} from "react";
import { Button } from "@/components/ui/button";
import { Input } from "@/components/ui/input";
import {
    Sheet,
    SheetContent,
    SheetDescription,
    SheetHeader,
    SheetTitle,
} from "@/components/ui/sheet";
import { ToggleGroup, ToggleGroupItem } from "@/components/ui/toggle-group";
import {
    Select,
    SelectContent,
    SelectItem,
    SelectTrigger,
    SelectValue,
} from "@/components/ui/select";
import { useActiveMarket } from "@/components/trading/active-market";
import { formatPrice, type MarketType } from "@/lib/market";
import { hasSubscriptionFeature } from "@/lib/subscription-access";
import { useI18n } from "@/lib/i18n";

interface CatalogItem {
    symbol: string;
    name: string;
}

interface ProviderOption {
    name: string;
    slug: string;
    driver: string;
    markets: MarketType[];
}

interface TickerItem {
    symbol: string;
    last: number;
    change_pct: number;
    quote_volume: number;
}

interface HeaderCoinSearchProps {
    open: boolean;
    onOpenChange: (open: boolean) => void;
}

interface SharedProps extends PageProps {
    subscription?: {
        active?: boolean;
        features?: string[];
    } | null;
}

type CoinFilter = "all" | "gainers" | "losers" | "favorites";

const INITIAL_VISIBLE_ITEMS = 25;
const VISIBLE_ITEMS_STEP = 25;

const MARKET_OPTIONS: { value: MarketType; label: string }[] = [
    { value: "spot", label: "Spot" },
    { value: "futures", label: "Futures" },
];

const normalizeSymbol = (value: string) =>
    value
        .trim()
        .toUpperCase()
        .replace(/[\s/_-]/g, "");

function isCatalog(value: unknown): value is CatalogItem[] {
    return (
        Array.isArray(value) &&
        value.every(
            (item) =>
                item &&
                typeof item === "object" &&
                typeof (item as CatalogItem).symbol === "string" &&
                typeof (item as CatalogItem).name === "string",
        )
    );
}

function isTickerList(value: unknown): value is TickerItem[] {
    return (
        Array.isArray(value) &&
        value.every(
            (item) =>
                item &&
                typeof item === "object" &&
                typeof (item as TickerItem).symbol === "string" &&
                Number.isFinite((item as TickerItem).last) &&
                Number.isFinite((item as TickerItem).change_pct),
        )
    );
}

type RequestErrorMessages = {
    featureUnavailable: string;
    accessDenied: string;
    loadFailed: (status: number) => string;
};

async function getJson<T>(
    url: string,
    signal: AbortSignal | undefined,
    messages: RequestErrorMessages,
): Promise<T> {
    const response = await fetch(url, {
        headers: {
            Accept: "application/json",
            "X-Requested-With": "XMLHttpRequest",
        },
        credentials: "same-origin",
        signal,
    });
    if (!response.ok) {
        throw new Error(
            response.status === 402
                ? messages.featureUnavailable
                : response.status === 403
                  ? messages.accessDenied
                  : messages.loadFailed(response.status),
        );
    }
    return (await response.json()) as T;
}

export default function HeaderCoinSearch({
    open,
    onOpenChange,
}: HeaderCoinSearchProps) {
    const page = usePage<SharedProps>();
    const { t, locale } = useI18n();
    const { activeMarket, updateActiveMarket } = useActiveMarket();

    const tx = (
        key: string,
        english: string,
        indonesian: string,
        replacements: Record<string, string | number> = {},
    ) =>
        t(
            key,
            locale.toLowerCase().startsWith("id") ? indonesian : english,
            replacements,
        );
    const canAccessChart = hasSubscriptionFeature(
        page.props.subscription,
        "chart",
    );
    const canUseWatchlist = hasSubscriptionFeature(
        page.props.subscription,
        "watchlist",
    );
    const [market, setMarket] = useState<MarketType>(
        activeMarket?.market ?? "spot",
    );
    const [search, setSearch] = useState("");
    const deferredSearch = useDeferredValue(search);
    const [coinFilter, setCoinFilter] = useState<CoinFilter>("all");
    const [visibleLimit, setVisibleLimit] = useState(INITIAL_VISIBLE_ITEMS);
    const activeProvider = activeMarket?.provider ?? "binance";
    const interval = activeMarket?.interval ?? "1h";
    const [selectedProvider, setSelectedProvider] = useState(activeProvider);
    const [providers, setProviders] = useState<ProviderOption[]>([]);
    const [providerLoading, setProviderLoading] = useState(false);
    const [catalogs, setCatalogs] = useState<Record<string, CatalogItem[]>>({});
    const [catalogLoaded, setCatalogLoaded] = useState<Record<string, boolean>>(
        {},
    );
    const provider = selectedProvider;
    const catalogKey = `${provider}|${market}`;
    const catalog = catalogs[catalogKey] ?? [];
    const [tickerSnapshot, setTickerSnapshot] = useState<{
        context: string;
        values: Record<string, TickerItem>;
    }>({ context: "", values: {} });
    const tickerContext = `${market}|${provider}`;
    const tickers =
        tickerSnapshot.context === tickerContext ? tickerSnapshot.values : {};
    const [watchlist, setWatchlist] = useState<string[]>([]);
    const [loading, setLoading] = useState(false);
    const [error, setError] = useState<string | null>(null);
    const [favoriteBusy, setFavoriteBusy] = useState<string | null>(null);
    const [watchlistLoading, setWatchlistLoading] = useState(false);
    const [watchlistError, setWatchlistError] = useState<string | null>(null);
    const watchlistMutationVersion = useRef(0);

    useEffect(() => {
        if (providers.length === 0) return;

        setSelectedProvider((current) => {
            if (
                providers.some(
                    (item) =>
                        item.slug === current && item.markets.includes(market),
                )
            ) {
                return current;
            }

            return (
                providers.find((item) => item.markets.includes(market))?.slug ??
                current
            );
        });
    }, [market, providers]);

    useEffect(() => {
        if (!open || !canAccessChart) return;

        const controller = new AbortController();
        let active = true;
        setProviderLoading(true);

        void getJson<unknown>("/market/providers", controller.signal, {
            featureUnavailable: tx(
                "header_coin_search.market_feature_unavailable",
                "Market access is not available on your plan.",
                "Akses market tidak tersedia pada paket Anda.",
            ),
            accessDenied: tx(
                "header_coin_search.market_access_denied",
                "Market access is not allowed.",
                "Akses market tidak diizinkan.",
            ),
            loadFailed: (status) =>
                tx(
                    "header_coin_search.market_load_failed",
                    `Failed to load market providers (HTTP ${status}).`,
                    `Gagal memuat market provider (HTTP ${status}).`,
                ),
        })
            .then((data) => {
                if (!active || !Array.isArray(data)) return;
                // /market/providers returns normalized capability data from ProviderRegistry:
                // { name, slug, driver, markets: ["spot", "futures"] }.
                // Older responses may still expose spot_enabled/futures_enabled, so keep
                // those as a backwards-compatible fallback.
                const next = data
                    .map((item): ProviderOption | null => {
                        if (!item || typeof item !== "object") return null;

                        const candidate = item as {
                            name?: unknown;
                            slug?: unknown;
                            driver?: unknown;
                            markets?: unknown;
                            spot_enabled?: unknown;
                            futures_enabled?: unknown;
                        };

                        if (
                            typeof candidate.name !== "string" ||
                            typeof candidate.slug !== "string" ||
                            typeof candidate.driver !== "string"
                        ) {
                            return null;
                        }

                        const markets = Array.isArray(candidate.markets)
                            ? candidate.markets.filter(
                                  (value): value is MarketType =>
                                      value === "spot" || value === "futures",
                              )
                            : [
                                  ...(candidate.spot_enabled === true
                                      ? (["spot"] as const)
                                      : []),
                                  ...(candidate.futures_enabled === true
                                      ? (["futures"] as const)
                                      : []),
                              ];

                        if (markets.length === 0) return null;

                        return {
                            name: candidate.name,
                            slug: candidate.slug,
                            driver: candidate.driver,
                            markets: Array.from(new Set(markets)),
                        };
                    })
                    .filter((item): item is ProviderOption => item !== null);

                setProviders(next);
                setSelectedProvider((current) => {
                    const currentProvider = next.find(
                        (item) => item.slug === current,
                    );
                    if (currentProvider?.markets.includes(market))
                        return current;
                    return (
                        next.find((item) => item.markets.includes(market))
                            ?.slug ?? current
                    );
                });
            })
            .catch((reason: unknown) => {
                if (
                    !active ||
                    (reason instanceof DOMException &&
                        reason.name === "AbortError")
                )
                    return;
                setError(
                    reason instanceof Error
                        ? reason.message
                        : tx(
                              "header_coin_search.provider_load_failed",
                              "Failed to load market providers.",
                              "Gagal memuat market provider.",
                          ),
                );
            })
            .finally(() => {
                if (active) setProviderLoading(false);
            });

        return () => {
            active = false;
            controller.abort();
        };
    }, [open, canAccessChart, locale]);

    useEffect(() => {
        if (
            !open ||
            !canAccessChart ||
            !provider ||
            providerLoading ||
            providers.length === 0
        )
            return;
        setError(null);
        if (catalogLoaded[catalogKey]) {
            setLoading(false);
            return;
        }

        const controller = new AbortController();
        let active = true;
        setLoading(true);

        void getJson<unknown>(
            `/market/catalog?market=${market}&provider=${encodeURIComponent(provider)}`,
            controller.signal,
            {
                featureUnavailable: tx(
                    "header_coin_search.market_feature_unavailable",
                    "Market access is not available on your plan.",
                    "Akses market tidak tersedia pada paket Anda.",
                ),
                accessDenied: tx(
                    "header_coin_search.market_access_denied",
                    "Market access is not allowed.",
                    "Akses market tidak diizinkan.",
                ),
                loadFailed: (status) =>
                    tx(
                        "header_coin_search.market_load_failed",
                        `Failed to load market (HTTP ${status}).`,
                        `Failed to load market (HTTP ${status}).`,
                    ),
            },
        )
            .then((data) => {
                if (!active) return;
                if (!isCatalog(data)) {
                    throw new Error(
                        tx(
                            "header_coin_search.invalid_catalog_format",
                            "The market catalog format is invalid.",
                            "Format katalog market tidak valid.",
                        ),
                    );
                }
                setCatalogs((current) => ({ ...current, [catalogKey]: data }));
                setCatalogLoaded((current) => ({
                    ...current,
                    [catalogKey]: true,
                }));
                setLoading(false);
            })
            .catch((reason: unknown) => {
                if (
                    !active ||
                    (reason instanceof DOMException &&
                        reason.name === "AbortError")
                )
                    return;
                setError(
                    reason instanceof Error
                        ? reason.message
                        : tx(
                              "header_coin_search.catalog_load_failed",
                              "Failed to load the market catalog.",
                              "Failed to load the market catalog.",
                          ),
                );
                setLoading(false);
            });

        return () => {
            active = false;
            controller.abort();
        };
    }, [
        open,
        market,
        provider,
        providerLoading,
        providers.length,
        canAccessChart,
        catalogKey,
        catalogLoaded[catalogKey],
        locale,
    ]);

    useEffect(() => {
        if (!open || !canUseWatchlist) {
            setWatchlistLoading(false);
            return;
        }

        const controller = new AbortController();
        let active = true;
        const requestVersion = watchlistMutationVersion.current;
        setWatchlistLoading(true);
        setWatchlistError(null);

        void getJson<unknown>("/user/watchlist", controller.signal, {
            featureUnavailable: tx(
                "header_coin_search.watchlist_access_limit",
                "Your watchlist plan limit or access is insufficient.",
                "Batas atau akses watchlist paket Anda tidak mencukupi.",
            ),
            accessDenied: tx(
                "header_coin_search.market_access_denied",
                "Market access is not allowed.",
                "Akses market tidak diizinkan.",
            ),
            loadFailed: (status) =>
                tx(
                    "header_coin_search.watchlist_update_failed",
                    `Failed to load watchlist (HTTP ${status}).`,
                    `Failed to load watchlist (HTTP ${status}).`,
                ),
        })
            .then((data) => {
                if (
                    !active ||
                    requestVersion !== watchlistMutationVersion.current
                )
                    return;
                if (!Array.isArray(data)) {
                    throw new Error(
                        tx(
                            "header_coin_search.invalid_watchlist_format",
                            "The watchlist format is invalid.",
                            "Format watchlist tidak valid.",
                        ),
                    );
                }
                const items = data.filter(
                    (
                        item: unknown,
                    ): item is { symbol: string; market: MarketType } => {
                        if (!item || typeof item !== "object") return false;
                        const candidate = item as {
                            symbol?: unknown;
                            market?: unknown;
                        };
                        return (
                            typeof candidate.symbol === "string" &&
                            (candidate.market === "spot" ||
                                candidate.market === "futures")
                        );
                    },
                );
                setWatchlist(
                    items.map(
                        (item) =>
                            `${item.market}:${normalizeSymbol(item.symbol)}`,
                    ),
                );
            })
            .catch((reason: unknown) => {
                if (
                    !active ||
                    (reason instanceof DOMException &&
                        reason.name === "AbortError")
                )
                    return;
                setWatchlistError(
                    reason instanceof Error
                        ? reason.message
                        : tx(
                              "header_coin_search.watchlist_load_failed",
                              "Failed to load favorites.",
                              "Failed to load favorites.",
                          ),
                );
            })
            .finally(() => {
                if (active) setWatchlistLoading(false);
            });

        return () => {
            active = false;
            controller.abort();
        };
    }, [open, canUseWatchlist, locale]);

    useEffect(() => {
        if (!open || !canAccessChart) return;
        let active = true;
        let timer: ReturnType<typeof setTimeout> | undefined;
        let controller: AbortController | null = null;

        const schedule = () => {
            if (active) timer = setTimeout(() => void refresh(), 15_000);
        };

        const refresh = async () => {
            if (!active) return;
            if (timer) {
                clearTimeout(timer);
                timer = undefined;
            }
            if (document.visibilityState !== "visible") {
                schedule();
                return;
            }

            const requestController = new AbortController();
            controller = requestController;
            try {
                const data = await getJson<unknown>(
                    `/market/tickers?market=${market}&provider=${encodeURIComponent(provider)}`,
                    requestController.signal,
                    {
                        featureUnavailable: tx(
                            "header_coin_search.market_feature_unavailable",
                            "Market access is not available on your plan.",
                            "Akses market tidak tersedia pada paket Anda.",
                        ),
                        accessDenied: tx(
                            "header_coin_search.market_access_denied",
                            "Market access is not allowed.",
                            "Akses market tidak diizinkan.",
                        ),
                        loadFailed: (status) =>
                            tx(
                                "header_coin_search.market_load_failed",
                                `Failed to load market (HTTP ${status}).`,
                                `Failed to load market (HTTP ${status}).`,
                            ),
                    },
                );
                if (active && isTickerList(data)) {
                    setTickerSnapshot({
                        context: tickerContext,
                        values: Object.fromEntries(
                            data.map((item) => [item.symbol, item]),
                        ),
                    });
                }
            } catch {
                // Keep the last successful ticker snapshot while the picker remains open.
            } finally {
                if (controller === requestController) {
                    controller = null;
                    schedule();
                }
            }
        };

        const handleVisibilityChange = () => {
            if (document.visibilityState === "visible") {
                if (timer) {
                    clearTimeout(timer);
                    timer = undefined;
                }
                void refresh();
            } else {
                controller?.abort();
            }
        };

        void refresh();
        document.addEventListener("visibilitychange", handleVisibilityChange);
        return () => {
            active = false;
            if (timer) clearTimeout(timer);
            controller?.abort();
            document.removeEventListener(
                "visibilitychange",
                handleVisibilityChange,
            );
        };
    }, [open, canAccessChart, market, provider, tickerContext]);

    const watchlistSet = useMemo(() => new Set(watchlist), [watchlist]);

    const visibleItems = useMemo(() => {
        const normalizedQuery = deferredSearch.trim().toLowerCase();
        const filtered = catalog.filter((item) => {
            // Defensive UI filter: some cached/legacy catalog responses may still
            // contain a bare `USDT`, which renders as `/USDT`. Never show it.
            const displaySymbol = item.symbol
                .trim()
                .toUpperCase()
                .replace(/USDT$/, "/USDT");
            if (displaySymbol === "/USDT") return false;

            const isFavorite = watchlistSet.has(
                `${market}:${normalizeSymbol(item.symbol)}`,
            );
            if (
                coinFilter === "favorites" &&
                (!canUseWatchlist || !isFavorite)
            ) {
                return false;
            }
            if (
                normalizedQuery &&
                !item.symbol.toLowerCase().includes(normalizedQuery) &&
                !item.name.toLowerCase().includes(normalizedQuery)
            ) {
                return false;
            }

            const ticker = tickers[item.symbol];
            if (coinFilter === "gainers")
                return Boolean(ticker && ticker.change_pct > 0);
            if (coinFilter === "losers")
                return Boolean(ticker && ticker.change_pct < 0);
            return true;
        });

        if (coinFilter === "gainers") {
            filtered.sort(
                (a, b) =>
                    (tickers[b.symbol]?.change_pct ?? -Infinity) -
                    (tickers[a.symbol]?.change_pct ?? -Infinity),
            );
        } else if (coinFilter === "losers") {
            filtered.sort(
                (a, b) =>
                    (tickers[a.symbol]?.change_pct ?? Infinity) -
                    (tickers[b.symbol]?.change_pct ?? Infinity),
            );
        }

        return filtered;
    }, [
        catalog,
        deferredSearch,
        coinFilter,
        watchlistSet,
        market,
        canUseWatchlist,
        tickers,
    ]);

    const displayedItems = useMemo(
        () => visibleItems.slice(0, visibleLimit),
        [visibleItems, visibleLimit],
    );

    useEffect(() => {
        setVisibleLimit(INITIAL_VISIBLE_ITEMS);
    }, [market, provider, coinFilter, search]);

    const close = useCallback(
        (nextOpen: boolean) => {
            onOpenChange(nextOpen);
            if (!nextOpen) {
                setSearch("");
                setCoinFilter("all");
                setError(null);
                setWatchlistError(null);
            } else {
                setMarket(activeMarket?.market ?? "spot");
                setSelectedProvider(activeMarket?.provider ?? "binance");
            }
        },
        [activeMarket?.market, activeMarket?.provider, onOpenChange],
    );

    const handleMarketChange = (nextMarket: MarketType) => {
        setMarket(nextMarket);
        setSelectedProvider((current) => {
            const currentProvider = providers.find(
                (item) => item.slug === current,
            );
            if (currentProvider?.markets.includes(nextMarket)) return current;
            return (
                providers.find((item) => item.markets.includes(nextMarket))
                    ?.slug ?? current
            );
        });
        setError(null);
    };

    const handleProviderChange = (nextProvider: string) => {
        const selected = providers.find((item) => item.slug === nextProvider);
        if (!selected?.markets.includes(market)) return;
        setSelectedProvider(nextProvider);
        setCoinFilter("all");
        setSearch("");
        setError(null);
    };

    const toggleFavorite = async (symbol: string) => {
        if (!canUseWatchlist || favoriteBusy !== null || watchlistLoading)
            return;

        const key = `${market}:${normalizeSymbol(symbol)}`;
        const wasFavorite = watchlistSet.has(key);
        watchlistMutationVersion.current += 1;
        setFavoriteBusy(key);
        setWatchlistError(null);
        setWatchlist((current) =>
            wasFavorite
                ? current.filter((item) => item !== key)
                : [...current, key],
        );

        try {
            const csrfToken = document.querySelector<HTMLMetaElement>(
                'meta[name="csrf-token"]',
            )?.content;
            const response = await fetch("/user/watchlist/toggle", {
                method: "POST",
                headers: {
                    "Content-Type": "application/json",
                    Accept: "application/json",
                    "X-Requested-With": "XMLHttpRequest",
                    ...(csrfToken ? { "X-CSRF-TOKEN": csrfToken } : {}),
                },
                credentials: "same-origin",
                body: JSON.stringify({ symbol, market }),
            });
            const body: unknown = await response.json().catch(() => null);
            const payload =
                body && typeof body === "object"
                    ? (body as {
                          status?: unknown;
                          key?: unknown;
                          message?: unknown;
                      })
                    : null;

            if (!response.ok) {
                const serverMessage =
                    typeof payload?.message === "string"
                        ? payload.message
                        : response.status === 419
                          ? tx(
                                "header_coin_search.security_session_expired",
                                "Your security session has expired. Reload the page and try again.",
                                "Sesi keamanan kedaluwarsa. Muat ulang halaman lalu coba lagi.",
                            )
                          : response.status === 402
                            ? tx(
                                  "header_coin_search.watchlist_access_limit",
                                  "Your watchlist plan limit or access is insufficient.",
                                  "Batas atau akses watchlist paket Anda tidak mencukupi.",
                              )
                            : tx(
                                  "header_coin_search.watchlist_update_failed",
                                  `Failed to update watchlist (HTTP ${response.status}).`,
                                  `Watchlist gagal diperbarui (HTTP ${response.status}).`,
                              );
                throw new Error(serverMessage);
            }

            if (
                (payload?.status !== "added" &&
                    payload?.status !== "removed") ||
                (typeof payload.key === "string" && payload.key !== key)
            ) {
                throw new Error(
                    tx(
                        "header_coin_search.watchlist_response_invalid",
                        "The watchlist response does not match the requested change.",
                        "Respons watchlist tidak sesuai dengan perubahan yang diminta.",
                    ),
                );
            }

            setWatchlist((current) => {
                const next = new Set(current);
                if (payload.status === "added") next.add(key);
                else next.delete(key);
                return [...next];
            });
        } catch (reason) {
            setWatchlist((current) => {
                const next = new Set(current);
                if (wasFavorite) next.add(key);
                else next.delete(key);
                return [...next];
            });
            setWatchlistError(
                reason instanceof Error
                    ? reason.message
                    : tx(
                          "header_coin_search.watchlist_update_failed_generic",
                          "Failed to update watchlist.",
                          "Watchlist gagal diperbarui.",
                      ),
            );
        } finally {
            setFavoriteBusy(null);
        }
    };

    const selectCoin = (item: CatalogItem) => {
        updateActiveMarket({
            symbol: item.symbol,
            market,
            interval,
            provider,
            name: item.name,
            price: tickers[item.symbol]?.last ?? null,
            changePct: tickers[item.symbol]?.change_pct ?? null,
            updatedAt: Date.now(),
        });
        router.get(
            `/trading/${encodeURIComponent(item.symbol)}`,
            {
                interval,
                ...(market === "futures" ? { market } : {}),
                ...(provider !== "binance" ? { provider } : {}),
            },
            { preserveScroll: false, preserveState: false, replace: false },
        );
        close(false);
    };

    if (!canAccessChart) return null;

    return (
        <Sheet open={open} onOpenChange={close}>
            <SheetContent
                side="left"
                className="flex w-full flex-col gap-0 border-border/60 bg-background/95 p-0 text-foreground shadow-2xl backdrop-blur-xl sm:max-w-md"
            >
                <SheetHeader className="space-y-4 border-b border-border/60 p-5">
                    <div>
                        <SheetTitle className="flex items-center gap-2 text-lg font-bold">
                            <TrendingUp className="size-5 text-amber-500" />
                            {tx(
                                "header_coin_search.title",
                                "Market Search",
                                "Pencarian market",
                            )}
                        </SheetTitle>
                        <SheetDescription className="text-xs">
                            {tx(
                                "header_coin_search.description",
                                "Choose an asset to open its chart and carry market context to other pages.",
                                "Pilih aset untuk membuka chart dan membawa konteks market ke halaman lain.",
                            )}
                        </SheetDescription>
                    </div>
                    <div className="space-y-1.5">
                        <div className="text-[11px] font-semibold uppercase tracking-wide text-muted-foreground">
                            {tx(
                                "header_coin_search.provider",
                                "Provider",
                                "Provider",
                            )}
                        </div>
                        <Select
                            value={provider}
                            onValueChange={handleProviderChange}
                            disabled={providerLoading || providers.length === 0}
                        >
                            <SelectTrigger className="h-10 w-full rounded-xl text-sm font-semibold">
                                <SelectValue
                                    placeholder={tx(
                                        "header_coin_search.provider_placeholder",
                                        "Select provider",
                                        "Pilih provider",
                                    )}
                                />
                            </SelectTrigger>
                            <SelectContent className="z-120">
                                {providers
                                    .filter((item) =>
                                        item.markets.includes(market),
                                    )
                                    .map((item) => (
                                        <SelectItem
                                            key={item.slug}
                                            value={item.slug}
                                        >
                                            {item.name}
                                        </SelectItem>
                                    ))}
                            </SelectContent>
                        </Select>
                    </div>
                    <ToggleGroup
                        type="single"
                        value={market}
                        onValueChange={(value) =>
                            value && handleMarketChange(value as MarketType)
                        }
                        className="grid w-full grid-cols-2 gap-1 rounded-xl border border-border/60 bg-muted/40 p-1"
                        aria-label={tx(
                            "chart.market_type",
                            "Market type",
                            "Jenis market",
                        )}
                    >
                        {MARKET_OPTIONS.map((item) => (
                            <ToggleGroupItem
                                key={item.value}
                                value={item.value}
                                className="h-9 rounded-lg text-xs font-semibold"
                            >
                                {item.value === "spot"
                                    ? tx("chart.spot", "Spot", "Spot")
                                    : tx(
                                          "header_coin_search.futures",
                                          "Futures",
                                          "Futures",
                                      )}
                            </ToggleGroupItem>
                        ))}
                    </ToggleGroup>
                    <div className="relative">
                        <Search className="absolute left-3 top-1/2 size-4 -translate-y-1/2 text-muted-foreground" />
                        <Input
                            value={search}
                            onChange={(event) => setSearch(event.target.value)}
                            placeholder={tx(
                                "header_coin_search.search_placeholder",
                                "Search BTC, ETH, or asset name...",
                                "Cari BTC, ETH, nama aset...",
                            )}
                            autoComplete="off"
                            className="h-10 rounded-xl pl-9 pr-9"
                            aria-label={tx(
                                "header_coin_search.search_coin",
                                "Search coin",
                                "Cari koin",
                            )}
                        />
                        {search && (
                            <button
                                type="button"
                                onClick={() => setSearch("")}
                                className="absolute right-3 top-1/2 -translate-y-1/2 text-muted-foreground transition-colors hover:text-foreground"
                                aria-label={tx(
                                    "header_coin_search.clear_search",
                                    "Clear search",
                                    "Hapus pencarian",
                                )}
                            >
                                <X className="size-4" />
                            </button>
                        )}
                    </div>
                    <div className="space-y-2">
                        <ToggleGroup
                            type="single"
                            value={coinFilter}
                            onValueChange={(value) =>
                                value && setCoinFilter(value as CoinFilter)
                            }
                            className={`grid w-full ${canUseWatchlist ? "grid-cols-4" : "grid-cols-3"} gap-1 rounded-xl border border-border/60 bg-muted/30 p-1`}
                            aria-label={tx(
                                "header_coin_search.filter",
                                "Coin filter",
                                "Filter koin",
                            )}
                        >
                            <ToggleGroupItem
                                value="all"
                                className="h-8 rounded-lg px-1 text-[11px]"
                            >
                                {tx("common.all", "All", "Semua")}
                            </ToggleGroupItem>
                            <ToggleGroupItem
                                value="gainers"
                                className="h-8 gap-1 rounded-lg px-1 text-[11px]"
                            >
                                <ArrowUpRight className="size-3.5 text-emerald-500" />{" "}
                                {tx(
                                    "header_coin_search.gainers",
                                    "Gainers",
                                    "Naik",
                                )}
                            </ToggleGroupItem>
                            <ToggleGroupItem
                                value="losers"
                                className="h-8 gap-1 rounded-lg px-1 text-[11px]"
                            >
                                <ArrowDownRight className="size-3.5 text-red-500" />{" "}
                                {tx(
                                    "header_coin_search.losers",
                                    "Losers",
                                    "Turun",
                                )}
                            </ToggleGroupItem>
                            {canUseWatchlist && (
                                <ToggleGroupItem
                                    value="favorites"
                                    className="h-8 gap-1 rounded-lg px-1 text-[11px]"
                                >
                                    <Star className="size-3.5 text-amber-500" />{" "}
                                    {tx(
                                        "header_coin_search.favorites",
                                        "Favorites",
                                        "Favorit",
                                    )}
                                </ToggleGroupItem>
                            )}
                        </ToggleGroup>
                        <div className="flex items-center justify-between gap-2 text-[11px] text-muted-foreground">
                            <span>
                                {tx(
                                    "header_coin_search.asset_count",
                                    ":shown of :total assets",
                                    ":shown dari :total aset",
                                    {
                                        shown: displayedItems.length,
                                        total: visibleItems.length,
                                    },
                                )}
                            </span>
                            {watchlistLoading && canUseWatchlist && (
                                <span>
                                    {tx(
                                        "header_coin_search.loading_favorites",
                                        "Loading favorites…",
                                        "Loading favorites…",
                                    )}
                                </span>
                            )}
                        </div>
                    </div>
                </SheetHeader>
                {(error || watchlistError) && (
                    <div
                        className="mx-4 mt-3 space-y-1 rounded-lg border border-destructive/30 bg-destructive/10 px-3 py-2 text-xs text-destructive"
                        role="alert"
                    >
                        {error && <p>{error}</p>}
                        {watchlistError && <p>{watchlistError}</p>}
                    </div>
                )}
                <div className="flex-1 overflow-y-auto px-3 py-2">
                    {loading && catalog.length === 0 ? (
                        <div className="px-4 py-12 text-center text-sm text-muted-foreground">
                            {tx(
                                "header_coin_search.loading_catalog",
                                "Loading coin catalog…",
                                "Loading coin catalog…",
                            )}
                        </div>
                    ) : visibleItems.length === 0 ? (
                        <div className="px-4 py-12 text-center text-sm text-muted-foreground">
                            {catalog.length === 0
                                ? tx(
                                      "header_coin_search.catalog_unavailable",
                                      "Market catalog is not available yet.",
                                      "Katalog market belum tersedia.",
                                  )
                                : tx(
                                      "header_coin_search.no_matching_assets",
                                      "No matching assets found.",
                                      "Tidak ada aset yang cocok.",
                                  )}
                        </div>
                    ) : (
                        <ul className="divide-y divide-border/40">
                            {displayedItems.map((item) => {
                                const ticker = tickers[item.symbol];
                                const isFavorite = watchlist.includes(
                                    `${market}:${normalizeSymbol(item.symbol)}`,
                                );
                                const isActive =
                                    activeMarket?.symbol === item.symbol &&
                                    activeMarket.market === market &&
                                    activeMarket.provider === provider;
                                return (
                                    <li
                                        key={item.symbol}
                                        className="flex items-center gap-2 py-1"
                                    >
                                        {canUseWatchlist && (
                                            <Button
                                                type="button"
                                                variant="ghost"
                                                size="icon-sm"
                                                disabled={
                                                    favoriteBusy !== null ||
                                                    watchlistLoading
                                                }
                                                aria-label={
                                                    isFavorite
                                                        ? tx(
                                                              "header_coin_search.remove_favorite",
                                                              `Remove ${item.symbol} from favorites`,
                                                              `Hapus ${item.symbol} dari favorit`,
                                                          )
                                                        : tx(
                                                              "header_coin_search.add_favorite",
                                                              `Add ${item.symbol} to favorites`,
                                                              `Tambah ${item.symbol} ke favorit`,
                                                          )
                                                }
                                                onClick={() =>
                                                    void toggleFavorite(
                                                        item.symbol,
                                                    )
                                                }
                                                className="shrink-0"
                                            >
                                                <Star
                                                    className={`size-4 ${isFavorite ? "fill-amber-400 text-amber-400" : "text-muted-foreground"}`}
                                                />
                                            </Button>
                                        )}
                                        <button
                                            type="button"
                                            onClick={() => selectCoin(item)}
                                            className={`flex min-w-0 flex-1 items-center justify-between gap-3 rounded-lg px-3 py-3 text-left transition-colors hover:bg-muted/50 ${isActive ? "bg-amber-500/10" : ""}`}
                                            aria-current={
                                                isActive ? "true" : undefined
                                            }
                                        >
                                            <span className="min-w-0">
                                                <span className="flex items-center gap-2 text-sm font-semibold text-foreground">
                                                    {item.symbol.replace(
                                                        /USDT$/,
                                                        "/USDT",
                                                    )}
                                                    {market === "futures" && (
                                                        <span className="rounded border border-amber-500/20 bg-amber-500/10 px-1 py-0.5 text-[9px] text-amber-600">
                                                            {tx(
                                                                "header_coin_search.perpetual_badge",
                                                                "PERP",
                                                                "PERP",
                                                            )}
                                                        </span>
                                                    )}
                                                    {isActive && (
                                                        <span className="size-1.5 rounded-full bg-emerald-500" />
                                                    )}
                                                </span>
                                                <span className="mt-0.5 block truncate text-xs text-muted-foreground">
                                                    {item.name}
                                                </span>
                                            </span>
                                            <span className="shrink-0 text-right tabular-nums">
                                                <span className="block text-sm font-semibold">
                                                    {ticker
                                                        ? formatPrice(
                                                              ticker.last,
                                                          )
                                                        : "—"}
                                                </span>
                                                <span
                                                    className={`text-[11px] ${ticker ? (ticker.change_pct >= 0 ? "text-emerald-600" : "text-red-500") : "text-muted-foreground"}`}
                                                >
                                                    {ticker
                                                        ? `${ticker.change_pct >= 0 ? "+" : ""}${ticker.change_pct.toFixed(2)}%`
                                                        : tx(
                                                              "header_coin_search.price_unavailable",
                                                              "Price —",
                                                              "Harga —",
                                                          )}
                                                </span>
                                            </span>
                                        </button>
                                    </li>
                                );
                            })}
                        </ul>
                    )}
                    {displayedItems.length < visibleItems.length && (
                        <div className="flex justify-center py-3">
                            <Button
                                type="button"
                                variant="outline"
                                size="sm"
                                onClick={() =>
                                    setVisibleLimit(
                                        (current) =>
                                            current + VISIBLE_ITEMS_STEP,
                                    )
                                }
                            >
                                {tx(
                                    "header_coin_search.load_more",
                                    "Load :count more assets",
                                    "Muat :count aset lagi",
                                    {
                                        count: Math.min(
                                            VISIBLE_ITEMS_STEP,
                                            visibleItems.length -
                                                displayedItems.length,
                                        ),
                                    },
                                )}
                            </Button>
                        </div>
                    )}
                </div>
            </SheetContent>
        </Sheet>
    );
}
