import { VenicePlugin } from '../index';
import dotenv from 'dotenv';
import { ethers } from 'ethers';
import readline from 'readline';

// Load environment variables
dotenv.config();

// Create readline interface for user input
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

// Prompt function that returns a promise
function prompt(question: string): Promise<string> {
  return new Promise((resolve) => {
    rl.question(question, (answer) => {
      resolve(answer);
    });
  });
}

async function main() {
  try {
    // Check for required environment variables
    if (!process.env.PRIVATE_KEY) {
      console.error('Error: PRIVATE_KEY environment variable is required');
      return;
    }

    const venicePlugin = new VenicePlugin({
      rpcUrl: "https://mainnet.base.org",
      privateKey: process.env.PRIVATE_KEY,
      stakingContractAddress: process.env.STAKING_CONTRACT_ADDRESS || '0x321b7ff75154472B18EDb199033fF4D116F340Ff'
    });

    await venicePlugin.initialize();
    console.log('Plugin initialized successfully');

    const provider = new ethers.JsonRpcProvider("https://mainnet.base.org");
    const wallet = new ethers.Wallet(process.env.PRIVATE_KEY, provider);
    const userAddress = wallet.address;
    console.log(`Connected wallet address: ${userAddress}`);

    // Check VVV token balance
    const tokenBalance = await venicePlugin.getTokenBalance(userAddress);
    if (tokenBalance.success) {
      console.log(`\nVVV Token Balance: ${tokenBalance.data.formatted} VVV`);
    } else {
      console.error(`Failed to get token balance: ${tokenBalance.error}`);
    }

    // Check staking allowance
    const allowance = await venicePlugin.checkAllowance(userAddress);
    if (allowance.success) {
      console.log(`Staking Allowance: ${allowance.data.formatted} VVV`);
    } else {
      console.error(`Failed to get allowance: ${allowance.error}`);
    }

    try {
      // Display user staking information
      const userInfo = await venicePlugin.getUserStakeInfo(userAddress);
      if (userInfo.success) {
        console.log('\nYour staking information:');
        console.log(`- Staked amount: ${userInfo.data.stakeAmount} VVV`);
        console.log(`- Pending rewards: ${userInfo.data.pendingRewards} VVV`);
        console.log(`- Cooldown amount: ${userInfo.data.stakeInfo.cooldownAmount} VVV`);
        
        const cooldownEnd = Number(userInfo.data.stakeInfo.cooldownEnd);
        if (cooldownEnd > 0) {
          const now = Math.floor(Date.now() / 1000);
          if (cooldownEnd > now) {
            console.log(`- Cooldown ends: ${new Date(cooldownEnd * 1000).toISOString()} (${(cooldownEnd - now) / 86400} days remaining)`);
          } else {
            console.log(`- Cooldown ended: ${new Date(cooldownEnd * 1000).toISOString()} (ready to finalize)`);
          }
        } else {
          console.log('- No active cooldown');
        }
      } else {
        console.error(`Failed to get user info: ${userInfo.error}`);
      }
    } catch (error) {
      console.error(`Error fetching staking info: ${error instanceof Error ? error.message : String(error)}`);
    }

    // Display menu and handle user choice
    while (true) {
      console.log('\n--- Venice Staking Operations ---');
      console.log('1. Approve VVV tokens for staking');
      console.log('2. Stake tokens');
      console.log('3. Initiate unstaking');
      console.log('4. Finalize unstaking');
      console.log('5. Claim rewards');
      console.log('6. View staking statistics');
      console.log('7. Check VVV balance and allowance');
      console.log('8. Exit');

      const choice = await prompt('Select an option (1-8): ');

      switch (choice) {
        case '1': {
          // Approve tokens
          const amount = await prompt('Enter amount to approve (or "max" for maximum): ');
          let approveAmount = '0';
          
          if (amount.toLowerCase() === 'max') {
            // Use a very large number for unlimited approval
            approveAmount = '115792089237316195423570985008687907853269984665640564039457584007913129639935';
          } else {
            approveAmount = amount;
          }
          
          const approveResult = await venicePlugin.approveStaking(approveAmount);
          
          if (approveResult.success) {
            console.log(`Approval successful! Transaction hash: ${approveResult.transactionHash}`);
          } else {
            console.error(`Approval failed: ${approveResult.error}`);
          }
          break;
        }
        
        case '2': {
          // Stake tokens
          const amount = await prompt('Enter amount to stake: ');
          const recipient = await prompt('Enter recipient address (leave empty for self): ');
          
          // Check allowance first
          const allowanceCheck = await venicePlugin.checkAllowance(userAddress);
          if (allowanceCheck.success) {
            const amountToStake = ethers.parseUnits(amount, 18);
            if (allowanceCheck.data.raw < amountToStake) {
              console.log(`Insufficient allowance. Current: ${allowanceCheck.data.formatted}, Required: ${amount}`);
              const shouldApprove = await prompt('Would you like to approve tokens now? (y/n): ');
              
              if (shouldApprove.toLowerCase() === 'y') {
                const approveResult = await venicePlugin.approveStaking(amount);
                if (!approveResult.success) {
                  console.error(`Approval failed: ${approveResult.error}`);
                  break;
                }
                console.log(`Approval successful! Transaction hash: ${approveResult.transactionHash}`);
              } else {
                break;
              }
            }
          }
          
          // Now stake
          const stakeResult = await venicePlugin.stake(
            recipient || userAddress,
            amount
          );
          
          if (stakeResult.success) {
            console.log(`Staked successfully! Transaction hash: ${stakeResult.transactionHash}`);
          } else {
            console.error(`Staking failed: ${stakeResult.error}`);
          }
          break;
        }
        
        case '3': {
          // Initiate unstaking
          const amount = await prompt('Enter amount to unstake: ');
          
          const initiateResult = await venicePlugin.initiateUnstake(amount);
          
          if (initiateResult.success) {
            console.log(`Unstaking initiated successfully! Transaction hash: ${initiateResult.transactionHash}`);
            console.log('You will need to wait for the cooldown period before finalizing.');
          } else {
            console.error(`Initiating unstake failed: ${initiateResult.error}`);
          }
          break;
        }
        
        case '4': {
          // Finalize unstaking
          const finalizeResult = await venicePlugin.finalizeUnstake();
          
          if (finalizeResult.success) {
            console.log(`Unstaking finalized successfully! Transaction hash: ${finalizeResult.transactionHash}`);
          } else {
            console.error(`Finalizing unstake failed: ${finalizeResult.error}`);
          }
          break;
        }
        
        case '5': {
          // Claim rewards
          const claimResult = await venicePlugin.claim();
          
          if (claimResult.success) {
            console.log(`Rewards claimed successfully! Transaction hash: ${claimResult.transactionHash}`);
          } else {
            console.error(`Claiming rewards failed: ${claimResult.error}`);
          }
          break;
        }
        
        case '6': {
          // View staking statistics
          const stats = await venicePlugin.getStakingStats();
          if (stats.success) {
            console.log('\nStaking contract statistics:');
            console.log(`- Total staked: ${stats.data.totalStaked} VVV`);
            console.log(`- Emission rate: ${stats.data.emissionRate} VVV per second`);
            console.log(`- Cooldown duration: ${Number(stats.data.cooldownDuration) / 86400} days`);
            console.log(`- Venice percentage: ${stats.data.venicePercentage}`);
          } else {
            console.error(`Failed to get staking stats: ${stats.error}`);
          }
          break;
        }
        
        case '7': {
          // Check VVV balance and allowance
          const [balance, allowance] = await Promise.all([
            venicePlugin.getTokenBalance(userAddress),
            venicePlugin.checkAllowance(userAddress)
          ]);
          
          console.log('\nVVV Token Information:');
          if (balance.success) {
            console.log(`- Balance: ${balance.data.formatted} VVV`);
          } else {
            console.error(`- Failed to get balance: ${balance.error}`);
          }
          
          if (allowance.success) {
            console.log(`- Staking Allowance: ${allowance.data.formatted} VVV`);
          } else {
            console.error(`- Failed to get allowance: ${allowance.error}`);
          }
          break;
        }
        
        case '8': {
          // Exit
          console.log('Exiting...');
          await venicePlugin.cleanup();
          rl.close();
          return;
        }
        
        default:
          console.log('Invalid option. Please try again.');
      }
    }
  } catch (error) {
    console.error('Error in staking operations:', error);
  } finally {
    rl.close();
  }
}

// Run the example
main().catch(console.error); 