/**
 * Smoke test: Comprehensive test of Tatum SDK integration with ChainID 138
 * 
 * This test verifies:
 * 1. RPC connectivity
 * 2. Chain ID verification
 * 3. Basic RPC calls
 * 4. Transaction signing (dry run)
 * 5. Contract interaction (if deployed)
 */

import { initTatumSDK, verifyConnection } from './tatum-client';
import { CHAIN_ID, CHAIN_NAME, DEFAULT_RPC_URL } from './config';
import { ethers } from 'ethers';

interface TestResult {
  name: string;
  passed: boolean;
  error?: string;
  details?: any;
}

async function runTest(name: string, testFn: () => Promise<any>): Promise<TestResult> {
  try {
    const result = await testFn();
    return {
      name,
      passed: true,
      details: result,
    };
  } catch (error) {
    return {
      name,
      passed: false,
      error: error instanceof Error ? error.message : String(error),
    };
  }
}

async function main() {
  console.log('='.repeat(70));
  console.log(`Smoke Test: ${CHAIN_NAME} (ChainID ${CHAIN_ID})`);
  console.log('='.repeat(70));
  console.log();
  
  const results: TestResult[] = [];
  
  // Test 1: Initialize Tatum SDK
  console.log('Test 1: Initializing Tatum SDK...');
  const tatum = await initTatumSDK({
    rpcUrl: DEFAULT_RPC_URL,
    verbose: false,
  });
  results.push(await runTest('Initialize Tatum SDK', async () => {
    if (!tatum) throw new Error('Tatum SDK initialization failed');
    return { initialized: true };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  // Test 2: Verify connection and chain ID
  console.log('Test 2: Verifying connection and chain ID...');
  results.push(await runTest('Verify Connection', async () => {
    return await verifyConnection(tatum);
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  if (results[results.length - 1].passed && results[results.length - 1].details) {
    const info = results[results.length - 1].details;
    console.log(`  Chain ID: ${info.chainId}, Block: ${info.blockNumber}`);
  }
  
  // Test 3: Test basic RPC calls
  console.log('Test 3: Testing basic RPC calls...');
  results.push(await runTest('RPC: eth_blockNumber', async () => {
    const blockNumber = await tatum.rpc.request('eth_blockNumber', []);
    return { blockNumber };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  results.push(await runTest('RPC: eth_chainId', async () => {
    const chainId = await tatum.rpc.request('eth_chainId', []);
    const chainIdDecimal = parseInt(chainId as string, 16);
    if (chainIdDecimal !== CHAIN_ID) {
      throw new Error(`Chain ID mismatch: expected ${CHAIN_ID}, got ${chainIdDecimal}`);
    }
    return { chainId: chainIdDecimal };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  results.push(await runTest('RPC: eth_gasPrice', async () => {
    const gasPrice = await tatum.rpc.request('eth_gasPrice', []);
    return { gasPrice };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  results.push(await runTest('RPC: net_peerCount', async () => {
    const peerCount = await tatum.rpc.request('net_peerCount', []);
    return { peerCount: parseInt(peerCount as string, 16) };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  // Test 4: Test ethers.js provider
  console.log('Test 4: Testing ethers.js provider...');
  results.push(await runTest('Ethers: Provider Initialization', async () => {
    const provider = new ethers.JsonRpcProvider(DEFAULT_RPC_URL, {
      chainId: CHAIN_ID,
      name: 'defi-oracle-mainnet',
    });
    const network = await provider.getNetwork();
    if (Number(network.chainId) !== CHAIN_ID) {
      throw new Error(`Chain ID mismatch: expected ${CHAIN_ID}, got ${Number(network.chainId)}`);
    }
    return { chainId: Number(network.chainId), name: network.name };
  }));
  console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  
  // Test 5: Test transaction signing (dry run)
  console.log('Test 5: Testing transaction signing (dry run)...');
  if (process.env.PRIVATE_KEY) {
    results.push(await runTest('Ethers: Transaction Signing', async () => {
      const provider = new ethers.JsonRpcProvider(DEFAULT_RPC_URL, {
        chainId: CHAIN_ID,
        name: 'defi-oracle-mainnet',
      });
      const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
      
      // Create a transaction (but don't send it)
      const tx = await wallet.populateTransaction({
        to: '0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb',
        value: ethers.parseEther('0.001'),
        chainId: CHAIN_ID,
      });
      
      // Verify chainId is set correctly
      if (tx.chainId !== BigInt(CHAIN_ID)) {
        throw new Error(`Transaction chainId mismatch: expected ${CHAIN_ID}, got ${tx.chainId}`);
      }
      
      return { chainId: Number(tx.chainId), to: tx.to, value: tx.value?.toString() };
    }));
    console.log(results[results.length - 1].passed ? '✓' : '✗', results[results.length - 1].name);
  } else {
    console.log('⚠ Skipping transaction signing test (PRIVATE_KEY not set)');
  }
  
  // Summary
  console.log();
  console.log('='.repeat(70));
  console.log('Test Summary');
  console.log('='.repeat(70));
  
  const passed = results.filter(r => r.passed).length;
  const failed = results.filter(r => !r.passed).length;
  
  console.log(`Total Tests: ${results.length}`);
  console.log(`Passed: ${passed}`);
  console.log(`Failed: ${failed}`);
  console.log();
  
  if (failed > 0) {
    console.log('Failed Tests:');
    results.filter(r => !r.passed).forEach(r => {
      console.log(`  ✗ ${r.name}: ${r.error}`);
    });
    console.log();
  }
  
  console.log('='.repeat(70));
  
  if (failed === 0) {
    console.log('✓ All tests passed!');
    process.exit(0);
  } else {
    console.log('✗ Some tests failed');
    process.exit(1);
  }
}

main().catch((error) => {
  console.error('Fatal error:', error);
  process.exit(1);
});

