import SyncSwapSDK from "@syncswap/sdk";
import { BigNumber } from "ethers";
import { Provider, Wallet } from "zksync-web3";

const PRIVATE_KEY = process.env.PRIVATE_KEY;

async function swapExample() {
  const provider = new Provider("https://rpc.sophon.xyz");
  const signer = new Wallet(PRIVATE_KEY!, provider);
  const sdk = new SyncSwapSDK({ network: "sophonMainnet", enablePaymaster: false });

  await sdk.initialize(signer);

  // get current network tokens
  // const tokens = await sdk.getAllTokens();

  const SOPHON_MAINNET_USDC = "0x9aa0f72392b5784ad86c6f3e899bcc053d00db4f";
  const SOPHON_MAINNET_ETH = "0x72af9f169b619d85a47dfa8fefbcd39de55c567d";
  const tokenIn = SOPHON_MAINNET_USDC;
  const tokenOut = SOPHON_MAINNET_ETH;
  const amountIn = BigNumber.from("10000"); // Amount to swap
  const account = await signer.getAddress();
  const to = account; // Address to receive output tokens
  // step1, fetch swap route pool data, can be cached for later use

  console.log("Fetching swap route pools...");
  // Get route
  const routePools = await sdk.fetchSyncSwapRouteData(
    tokenIn,
    tokenOut,
    account
  );
  if (!routePools) {
    throw new Error("No route pools found for the given tokens");
  }
  console.log("Route pools fetched successfully:", routePools);

  const route = await sdk.calculateSyncSwapRoute(
    routePools,
    tokenIn,
    tokenOut,
    amountIn
  );

  let permitSignature;

  // Try to use permit for gasless approval (cached after first check)
  const permitData = await sdk.getTokenPermitData(tokenIn);
  if (permitData) {
    console.log("Token supports permit! Using gasless approval...");

    // Sign permit instead of sending approval transaction
    permitSignature = await sdk.signPermit(
      tokenIn,
      amountIn,
      undefined // Will use default router address
    );

    if (permitSignature) {
      console.log("Permit signature created successfully");
    }
  }

  // Fallback to regular approval if permit is not available or failed
  if (!permitSignature) {
    const approved = await sdk.checkApproval(tokenIn, amountIn);
    if (!approved) {
      console.log("Token doesn't support permit, using regular approval...");
      const approveTx = await sdk.approve(tokenIn, amountIn);
      await signer.sendTransaction(approveTx);
      console.log("Approval transaction sent");
    }
  }

  // Execute swap with permit signature (or null if not available)
  const swapTx = await sdk.swapExactInput(route, permitSignature, to);

  // // estimate gas
  // const gas = await signer.estimateGas(swapTx);
  // console.log("Gas estimate:", gas.toString());

  const tx = await signer.sendTransaction(swapTx);
  console.log("Swap transaction sent:", tx.hash);

  const receipt = await tx.wait();
  console.log("Swap completed!", receipt);
}

async function main() {
  // If private key is available, also run swap example
  if (PRIVATE_KEY) {
    console.log("\n=== Starting Swap Example ===");
    await swapExample();
  } else {
    console.log("\nNote: Set PRIVATE_KEY environment variable to run swap example");
  }
}

main()
  .then(() => console.log("Example completed successfully"))
  .catch((error) => {
    console.error("Error in example:", error);
    process.exit(1);
  });
