import { useMemo } from "react";
import { useSelector } from "react-redux";
import { useAccount } from "wagmi";

import type { ReduxStateType } from "@store/types";
import { getFormattedTokenList } from "@utils/getFormattedTokenList";
import { useTokenSearch } from "./apis/common/useTokenSearch";
import { useSupportedChains } from "./useSupportedChains";

/**
 * useSearch.ts
 *
 * Key Features:
 * - Fetches the user's imported tokens from the Redux store.
 * - Performs a token search (api call) based on the input keyword and connected wallet address.
 * - Formats both imported and searched tokens using a standardized format utility.
 * - Optionally excludes tokens that have been previously shortlisted (imported).
 * - Filters tokens to only include those on supported input chains.
 * - Sorts the final result by USD balance in descending order.
 *
 * @returns An object containing:
 *   - `data`: The final list of filtered and sorted tokens.
 *   - `isLoading`: Boolean indicating the loading state of the token search API.
 */

export const useSearch = ({ keyword }: { keyword: string }) => {
	const importedTokens = useSelector(
		(state: ReduxStateType) => state.global.importedTokens,
	);
	const { supportedChainIds } = useSupportedChains({ input: true });
	const { address } = useAccount();

	const formattedImportedTokens = useMemo(
		() => importedTokens && getFormattedTokenList(importedTokens),
		[importedTokens],
	);

	const { data, isLoading } = useTokenSearch({
		keyword,
		address: address as string,
	});

	const formattedData = useMemo(() => getFormattedTokenList(data), [data]);

	// Exclude tokens that are included in formattedImportedTokens
	const filteredData = useMemo(
		() =>
			formattedData?.filter(
				(token) =>
					!formattedImportedTokens?.some(
						(importedToken) =>
							importedToken.address.toLowerCase() === token.address.toLowerCase() &&
							importedToken.chainId === token.chainId,
					) && supportedChainIds?.includes(token.chainId),
			),
		[formattedData, formattedImportedTokens, supportedChainIds],
	);

	// Sort tokens based on USD balance in descending order
	const sortedData = useMemo(
		() =>
			filteredData?.sort((a, b) => (b.balanceInUsd || 0) - (a.balanceInUsd || 0)),
		[filteredData],
	);

	return { data: sortedData, isLoading };
};
