import { useCallback, useEffect, useMemo, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";

import { SelectTokenButton } from "@components/common/SelectTokenButton";
import { TokenChip } from "@components/common/TokenChip";
import { useConfig } from "@hooks/useConfig";
import { setTokenSelectorData } from "@store/tokenSelectorSlice";
import type { ReduxStateType } from "@store/types";
import { DEFAULT_SOURCE_TOKEN } from "@utils/constants";
import { useInputTokenSelectorData } from "./useInputTokenSelectorData";

export const InputToken = () => {
	const dispatch = useDispatch();
	const config = useConfig();

	const tokenSelectorDataFromStore = useSelector(
		(state: ReduxStateType) => state.tokenSelector,
	);

	const fromTokens = useSelector(
		(state: ReduxStateType) => state.quoteParams.fromTokens,
	);
	const activeToken = fromTokens?.[0];

	const { data: tokenSelectorData, isLoading } = useInputTokenSelectorData();

	// Determine if we should show default token (when no token is set and no query params override)
	const shouldShowDefaultToken = useMemo(() => {
		if (activeToken) return false; // Already have a token
		if (
			config?.initialValues?.fromChain === DEFAULT_SOURCE_TOKEN.chainId &&
			config?.initialValues?.inputTokens?.[0]?.toLowerCase() ===
				DEFAULT_SOURCE_TOKEN.address.toLowerCase()
		) {
			// Config matches default, meaning no query params override
			return true;
		}
		return false;
	}, [activeToken, config]);

	// Use default token if we should show it, otherwise use activeToken
	const displayToken =
		activeToken || (shouldShowDefaultToken ? DEFAULT_SOURCE_TOKEN : null);

	const openSourceTokenSelector = useCallback(() => {
		dispatch(setTokenSelectorData(tokenSelectorData));
	}, [dispatch, tokenSelectorData]);

	const prevTokenSelectorData = useRef(tokenSelectorData);

	// to update token selector data when the tokens/chains are changed due to wallet/account switch or loading
	// to be updated only when the source token selector data is visible
	useEffect(() => {
		if (
			tokenSelectorData &&
			tokenSelectorData !== prevTokenSelectorData.current &&
			tokenSelectorDataFromStore?.isVisible &&
			tokenSelectorDataFromStore?.data?.isSourceTokenSelector
		) {
			dispatch(
				setTokenSelectorData({
					...tokenSelectorDataFromStore,
					data: {
						...tokenSelectorDataFromStore.data,
						chains: tokenSelectorData?.data?.chains,
						tokens: tokenSelectorData?.data?.tokens,
						isLoading: tokenSelectorData?.data?.isLoading,
					},
				}),
			);
		}
		prevTokenSelectorData.current = tokenSelectorData;
	}, [tokenSelectorData, tokenSelectorDataFromStore, dispatch]);

	return (
		<>
			{displayToken ? (
				<TokenChip
					token={displayToken}
					onClick={openSourceTokenSelector}
					showChain
					classNames="bn-bg-layer-3 hover:bn-bg-layer-1 "
					big
					id="src-token-selector-button"
				/>
			) : (
				<SelectTokenButton onClick={openSourceTokenSelector} />
			)}
		</>
	);
};
