import { useCallback } from "react";
import { type Address, erc20Abi, maxUint256 } from "viem";
import { useSendCalls } from "wagmi";

import type { ApprovalData, TxData } from "@hooks/apis/common/quote/types";
import { PERMIT2_ADDRESS } from "@utils/constants";

export function useBatchingTransaction({
	approvalData,
	txData,
	chainId,
	isApprovalRequired,
	needsPermit2Approval = false,
}: {
	txData: TxData;
	chainId: number;
	isApprovalRequired: boolean;
	approvalData?: ApprovalData;
	needsPermit2Approval?: boolean;
}) {
	const {
		sendCalls,
		sendCallsAsync,
		data: callsData,
		isSuccess,
		isError,
		error,
	} = useSendCalls();

	const trigger = useCallback(() => {
		const calls = [];

		// Add permit2 approval if missing
		if (needsPermit2Approval && approvalData) {
			calls.push({
				address: approvalData.tokenAddress as Address,
				abi: erc20Abi,
				functionName: "approve",
				args: [PERMIT2_ADDRESS, maxUint256],
				chainId,
				to: approvalData.tokenAddress as Address,
			});
		}

		// Add route-specific approval if needed
		if (isApprovalRequired && approvalData) {
			calls.push({
				address: approvalData.tokenAddress as Address,
				abi: erc20Abi,
				functionName: "approve",
				args: [
					approvalData.spenderAddress as Address,
					BigInt(approvalData.amount),
				],
				chainId,
				to: approvalData.tokenAddress as Address,
			});
		}

		// Add main transaction
		calls.push({
			data: txData.data as Address,
			to: txData.to as Address,
			value: BigInt(txData.value),
		});

		sendCalls({ calls });
	}, [
		chainId,
		txData,
		approvalData,
		isApprovalRequired,
		needsPermit2Approval,
		sendCalls,
	]);

	const triggerAsync = useCallback(() => {
		const calls = [];

		// Add permit2 approval if missing
		if (needsPermit2Approval && approvalData) {
			calls.push({
				address: approvalData.tokenAddress as Address,
				abi: erc20Abi,
				functionName: "approve",
				args: [PERMIT2_ADDRESS, maxUint256],
				chainId,
				to: approvalData.tokenAddress as Address,
			});
		}

		// Add route-specific approval if needed
		if (isApprovalRequired && approvalData) {
			calls.push({
				address: approvalData.tokenAddress as Address,
				abi: erc20Abi,
				functionName: "approve",
				args: [
					approvalData.spenderAddress as Address,
					BigInt(approvalData.amount),
				],
				chainId,
				to: approvalData.tokenAddress as Address,
			});
		}

		// Add main transaction
		calls.push({
			data: txData.data as Address,
			to: txData.to as Address,
			value: BigInt(txData.value),
		});

		return sendCallsAsync({ calls });
	}, [
		chainId,
		isApprovalRequired,
		needsPermit2Approval,
		sendCallsAsync,
		approvalData,
		txData,
	]);

	return {
		trigger,
		triggerAsync,
		isSuccess,
		isError,
		txData: callsData,
		error,
	};
}
