#!/usr/bin/env node

/**
 * REAL DRIFT PROTOCOL MINIMUM PERCENTAGE TEST
 * 
 * This test places ACTUAL small orders on Drift Protocol to validate
 * that the reduced minimum percentages work in real trading conditions.
 * 
 * SAFETY MEASURES:
 * - Uses very small position sizes ($0.50 - $2.00)
 * - Tests on SOL-PERP with high liquidity
 * - Automatically cancels test orders after validation
 * - Monitors for order rejection reasons
 */

const https = require('https');
const http = require('http');

// Test configuration
const API_BASE = 'http://localhost:3000/api';
const TEST_SYMBOL = 'SOLUSD';
const TEST_AMOUNT = 0.5; // $0.50 position size for safety

// Minimum percentages to test (progressively tighter)
const TEST_CASES = [
  { sl: 1.5, tp: 1.0, desc: 'Conservative scalping (1.5%/1.0%)' },
  { sl: 1.0, tp: 0.75, desc: 'Moderate scalping (1.0%/0.75%)' },
  { sl: 0.75, tp: 0.5, desc: 'Tight scalping (0.75%/0.5%)' },
  { sl: 0.5, tp: 0.25, desc: 'Ultra-tight scalping (0.5%/0.25%)' },
  { sl: 0.25, tp: 0.1, desc: 'Extreme scalping (0.25%/0.1%)' }
];

async function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function makeApiCall(endpoint, method = 'GET', body = null) {
  return new Promise((resolve, reject) => {
    const url = `http://localhost:3000/api${endpoint}`;
    const parsedUrl = new URL(url);
    
    const options = {
      hostname: parsedUrl.hostname,
      port: parsedUrl.port,
      path: parsedUrl.pathname + parsedUrl.search,
      method: method,
      headers: {
        'Content-Type': 'application/json',
      },
    };
    
    const req = http.request(options, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          const jsonData = JSON.parse(data);
          resolve({ success: res.statusCode >= 200 && res.statusCode < 300, data: jsonData, status: res.statusCode });
        } catch (error) {
          resolve({ success: false, error: `Parse error: ${error.message}`, data: data });
        }
      });
    });
    
    req.on('error', (error) => {
      resolve({ success: false, error: error.message });
    });
    
    if (body) {
      req.write(JSON.stringify(body));
    }
    
    req.end();
  });
}

async function getCurrentBalance() {
  console.log('💰 Checking current Drift balance...');
  const result = await makeApiCall('/drift/balance');
  
  if (!result.success) {
    throw new Error(`Failed to get balance: ${result.error}`);
  }
  
  console.log(`   Balance: $${result.data.totalCollateral}`);
  console.log(`   Available: $${result.data.availableBalance}`);
  
  return parseFloat(result.data.availableBalance);
}

async function getCurrentPositions() {
  console.log('📋 Checking current positions...');
  const result = await makeApiCall('/drift/positions');
  
  if (!result.success) {
    throw new Error(`Failed to get positions: ${result.error}`);
  }
  
  console.log(`   Active positions: ${result.data.positions.length}`);
  return result.data.positions;
}

