#!/usr/bin/env node
require('dotenv').config();
const { Connection, Keypair, PublicKey } = require('@solana/web3.js');

async function testDriftAccount() {
  console.log('🔍 Comprehensive Drift Account Analysis\n');
  
  try {
    // Setup
    const secret = process.env.SOLANA_PRIVATE_KEY;
    const keypair = Keypair.fromSecretKey(Buffer.from(JSON.parse(secret)));
    const connection = new Connection(process.env.SOLANA_RPC_URL || 'https://api.mainnet-beta.solana.com', 'confirmed');
    
    console.log('🔑 Wallet public key:', keypair.publicKey.toString());
    
    // Check SOL balance
    const balance = await connection.getBalance(keypair.publicKey);
    console.log('💰 SOL balance:', (balance / 1e9).toFixed(6), 'SOL\n');
    
    // Test multiple PDA calculation methods
    const DRIFT_PROGRAM_ID = 'dRiftyHA39MWEi3m9aunc5MzRF1JYuBsbn6VPcn33UH';
    
    console.log('📊 Testing different PDA calculation methods:\n');
    
    // Method 1: Manual calculation (what check-drift-account.js uses)
    console.log('1️⃣ Manual PDA calculation:');
    const [userAccountPDA1] = await PublicKey.findProgramAddress(
      [
        Buffer.from('user'),
        keypair.publicKey.toBuffer(),
        Buffer.from([0]) // subAccountId = 0
      ],
      new PublicKey(DRIFT_PROGRAM_ID)
    );
    console.log('   PDA:', userAccountPDA1.toString());
    
    const accountInfo1 = await connection.getAccountInfo(userAccountPDA1);
    console.log('   Exists:', !!accountInfo1);
    if (accountInfo1) {
      console.log('   Data length:', accountInfo1.data.length);
      console.log('   Owner:', accountInfo1.owner.toString());
    }
    
    // Method 2: Try using the Drift SDK's getUserAccountPublicKey function
    console.log('\n2️⃣ SDK PDA calculation:');
    try {
      // Import the getUserAccountPublicKey function from Drift SDK
      const { getUserAccountPublicKey } = require('@drift-labs/sdk');
      
      const userAccountPDA2 = await getUserAccountPublicKey(
        new PublicKey(DRIFT_PROGRAM_ID),
        keypair.publicKey,
        0
      );
      console.log('   PDA:', userAccountPDA2.toString());
      console.log('   Same as manual?', userAccountPDA1.equals(userAccountPDA2));
      
      const accountInfo2 = await connection.getAccountInfo(userAccountPDA2);
      console.log('   Exists:', !!accountInfo2);
      if (accountInfo2) {
        console.log('   Data length:', accountInfo2.data.length);
        console.log('   Owner:', accountInfo2.owner.toString());
      }
    } catch (sdkError) {
      console.log('   ❌ SDK method failed:', sdkError.message);
    }
    
    // Method 3: Try with different subaccount IDs
    console.log('\n3️⃣ Testing multiple subaccount IDs:');
    for (let subAccountId = 0; subAccountId < 5; subAccountId++) {
      const [userAccountPDA] = await PublicKey.findProgramAddress(
        [
          Buffer.from('user'),
          keypair.publicKey.toBuffer(),
          Buffer.from([subAccountId])
        ],
        new PublicKey(DRIFT_PROGRAM_ID)
      );
      
      const accountInfo = await connection.getAccountInfo(userAccountPDA);
      console.log(`   SubAccount ${subAccountId}: ${userAccountPDA.toString()} - ${accountInfo ? '✅ EXISTS' : '❌ NOT FOUND'}`);
    }
    
    // Method 4: Try searching for any user accounts by scanning program accounts
    console.log('\n4️⃣ Scanning for any Drift user accounts by this authority:');
    try {
      const programAccounts = await connection.getProgramAccounts(
        new PublicKey(DRIFT_PROGRAM_ID),
        {
          filters: [
            {
              memcmp: {
                offset: 8, // Skip discriminator
                bytes: keypair.publicKey.toBase58()
              }
            }
          ]
        }
      );
      
      console.log(`   Found ${programAccounts.length} account(s) owned by this program with this authority`);
      
      programAccounts.forEach((account, index) => {
        console.log(`   Account ${index + 1}: ${account.pubkey.toString()}`);
        console.log(`     Data length: ${account.account.data.length}`);
        console.log(`     Lamports: ${account.account.lamports}`);
      });
      
    } catch (scanError) {
      console.log('   ❌ Scan failed:', scanError.message);
    }
    
    // Method 5: Test API endpoints
    console.log('\n5️⃣ Testing API endpoints:');
    try {
      // Test login
      const loginResponse = await fetch('http://localhost:3000/api/drift/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' }
      });
      const loginData = await loginResponse.json();
      console.log('   Login API result:', JSON.stringify(loginData, null, 2));
      
      // Test balance
      const balanceResponse = await fetch('http://localhost:3000/api/drift/balance');
      const balanceData = await balanceResponse.json();
      console.log('   Balance API result:', JSON.stringify(balanceData, null, 2));
      
      // Test positions
      const positionsResponse = await fetch('http://localhost:3000/api/drift/positions');
      const positionsData = await positionsResponse.json();
      console.log('   Positions API result:', JSON.stringify(positionsData, null, 2));
      
    } catch (apiError) {
      console.log('   ❌ API test failed:', apiError.message);
    }
    
    // Method 6: Check actual Drift program state
    console.log('\n6️⃣ Checking Drift program state:');
    try {
      const programInfo = await connection.getAccountInfo(new PublicKey(DRIFT_PROGRAM_ID));
      console.log('   Program exists:', !!programInfo);
      console.log('   Program owner:', programInfo?.owner.toString());
      console.log('   Program executable:', programInfo?.executable);
    } catch (programError) {
      console.log('   ❌ Program check failed:', programError.message);
    }
    
    console.log('\n📋 Summary:');
    console.log('   - This wallet has sufficient SOL for transactions');
    console.log('   - The Drift program is accessible');
    console.log('   - Account existence discrepancy between manual check and SDK login');
    console.log('   - Need to investigate why the SDK reports account exists but manual check fails');
    
  } catch (error) {
    console.error('❌ Test failed:', error.message);
    console.error('Stack:', error.stack);
  }
}

testDriftAccount().catch(console.error);
