import { useEffect, useMemo, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { erc20Abi } from "viem";
import { useAccount, useConfig, useReadContract } from "wagmi";

import { Button } from "@components/common/Button";
import { SwitchChain } from "@components/common/SwitchChain";
import { setApprovalData } from "@store/approvalSlice";
import type { ReduxStateType } from "@store/types";
import { NATIVE_TOKEN_ADDRESS, PERMIT2_ADDRESS } from "@utils/constants";
import type { FormattedQuoteData } from "@utils/getQuoteData";
import { isWrapUnwrapCase } from "@utils/isWrapUnwrapCase";
import { checkUniversalSigningSupport } from "@utils/supportsUniversalSigning";
import { SendNativeTransaction } from "./SendNativeTransaction";
import { SignOrder } from "./SignOrder";

// biome-ignore format:
type Address = `0x${string}`;

export const ReviewActionButton = ({
	quoteData,
}: { quoteData: FormattedQuoteData }) => {
	const dispatch = useDispatch();
	const { chainId: activeChainId } = useAccount();

	const { chains: wagmiChains } = useConfig();
	const isCurrentChainSupported = wagmiChains.some(
		(chain) => chain.id === activeChainId,
	);

	const [isApprovalGiven, setIsApprovalGiven] = useState<boolean>(false);
	const isTokenApproved = useSelector(
		(state: ReduxStateType) => state.approval.isApprovalGiven,
	);
	const { primaryInput, sender, txData } = quoteData || {};

	const isNativeToken = useMemo(
		() => primaryInput?.token?.address?.toLowerCase() === NATIVE_TOKEN_ADDRESS,
		[primaryInput],
	);

	const {
		data,
		isLoading: isCheckingApproval,
		refetch: recheckApproval,
		isRefetching,
	} = useReadContract({
		abi: erc20Abi,
		address: primaryInput?.token.address as Address,
		functionName: "allowance",
		args: [sender as Address, PERMIT2_ADDRESS],
		chainId: primaryInput?.chainId,
		query: {
			enabled: !isNativeToken && !isWrapUnwrapCase(quoteData),
		},
	});

	useEffect(() => {
		// for native tokens
		if (isNativeToken) setIsApprovalGiven(true);

		// for erc20
		if (!!data?.toString() && primaryInput?.amount) {
			setIsApprovalGiven(data >= BigInt(primaryInput.amount));
		}
	}, [data, primaryInput, isNativeToken]);

	// If approval is set to true in store, rechecking the approval
	// This is done to make sure user has given sufficient approval
	useEffect(() => {
		if (isTokenApproved) recheckApproval();
	}, [isTokenApproved, recheckApproval]);

	const openApproval = () => {
		dispatch(
			setApprovalData({
				isVisible: true,
				approvalType: "permit2",
			}),
		);
	};

	const { connector } = useAccount();
	// const supportsUniversalSigning = checkUniversalSigningSupport(connector?.name);

	/**
	 * WIP
	 * Switch network when the wallet doesn't support signing from any network
	 * Switch when interacting with native tokens
	 * */

	const networkSwitchRequired =
		activeChainId !== primaryInput?.chainId || !isCurrentChainSupported;

	// biome-ignore format:
	const APPROVAL_BTN_LABEL = (isCheckingApproval || isRefetching) ? "Checking for approval" : `Approve ${primaryInput?.token?.symbol}`;

	if (networkSwitchRequired)
		return <SwitchChain switchTo={primaryInput?.chainId} />;

	if (!isApprovalGiven)
		return (
			<Button
				label={APPROVAL_BTN_LABEL}
				onClick={openApproval}
				disabled={isCheckingApproval || isRefetching}
				isLoading={isCheckingApproval || isRefetching}
			/>
		);

	if (txData) return <SendNativeTransaction quoteData={quoteData} />;

	return <SignOrder disabled={isCheckingApproval} quoteData={quoteData} />;
};