async function testOrderPlacement(testCase, entryPrice) {
  console.log(`\n🔬 Testing: ${testCase.desc}`);
  console.log(`   Entry: $${entryPrice.toFixed(4)}`);
  console.log(`   Stop Loss: ${testCase.sl}% (${(entryPrice * (1 - testCase.sl/100)).toFixed(4)})`);
  console.log(`   Take Profit: ${testCase.tp}% (${(entryPrice * (1 + testCase.tp/100)).toFixed(4)})`);
  
  // Calculate position size based on test amount
  const positionSize = TEST_AMOUNT / entryPrice;
  
  const tradeRequest = {
    symbol: TEST_SYMBOL,
    side: 'long',
    amount: positionSize.toFixed(6),
    stopLossPercent: testCase.sl,
    takeProfitPercent: testCase.tp,
    leverage: 1, // Conservative leverage for testing
    orderType: 'market'
  };
  
  console.log(`   Position size: ${positionSize.toFixed(6)} SOL ($${TEST_AMOUNT})`);
  
  try {
    // Place the order
    console.log('   📤 Placing order...');
    const result = await makeApiCall('/drift/trade', 'POST', tradeRequest);
    
    if (result.success) {
      console.log(`   ✅ SUCCESS: Order placed with ${testCase.sl}%/${testCase.tp}% levels`);
      console.log(`   📋 Transaction: ${result.data.signature || 'N/A'}`);
      
      // Wait a moment for order to process
      await delay(2000);
      
      // Check if position was created
      const positions = await getCurrentPositions();
      const newPosition = positions.find(p => p.symbol === TEST_SYMBOL);
      
      if (newPosition) {
        console.log(`   💼 Position created: ${newPosition.size} SOL`);
        console.log(`   🎯 Stop Loss: $${newPosition.stopLoss || 'N/A'}`);
        console.log(`   📈 Take Profit: $${newPosition.takeProfit || 'N/A'}`);
        
        // IMPORTANT: Close the test position immediately
        console.log('   🧹 Closing test position...');
        const closeResult = await makeApiCall('/drift/trade', 'POST', {
          symbol: TEST_SYMBOL,
          side: 'sell',
          amount: Math.abs(parseFloat(newPosition.size)),
          orderType: 'market'
        });
        
        if (closeResult.success) {
          console.log('   ✅ Test position closed successfully');
        } else {
          console.log(`   ⚠️  Warning: Could not close position: ${closeResult.error}`);
        }
      }
      
      return { success: true, details: result.data };
      
    } else {
      console.log(`   ❌ FAILED: ${result.data.error || result.error}`);
      
      // Analyze the failure reason
      const errorMsg = result.data.error || result.error || '';
      if (errorMsg.includes('trigger') || errorMsg.includes('price')) {
        console.log(`   🔍 Analysis: Price level too close to market`);
        return { success: false, reason: 'price_too_close' };
      } else if (errorMsg.includes('margin') || errorMsg.includes('collateral')) {
        console.log(`   🔍 Analysis: Insufficient margin/collateral`);
        return { success: false, reason: 'insufficient_margin' };
      } else {
        console.log(`   🔍 Analysis: Other error - ${errorMsg}`);
        return { success: false, reason: 'other', error: errorMsg };
      }
    }
    
  } catch (error) {
    console.log(`   ❌ EXCEPTION: ${error.message}`);
    return { success: false, reason: 'exception', error: error.message };
  }
}

async function getCurrentPrice() {
  console.log('📊 Getting current SOL price...');
  
  return new Promise((resolve, reject) => {
    const options = {
      hostname: 'api.binance.com',
      port: 443,
      path: '/api/v3/ticker/price?symbol=SOLUSDT',
      method: 'GET',
    };
    
    const req = https.request(options, (res) => {
      let data = '';
      
      res.on('data', (chunk) => {
        data += chunk;
      });
      
      res.on('end', () => {
        try {
          const jsonData = JSON.parse(data);
          const price = parseFloat(jsonData.price);
          console.log(`   SOL Price: $${price.toFixed(4)}`);
          resolve(price);
        } catch (error) {
          console.log(`   ⚠️  Could not parse price data: ${error.message}`);
          console.log('   Using fallback price: $200.00');
          resolve(200.00);
        }
      });
    });
    
    req.on('error', (error) => {
      console.log(`   ⚠️  Could not get price from Binance: ${error.message}`);
      console.log('   Using fallback price: $200.00');
      resolve(200.00);
    });
    
    req.end();
  });
}

