import { Connection, PublicKey } from "@solana/web3.js";
import { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { isAddress } from "viem";
import { useBalance } from "wagmi";

import { useConfig } from "@hooks/useConfig";
import { useMappedChainData } from "@hooks/useMappedChainData";
import { toggleAddOnRefuel } from "@store/quoteParamSlice";
import type { ReduxStateType } from "@store/types";
import { SOLANA_CHAIN_ID } from "@utils/constants";
import { isDummyAddress } from "@utils/isDummyAddress";
import { isPublicKey } from "@utils/isPublicKey";

/**
 * Custom hook to check if the receiver address has enough gas on the destination network
 * @returns gasRequired - boolean indicating if gas is required
 */
export const useGasBalanceCheck = () => {
	const [gasRequired, setGasRequired] = useState(false);
	const [solanaBalance, setSolanaBalance] = useState<string>("0");
	const [isLoadingSolana, setIsLoadingSolana] = useState(false);

	const dispatch = useDispatch();
	const { toChainId, receiver, fromChainId } = useSelector(
		(state: ReduxStateType) => state.quoteParams,
	);

	const mappedChainData = useMappedChainData();
	const { rpcs } = useConfig();

	// Check if this is a same chain swap or wrap/unwrap case
	const isSameChain = fromChainId === toChainId;
	const isSolanaChain =
		toChainId === SOLANA_CHAIN_ID || fromChainId === SOLANA_CHAIN_ID;

	const shouldDisableRefuel = isSameChain || isSolanaChain;

	// Reset refuel toggle on mount and when conditions change
	useEffect(() => {
		if (shouldDisableRefuel) {
			dispatch(toggleAddOnRefuel(false));
		}
	}, [shouldDisableRefuel, dispatch]);

	// Get the minimum native currency required for gas
	const minNativeCurrencyForGas = toChainId
		? mappedChainData?.[toChainId]?.currency?.minNativeCurrencyForGas || "0"
		: "0";

	// Check if this is a valid EVM address for wagmi's useBalance
	const isValidEvmAddress =
		receiver &&
		toChainId !== SOLANA_CHAIN_ID &&
		isAddress(receiver) &&
		!isDummyAddress(receiver);

	// Use wagmi's useBalance for EVM chains
	const { data: evmBalance, isLoading: isLoadingEvm } = useBalance({
		address: isValidEvmAddress ? (receiver as `0x${string}`) : undefined,
		chainId: isValidEvmAddress && toChainId ? toChainId : undefined,
		query: {
			enabled: Boolean(isValidEvmAddress),
			refetchOnMount: "always",
			staleTime: 10000, // 10 seconds
		},
	});

	// Handle Solana balance separately
	useEffect(() => {
		const fetchSolanaBalance = async () => {
			if (
				!receiver ||
				toChainId !== SOLANA_CHAIN_ID ||
				!isPublicKey(receiver) ||
				isDummyAddress(receiver)
			) {
				setSolanaBalance("0");
				setIsLoadingSolana(false);
				return;
			}

			setIsLoadingSolana(true);
			try {
				const connection = new Connection(rpcs?.solana || "");
				const balance = await connection.getBalance(new PublicKey(receiver));
				setSolanaBalance(balance.toString());
			} catch (error) {
				console.error("Error fetching Solana balance:", error);
				setSolanaBalance("0");
			} finally {
				setIsLoadingSolana(false);
			}
		};

		fetchSolanaBalance();
	}, [receiver, toChainId, rpcs?.solana]);

	// Determine the current balance and loading state
	const currentBalance =
		toChainId === SOLANA_CHAIN_ID
			? solanaBalance
			: evmBalance?.value?.toString() || "0";
	const isLoading =
		toChainId === SOLANA_CHAIN_ID ? isLoadingSolana : isLoadingEvm;

	// Check if gas is required
	useEffect(() => {
		if (!receiver || !toChainId || !currentBalance || isLoading) {
			setGasRequired(false);
			return;
		}

		const balanceBigInt = BigInt(currentBalance);
		const minGasBigInt = BigInt(minNativeCurrencyForGas);

		// Check if the balance is less than the minimum required for gas
		const isLowGas = balanceBigInt < minGasBigInt;

		setGasRequired(isLowGas);
	}, [receiver, toChainId, currentBalance, minNativeCurrencyForGas, isLoading]);

	return {
		gasRequired: shouldDisableRefuel ? false : gasRequired,
		isLoading,
		nativeBalance: currentBalance,
		minNativeCurrencyForGas,
		chainName: toChainId ? mappedChainData?.[toChainId]?.name : null,
		shouldDisableRefuel,
	};
};
