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

import { AddTokenButton } from "@components/MultiOutput/AddTokenButton";
import { MIcon } from "@components/common/MIcon";
import { SelectTokenButton } from "@components/common/SelectTokenButton";
import { TokenChip } from "@components/common/TokenChip";
import { useFetchQuote } from "@hooks/apis/useFetchQuote";
import { useConfig } from "@hooks/useConfig";
import { setMultiTokenData } from "@store/multiTokenModalSlice";
import {
	removeOutputToken,
	resetOutputTokenRatios,
} from "@store/quoteParamSlice";
import { setTokenSelectorData } from "@store/tokenSelectorSlice";
import type { ReduxStateType } from "@store/types";
import { NATIVE_TOKEN_ADDRESS } from "@utils/constants";
import { formatValue } from "@utils/formatValue";
import { useOutputNativeTokenSelectorData } from "./useOutputNativeTokenSelectorData";
import { useOutputTokenSelectorData } from "./useOutputTokenSelectorData";

export const OutputToken = () => {
	const dispatch = useDispatch();
	const config = useConfig();
	const { data: quoteData } = useFetchQuote();

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

	const { data: tokenSelectorData, isLoading } = useOutputTokenSelectorData();
	const { data: multiOutputData } = useOutputNativeTokenSelectorData();

	function openSourceTokenSelector() {
		dispatch(setTokenSelectorData(tokenSelectorData));
	}

	const prevTokenSelectorData = useRef(tokenSelectorData);

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

	function openMultiTokenModal() {
		dispatch(setMultiTokenData(multiOutputData));
	}

	function removeToken(id: number) {
		dispatch(removeOutputToken({ id }));
		dispatch(resetOutputTokenRatios());
	}

	const multiTokensCapReached =
		selectedOutputTokens?.length === config.multiOutputCap;

	const isFirstTokenNative =
		selectedOutputTokens?.[0]?.address?.toLowerCase() === NATIVE_TOKEN_ADDRESS;

	const showTokenAddButton =
		config.enableMultiOutput &&
		selectedOutputTokens?.length > 0 &&
		!multiTokensCapReached &&
		!isFirstTokenNative;

	// @note: for multi-token, the amount is taken from quote response
	// tokens are fetched from quote params
	const renderTokensInfo = () => {
		const singleToken = selectedOutputTokens?.length === 1;

		if (selectedOutputTokens?.length === 0) {
			return (
				<SelectTokenButton onClick={openSourceTokenSelector} isLoading={isLoading} />
			);
		}

		return selectedOutputTokens?.map((token, id) => {
			// biome-ignore format:
			const key = `${token.address}-${id}`
			const formattedAmount = singleToken
				? undefined
				: formatValue(quoteData?.output[id].amount, token.decimals);

			return (
				<TokenChip
					token={token}
					key={key}
					onClick={singleToken ? openSourceTokenSelector : () => {}}
					classNames="bn-bg-layer-3"
					amount={formattedAmount}
					showChain
					big
				>
					{/* temporarily hiding close button for 1st token */}
					{!singleToken && id !== 0 && (
						// biome-ignore lint/a11y/useKeyWithClickEvents: <explanation>
						<div
							onClick={() => removeToken(id)}
							className="bn-bg-transparent bn-m-0 bn-p-0 bn-size-[18px] bn-cursor-pointer"
						>
							<MIcon name="close" classNames="bn-text-lg bn-text-primary" />
						</div>
					)}
				</TokenChip>
			);
		});
	};

	// @fixme: check for unnecessary rerenders
	return (
		<div className="bn-flex bn-items-center bn-space-x-2">
			{/* Note: Temporarily hiding for beta launch */}
			{/* {showTokenAddButton && (
				<AddTokenButton openMultiTokenModal={openMultiTokenModal} />
			)} */}
			{renderTokensInfo()}
		</div>
	);
};