async function runRealDriftTest() {
  console.log('🚀 REAL DRIFT PROTOCOL MINIMUM PERCENTAGE TEST');
  console.log('=' .repeat(60));
  console.log('⚠️  WARNING: This test places REAL orders with REAL money');
  console.log('💡 Position size limited to $0.50 for safety');
  console.log('🧹 Test positions are automatically closed');
  console.log('=' .repeat(60));
  
  try {
    // Pre-flight checks
    const balance = await getCurrentBalance();
    if (balance < 10) {
      throw new Error(`Insufficient balance: $${balance}. Minimum $10 required for safe testing.`);
    }
    
    const initialPositions = await getCurrentPositions();
    const entryPrice = await getCurrentPrice();
    
    // Run tests
    console.log('\n📋 Test Results Summary:');
    console.log('-' .repeat(60));
    
    const results = [];
    
    for (const testCase of TEST_CASES) {
      const result = await testOrderPlacement(testCase, entryPrice);
      results.push({ ...testCase, ...result });
      
      // Wait between tests to avoid rate limits
      await delay(3000);
    }
    
    // Analysis
    console.log('\n🎯 FINAL ANALYSIS:');
    console.log('=' .repeat(60));
    
    const successful = results.filter(r => r.success);
    const failed = results.filter(r => !r.success);
    
    console.log(`✅ Successful: ${successful.length}/${results.length} test cases`);
    console.log(`❌ Failed: ${failed.length}/${results.length} test cases`);
    
    if (successful.length > 0) {
      const tightest = successful[successful.length - 1];
      console.log(`\n🏆 TIGHTEST WORKING PERCENTAGES:`);
      console.log(`   Stop Loss: ${tightest.sl}%`);
      console.log(`   Take Profit: ${tightest.tp}%`);
      console.log(`   Description: ${tightest.desc}`);
      
      console.log(`\n💡 RECOMMENDED NEW MINIMUMS:`);
      console.log(`   stopLossPercentCalc = Math.max(stopLossPercent / 100, ${(tightest.sl / 100).toFixed(4)}) // ${tightest.sl}%`);
      console.log(`   takeProfitPercentCalc = Math.max(takeProfitPercent / 100, ${(tightest.tp / 100).toFixed(4)}) // ${tightest.tp}%`);
    }
    
    if (failed.length > 0) {
      console.log(`\n⚠️  FAILURES ANALYSIS:`);
      failed.forEach(f => {
        console.log(`   ${f.desc}: ${f.reason}`);
      });
    }
    
    // Final position check
    console.log('\n🧹 POST-TEST CLEANUP CHECK:');
    const finalPositions = await getCurrentPositions();
    const newPositions = finalPositions.length - initialPositions.length;
    
    if (newPositions > 0) {
      console.log(`⚠️  Warning: ${newPositions} test positions remain open`);
      console.log('   Manual cleanup may be required');
    } else {
      console.log('✅ All test positions cleaned up successfully');
    }
    
    const finalBalance = await getCurrentBalance();
    const balanceChange = finalBalance - balance;
    console.log(`💰 Balance change: ${balanceChange >= 0 ? '+' : ''}$${balanceChange.toFixed(2)}`);
    
  } catch (error) {
    console.error('❌ Test failed:', error.message);
    console.log('\nℹ️  This could be due to:');
    console.log('   - Network connectivity issues');
    console.log('   - Drift Protocol API changes');
    console.log('   - Insufficient balance or margin');
    console.log('   - Market conditions (low liquidity)');
  }
}

// Safety confirmation
console.log('⚠️  SAFETY CONFIRMATION REQUIRED ⚠️');
console.log('This test will place REAL orders on Drift Protocol');
console.log('Position size is limited to $0.50 per test');
console.log('Orders will be automatically closed');
console.log('');
console.log('To proceed, run: node test-drift-real-orders.js --confirm');

if (process.argv.includes('--confirm')) {
  runRealDriftTest();
} else {
  console.log('Test not run - confirmation required');
  process.exit(0);
}
