import { openTxConfigForm } from "@src/components";
import { Chain, ModalIntegrationPayload, Web3Environment } from "@src/models";
import { getChains } from "@src/services";
import { isETHAddressValid } from "@src/utils";

export const openTransactionModal = async ({
  integratorId,
  dstChain,
  dstToken,
  srcChain,
  srcToken,
  customContractCalls = [],
  desc,
  dstDisplayToken,
  lightTheme,
  defaultWalletPicker,
  styles,
  onPendingTransactionsChange,
  dstTokenLocked,
  dstChainLocked,
  srcTokenLocked,
  srcChainLocked,
  onDstTokenChange,
  onDstChainChange,
  onSrcTokenChange,
  onSrcChainChange,
  bridge,
  highlightedDstTokens,
}: ModalIntegrationPayload) => {
  const supportedChains: Chain[] = (await getChains()).filter(
    ({ web3Environment, swapSupported }) =>
      web3Environment === Web3Environment.MAINNET && swapSupported,
  );

  validateSwapTxData(
    integratorId,
    supportedChains,
    dstChain,
    dstToken,
    srcChain,
    srcToken,
  );

  await openTxConfigForm({
    integratorId,
    dstChainId: dstChain,
    dstTokenAddr: dstToken,
    srcChainId: srcChain,
    srcTokenAddr: srcToken,
    customContractCalls,
    desc,
    dstDisplayTokenAddr: dstDisplayToken,
    supportedChains,
    lightTheme,
    defaultWalletPicker,
    styles,
    onPendingTransactionsChange,
    dstTokenLocked,
    dstChainLocked,
    srcTokenLocked,
    srcChainLocked,
    onDstTokenChange,
    onDstChainChange,
    onSrcTokenChange,
    onSrcChainChange,
    bridge,
    highlightedDstTokens,
  });
};

const validateSwapTxData = (
  integratorId: string,
  supportedChains: Chain[],
  dstChain?: string,
  dstToken?: string,
  srcChain?: string,
  srcToken?: string,
) => {
  if (!integratorId) {
    throw new Error(
      "Provide integratorId or contact the team to generate one.",
    );
  }

  if (dstChain) {
    const supportedDstChain = supportedChains.find(
      ({ chainId }) => chainId === dstChain,
    );
    if (!supportedDstChain) {
      throw new Error(`Provided chain '${dstChain}' is not supported`);
    }
    if (dstToken && !isETHAddressValid(dstToken)) {
      throw new Error(
        `Provided token address ${dstToken} on chain ${dstChain} is invalid`,
      );
    }
  }

  if (srcChain) {
    const supportedSrcChain = supportedChains.find(
      ({ chainId }) => chainId === srcChain,
    );
    if (!supportedSrcChain) {
      throw new Error(`Provided chain '${srcChain}' is not supported`);
    }
    if (srcToken && !isETHAddressValid(srcToken)) {
      throw new Error(
        `Provided token address ${srcToken} on chain ${srcChain} is invalid`,
      );
    }
  }
};
