import { 
  getLatestBlocks, 
  getLatestBlockNumber, 
  getBlockByNumber,
  formatNumber,
  parseHexToDecimal,
  formatRelativeTime,
  calculateGasPercentage,
  formatGasValue,
  truncateString
} from '../src';

// Import FormattedBlock type to properly handle the block data
import { FormattedBlock } from '../src/modules/blocks/utils';

/**
 * Display blocks in a card-like format
 */
async function displayBlocks() {
  try {
    console.log('\n🔍 Fetching latest blocks from Exatechl2 blockchain...');

    // Pagination parameters
    const page = 1;
    const perPage = 10;
    const includeTransactions = false;

    // Get paginated blocks from the blockchain explorer
    const { blocks, totalCount, totalPages } = await getLatestBlocks(page, perPage, includeTransactions);

    // Format and display block data
    console.log(`\n📊 Latest Blocks (Page ${page}/${totalPages}, Total: ${formatNumber(totalCount)})`);
    console.log('Block\tAge\tTxn\tSize\tGas Used\tGas Limit\tBase Fee\tBatch ID\tStatus');
    
    blocks.forEach((block: FormattedBlock, index) => {
      // Get proper relative time
      const relativeTime = formatRelativeTime(block.timestamp).split(' ').slice(0, 3).join(' ');
      
      // Format gas values
      const gasUsed = formatNumber(parseInt(block.gasUsed || '0'));
      const gasPercentage = block.gasUsedPercentage !== undefined ? `(${block.gasUsedPercentage.toFixed(1)}%)` : '(0%)';
      const gasLimit = formatNumber(parseInt(block.gasLimit || '0'));
      
      // Format base fee with Gwei unit
      const baseFee = block.baseFee ? `${block.baseFee} Gwei` : 'N/A';
      
      // Format batch ID with # prefix
      const batchId = block.batchId ? `#${block.batchId}` : 'N/A';
      
      // Format status with capitalization
      const status = block.status ? block.status.charAt(0).toUpperCase() + block.status.slice(1).toLowerCase() : 'N/A';
      
      // Print block in card-like format
      console.log(`${block.numberDecimal}`);
      console.log(`${relativeTime}`);
      console.log(`${block.txCount || 0}\t${block.size || 'N/A'}`);
      console.log(`${gasUsed}`);
      console.log(`${gasPercentage}`);
      console.log(`${gasLimit}`);
      console.log(`${baseFee}`);
      console.log(`${batchId}`);
      console.log(`${status}`);
      
      // Add separator between blocks if not the last one
      if (index < blocks.length - 1) {
        console.log('─'.repeat(40));
      }
    });
    
    console.log(`\nShowing ${blocks.length} of ${formatNumber(totalCount)} blocks\n`);

    // Get the very latest block from the chain using RPC
    const latestBlockNumber = await getLatestBlockNumber();
    console.log(`🔴 Latest block via RPC: #${parseHexToDecimal(latestBlockNumber)}`);

    // Get detailed information about the latest block
    const blockDetails = await getBlockByNumber(latestBlockNumber, true);
    
    // Format the values for display
    const gasUsed = parseHexToDecimal(blockDetails.gasUsed || '0x0');
    const gasLimit = parseHexToDecimal(blockDetails.gasLimit || '0x0');
    const gasPercentage = calculateGasPercentage(blockDetails.gasUsed, blockDetails.gasLimit);
    const baseFeePerGas = formatGasValue(blockDetails.baseFeePerGas || '0x0', 'gwei', 2);
    
    console.log('\n📋 Latest Block Details:');
    console.log('  Block Number:', parseHexToDecimal(blockDetails.number));
    console.log('  Hash:', blockDetails.hash);
    console.log('  Timestamp:', formatRelativeTime(blockDetails.timestamp));
    console.log('  Transactions:', blockDetails.transactions.length);
    console.log('  Gas Used:', formatNumber(gasUsed), `(${gasPercentage.toFixed(1)}%)`);
    console.log('  Gas Limit:', formatNumber(gasLimit));
    console.log('  Base Fee Per Gas:', baseFeePerGas);
    console.log('  Batch ID:', blockDetails.batchId ? `#${blockDetails.batchId}` : 'N/A');
    
    const status = blockDetails.status || blockDetails.batchStatus || 'N/A';
    console.log('  Status:', status.charAt(0).toUpperCase() + status.slice(1).toLowerCase());
    console.log('  Miner/Validator:', blockDetails.miner || blockDetails.validator || 'Unknown');
    
    if (blockDetails.transactions.length > 0) {
      console.log('\n💰 First 3 Transactions:');
      blockDetails.transactions.slice(0, 3).forEach((tx, index) => {
        if (typeof tx === 'string') {
          console.log(`  ${index + 1}. ${tx}`);
        } else {
          console.log(`  ${index + 1}. ${tx.hash} (From: ${truncateString(tx.from, 6, 4)} To: ${tx.to ? truncateString(tx.to, 6, 4) : 'Contract Creation'})`);
        }
      });
    }

  } catch (error) {
    console.error('❌ Error fetching blocks:', error);
  }
}

