import { EtherspotBundler, ModularSdk, SessionKeyValidator, KeyStore } from '@etherspot/modular-sdk';
import * as dotenv from 'dotenv';

dotenv.config();

const secondsInAMonth = 30 * 24 * 60 * 60; // 2592000 seconds

async function main() {
  const bundlerApiKey = process.env.API_KEY as string;
  const walletPrivateKey = process.env.WALLET_PRIVATE_KEY as string;
  const chainId = Number(process.env.CHAIN_ID);

  // initializating sdk...
  const modularSdk = new ModularSdk({ privateKey: walletPrivateKey },
    {
      chainId: chainId,
      bundlerProvider: new EtherspotBundler(chainId, bundlerApiKey)
    })

  console.log('address: ', modularSdk.state.EOAAddress);

  // get address of EtherspotWallet
  const address: string = await modularSdk.getCounterFactualAddress();

  console.log('\x1b[33m%s\x1b[0m', `EtherspotWallet address: ${address}`);

  const token = process.env.TOKEN_ADDRESS as string;
  const functionSelector = process.env.FUNCTION_SELECTOR as string;
  const spendingLimit = '1000000000000000000000';
  const validAfter = getEpochTimeInSeconds() + 31; // 10 seconds from now
  const validUntil = getEpochTimeInSeconds() + secondsInAMonth;

  console.log(`validAfter: ${validAfter} validUntil: ${validUntil}`);

  // get instance  of SessionKeyValidator
  const sessionKeyModule = await SessionKeyValidator.create(
    modularSdk,
    new EtherspotBundler(chainId, bundlerApiKey)
  )

  const response = await sessionKeyModule.enableSessionKey(
    token,
    functionSelector,
    spendingLimit,
    validAfter,
    validUntil,
    KeyStore.AWS
  );

  console.log('\x1b[33m%s\x1b[0m', `UserOpHash: `, response.userOpHash);
  console.log('\x1b[33m%s\x1b[0m', `SessionKey: `, response.sessionKey);

  // get transaction hash...
  console.log('Waiting for transaction...');
  let userOpsReceipt = null;
  const timeout = Date.now() + 60000; // 1 minute timeout
  while ((userOpsReceipt == null) && (Date.now() < timeout)) {
    await sleep(2);
    userOpsReceipt = await modularSdk.getUserOpReceipt(response.userOpHash);
  }
  console.log('\x1b[33m%s\x1b[0m', `Transaction Receipt: `, userOpsReceipt);

  const sessionKeys = await sessionKeyModule.getAssociatedSessionKeys();
  console.log('\x1b[33m%s\x1b[0m', `AssociatedSessionKeys: `, sessionKeys);

  const sessionData = await sessionKeyModule.sessionData(response.sessionKey);
  console.log('\x1b[33m%s\x1b[0m', `SessionData: `, sessionData);
}

const getEpochTimeInSeconds = () => Math.floor(new Date().getTime() / 1000);