// ============================================================================
// WORKFLOW BUSINESS LOGIC - EDIT THIS FILE TO CUSTOMIZE
// ============================================================================
// This file is NOT minified and can be freely edited.
//
// Available globals (injected by workflow.js):
//   - Input: workflow input configuration object (loaded from config.json)
//   - node: node utilities { log(msg), done(result) }
//   - Invoker: service invoker for calling external services
//   - invoke(callSite, service, method, params): helper to invoke services
//
// Example:
//   const result = await invoke('myCallsite', 'twitter', 'postTweet', { text: 'Hello' });
//   node.log(result);
//   node.done({ success: true });
//
// ============================================================================

// ===== YOUR WORKFLOW CODE BELOW =====

const config = Input;

const invoke = new Invoker(config, node);

// Parse configuration
const tokenAddress = config.tokenAddress;
const buyAmount = config.buyAmount;
const sellDelaySeconds = Number(config.sellDelaySeconds || 10);
const loopCount = Number(config.loopCount || 1);
const loopIntervalSeconds = Number(config.loopIntervalSeconds || 5);
const apiKey = config.o1exchange_apiKey;
const signerAddress = config.signerAddress;
const slippageBps = Number(config.slippageBps || 100);

// Validate required fields
if (!tokenAddress || !buyAmount || !apiKey || !signerAddress) {
  throw new Error('Missing required config: tokenAddress, buyAmount, o1exchange_apiKey, or signerAddress');
}

// Sign callbacks for o1exchange createOrder (single-method flow)
const signTypedDataFn = async (domain, types, primaryType, message) => {
  node.log('Signing Permit2 EIP-712 via humanInTheLoop');
  const result = await invoke('awaitSignTypedDataPermit2', 'humanInTheLoop', 'awaitSignTypedData', {
    account: signerAddress,
    domain,
    types,
    message,
    primaryType
  });
  return { signature: result.signature };
};

const signTransactionFn = async (transaction) => {
  node.log('Signing transaction via humanInTheLoop');
  const valueHex = transaction.value !== undefined && transaction.value !== null ? (typeof transaction.value === 'bigint' ? '0x' + transaction.value.toString(16) : String(transaction.value)) : '0x0';
  const signParams = {
    from: signerAddress,
    to: transaction.to,
    chainType: 'base',
    data: transaction.data,
    value: valueHex,
    gas: transaction.gas?.toString(),
    gasPrice: transaction.gasPrice?.toString(),
    maxFeePerGas: transaction.maxFeePerGas?.toString(),
    maxPriorityFeePerGas: transaction.maxPriorityFeePerGas?.toString(),
    nonce: transaction.nonce?.toString(),
    isSubmit: false
  };
  const signResult = await invoke('awaitSignTransactionEvm', 'humanInTheLoop', 'awaitSignTransaction', signParams);
  return { signed: signResult.signature };
};

let currentLoop = 0;

const wait = (seconds) => new Promise((resolve) => setTimeout(resolve, seconds * 1000));

const runLoop = async () => {
  try {
    currentLoop++;
    node.log(`Starting loop ${currentLoop}/${loopCount}`);

    // Buy: single createOrder call
    node.log(`Creating buy order for ${buyAmount} ETH, token ${tokenAddress}`);
    // @ts-ignore
    const buyResult = await invoke('createOrderBuy', 'o1exchange', 'createOrder', {
      signerAddress,
      tokenAddress,
      amount: buyAmount,
      side: 'buy',
      apiKey,
      signTypedDataFn,
      signTransactionFn,
      slippageBps,
      networkId: 8453
    });
    if (!buyResult.success) {
      throw new Error(`Buy order failed: ${buyResult.message || 'Unknown error'}`);
    }
    node.log(`Buy order submitted successfully`);

    node.log(`Waiting ${sellDelaySeconds} seconds before selling...`);
    await wait(sellDelaySeconds);

    // Sell: get balance then single createOrder call
    node.log(`Getting token balance for ${tokenAddress}`);
    const balanceResult = await invoke('getTokenBalance', 'chainKit', 'getTokenBalance', {
      tokenAddress,
      ownerAddress: signerAddress,
      chainType: 'base'
    });
    const tokenBalance = balanceResult.balance;
    if (!tokenBalance || tokenBalance === '0' || parseFloat(tokenBalance) <= 0) {
      node.log(`No token balance to sell, skipping sell phase in loop ${currentLoop}`);
    } else {
      node.log(`Creating sell order for ${tokenBalance} tokens`);
      // @ts-ignore
      const sellResult = await invoke('createOrderSell', 'o1exchange', 'createOrder', {
        signerAddress,
        tokenAddress,
        amount: tokenBalance,
        side: 'sell',
        apiKey,
        signTypedDataFn,
        signTransactionFn,
        slippageBps,
        networkId: 8453
      });
      if (!sellResult.success) {
        throw new Error(`Sell order failed: ${sellResult.message || 'Unknown error'}`);
      }
      node.log(`Sell order submitted successfully`);
    }

    node.log(`Completed loop ${currentLoop}/${loopCount}`);

    if (currentLoop < loopCount) {
      node.log(`Waiting ${loopIntervalSeconds} seconds before next loop...`);
      await wait(loopIntervalSeconds);
      setTimeout(runLoop, 0);
    } else {
      node.log(`All ${loopCount} loops completed`);
      node.done({ message: 'done', loopCount, completed: true });
    }
  } catch (err) {
    const errorMessage = err instanceof Error ? err.message : String(err);
    node.error(errorMessage);
    node.done({
      message: 'done',
      loopCount,
      completed: false,
      error: errorMessage,
      completedLoops: currentLoop
    });
  }
};

runLoop();
node.log(`Started o1exchange buy-sell loop: ${loopCount} loops, ${sellDelaySeconds}s sell delay, ${loopIntervalSeconds}s loop interval`);


// ===== WORKFLOW CODE END =====
