import { ArrowDownIcon, TokensIcon } from "@src/assets/icons";
import { Skeleton } from "@src/components";
import { useSwapContext } from "@src/context";
import { safeBigNumberFrom, weiToHumanReadable } from "@src/utils";
import { useEffect, useMemo, useState } from "react";
import { DeliveryInfo } from "./DeliveryInfo";
import { Fees } from "./Fees";
import { Ecosystem } from "@src/models";
import { Connection, PublicKey } from "@solana/web3.js";
import {
  CCIP_ROUTER_PROGRAM_ID,
  FEE_QUOTER_PROGRAM_ID,
  LINK_TOKEN_MINT,
  PROGRAM_ID,
  RMN_REMOTE_PROGRAM_ID,
  SOLANA_MAINNET_RPC_URL,
  SYSTEM_PROGRAM_ID,
} from "@src/constants";
import {
  AddressConversion,
  CCIPClient,
  CCIPContext,
  CCIPCoreConfig,
  CCIPProvider,
} from "@src/services/svm";
import { BN } from "@coral-xyz/anchor";
import { useWallet } from "@solana/wallet-adapter-react";
import useNetworks from "@src/hooks/networkManagement/useNetworks";

export const FeesPanel = () => {
  const [expanded, setExpanded] = useState(false);
  const [isFetchingSolanaFee, setIsFetchingSolanaFee] = useState(false);
  const [solanaBridgeFee, setSolanaBridgeFee] = useState<string | null>(null);

  const {
    route,
    feeToken,
    isFetchingRoute,
    srcChain,
    dstChain,
    srcToken,
    srcValueWei,
    bridgeUI,
  } = useSwapContext();

  const { publicKey } = useWallet();
  const {
    networks: {
      evm: { address: evmAddress },
    },
  } = useNetworks();

  useEffect(() => {
    const fetchSolanaBridgeFee = async () => {
      if (
        bridgeUI &&
        srcChain?.ecosystem === Ecosystem.SOLANA &&
        dstChain?.ccipChainId &&
        srcToken &&
        srcValueWei &&
        publicKey &&
        evmAddress
      ) {
        try {
          setIsFetchingSolanaFee(true);

          const connection = new Connection(
            SOLANA_MAINNET_RPC_URL,
            "confirmed",
          );

          const provider: CCIPProvider = {
            connection,
            wallet: null,
            getAddress() {
              return publicKey;
            },
            async signTransaction(tx) {
              return tx;
            },
          };

          const config: CCIPCoreConfig = {
            ccipRouterProgramId: CCIP_ROUTER_PROGRAM_ID,
            feeQuoterProgramId: FEE_QUOTER_PROGRAM_ID,
            tokenMint: new PublicKey(srcToken.address),
            rmnRemoteProgramId: RMN_REMOTE_PROGRAM_ID,
            linkTokenMint: LINK_TOKEN_MINT,
            nativeSol: PublicKey.default,
            systemProgramId: SYSTEM_PROGRAM_ID,
            programId: PROGRAM_ID,
          };

          const context: CCIPContext = {
            provider,
            config,
          };

          const client = new CCIPClient(context);

          const extraArgs = client.createExtraArgs({
            allowOutOfOrderExecution: true,
          });

          const receiver =
            AddressConversion.evmAddressToSolanaBytes(evmAddress);

          const feeRequest = {
            destChainSelector: new BN(dstChain.ccipChainId),
            message: {
              receiver: receiver,
              data: new Uint8Array(0),
              tokenAmounts: [
                {
                  token: new PublicKey(srcToken.address),
                  amount: new BN(srcValueWei.toString()),
                },
              ],
              feeToken: PublicKey.default,
              extraArgs: extraArgs,
            },
          };

          const feeResult = await client.getFee(feeRequest);
          const feeInLamports = feeResult.amount.toString();
          setSolanaBridgeFee(feeInLamports);

          const feeInSol = weiToHumanReadable({
            amount: feeInLamports,
            decimals: 9,
            precisionFractionalPlaces: 5,
          });
          setSolanaBridgeFee(feeInSol);
        } catch (error) {
          setSolanaBridgeFee(null);
        } finally {
          setIsFetchingSolanaFee(false);
        }
      } else {
        setSolanaBridgeFee(null);
      }
    };

    fetchSolanaBridgeFee();
  }, [
    bridgeUI,
    srcChain?.ecosystem,
    dstChain?.ccipChainId,
    srcToken?.address,
    srcValueWei,
    publicKey,
    evmAddress,
    srcToken,
  ]);

  const totalFee = useMemo(() => {
    if (!route) {
      return "0";
    }
    const totalWei = safeBigNumberFrom(route.xSwapFees.ccipFee || "0")
      .add(safeBigNumberFrom(route.xSwapFees.xSwapFee.nativeFee || "0"))
      .add(safeBigNumberFrom(route.xSwapFees.expressDeliveryFee || "0"))
      .toString();

    return weiToHumanReadable({
      amount: totalWei,
      decimals: feeToken?.decimals || 18,
      precisionFractionalPlaces: 5,
    });
  }, [feeToken?.decimals, route]);

  const isLoading =
    isFetchingRoute ||
    (srcChain?.ecosystem === Ecosystem.SOLANA &&
      bridgeUI &&
      isFetchingSolanaFee);

  return (
    <div className="flex flex-col x-border rounded-xl py-2 px-4 bg-t_bg_tertiary bg-opacity-5">
      <button
        aria-label={`${expanded ? "Collapse" : "Expand"} fees panel`}
        type="button"
        onClick={() => setExpanded((e) => !e)}
      >
        <div className="flex justify-between">
          <div className="flex gap-2 items-center text-xs font-medium sm:text-sm fill-t_text_primary">
            <TokensIcon />
            <p className="opacity-60">Fee: </p>
            {isLoading ? (
              <Skeleton className="w-[100px] h-full" />
            ) : (
              <p>{`${solanaBridgeFee ? solanaBridgeFee : totalFee} ${
                feeToken?.symbol || ""
              }`}</p>
            )}
          </div>
          <div className="flex gap-2 items-center fill-t_text_primary">
            {route && !isLoading && srcChain?.chainId !== dstChain?.chainId && (
              <DeliveryInfo />
            )}
            {expanded ? (
              <div className="w-4 h-2 rotate-180">
                <ArrowDownIcon />
              </div>
            ) : (
              <div className="w-4 h-2">
                <ArrowDownIcon />
              </div>
            )}
          </div>
        </div>
        {expanded && <Fees solanaBridgeFee={solanaBridgeFee} />}
      </button>
    </div>
  );
};
