import { ERC20Abi } from "@src/contracts";
import useEvmContractApi from "./useEvmContractApi";
import { ethers } from "ethers";
import { useCallback, useMemo } from "react";
import { useSwapContext } from "@src/context";
import { Ecosystem } from "@src/models";

interface Props {
  rpcChainId: string | undefined;
  currentChainId?: string;
  signer?: ethers.Signer;
  tokenAddress?: string;
}

export const useERC20Token = ({
  rpcChainId,
  currentChainId,
  signer,
  tokenAddress,
}: Props) => {
  const evmContractApi = useEvmContractApi();
  const { supportedChains } = useSwapContext();

  const contract = useMemo(() => {
    const rpcUrl = supportedChains.find(
      (chain) =>
        chain.ecosystem === Ecosystem.EVM && chain.chainId === rpcChainId,
    )?.publicRpcUrls[0];
    if (rpcUrl && tokenAddress) {
      return new ethers.Contract(
        tokenAddress,
        ERC20Abi,
        signer && (!currentChainId || currentChainId === rpcChainId)
          ? signer
          : ethers.getDefaultProvider(rpcUrl),
      );
    }
    return null;
  }, [rpcChainId, currentChainId, signer, tokenAddress, supportedChains]);

  return {
    balanceOf: useCallback(
      async (address: string) => {
        return await evmContractApi.query(contract, "balanceOf", [address]);
      },
      [contract, evmContractApi],
    ),
    allowance: useCallback(
      async (address: string, allowedToSpendAddress: string) => {
        return await evmContractApi.query(contract, "allowance", [
          address,
          allowedToSpendAddress,
        ]);
      },
      [contract, evmContractApi],
    ),
    approve: useCallback(
      async (amount: string, allowedToSpendAddress: string) => {
        return await evmContractApi.execute(contract, "approve", [
          allowedToSpendAddress,
          amount,
        ]);
      },
      [contract, evmContractApi],
    ),
  };
};