/**
 * Function to watch for new blocks in real-time
 */
async function watchBlocks(duration = 60000, interval = 5000) {
  try {
    console.log(`\n⏱️  Watching for new blocks for ${duration/1000} seconds...`);
    
    let lastBlockNumber = await getLatestBlockNumber();
    console.log(`Starting at block #${parseHexToDecimal(lastBlockNumber)}`);
    
    const endTime = Date.now() + duration;
    
    const intervalId = setInterval(async () => {
      try {
        const currentBlockNumber = await getLatestBlockNumber();
        
        if (currentBlockNumber !== lastBlockNumber) {
          console.log(`New block detected: #${parseHexToDecimal(currentBlockNumber)}`);
          
          // Get block details
          const block = await getBlockByNumber(currentBlockNumber, false);
          
          // Format the values
          const gasUsed = parseHexToDecimal(block.gasUsed || '0x0');
          const gasLimit = parseHexToDecimal(block.gasLimit || '0x0');
          const gasPercentage = calculateGasPercentage(block.gasUsed, block.gasLimit);
          const status = block.status || block.batchStatus || 'N/A';
          const statusFormatted = status.charAt(0).toUpperCase() + status.slice(1).toLowerCase();
          
          console.log(`  Timestamp: ${formatRelativeTime(block.timestamp)}`);
          console.log(`  Transactions: ${block.transactions.length}`);
          console.log(`  Gas Used: ${formatNumber(gasUsed)} (${gasPercentage.toFixed(1)}%)`);
          console.log(`  Gas Limit: ${formatNumber(gasLimit)}`);
          console.log(`  Batch ID: ${block.batchId ? `#${block.batchId}` : 'N/A'}`);
          console.log(`  Status: ${statusFormatted}`);
          
          lastBlockNumber = currentBlockNumber;
        }
        
        if (Date.now() >= endTime) {
          clearInterval(intervalId);
          console.log('\n⏹️  Block watching complete');
        }
      } catch (error) {
        console.error('  Error checking for new blocks:', error);
      }
    }, interval);
    
    // Allow the function to complete after duration
    await new Promise(resolve => setTimeout(resolve, duration + 100));
    
  } catch (error) {
    console.error('❌ Error watching blocks:', error);
  }
}

// Main function to run example
async function main() {
  console.log('='.repeat(120));
  console.log('📚 BLOCKCHAIN-API EXAMPLE: LIST BLOCKS');
  console.log('='.repeat(120));
  
  await displayBlocks();
  
  // Uncomment to watch for new blocks in real-time
  // await watchBlocks(30000); // Watch for 30 seconds
  
  console.log('\n✅ Example complete');
}

// Run the example
main().catch(console.error); 