#!/usr/bin/env node

/**
 * Test Stop Loss / Take Profit Preservation Fix
 * Verifies that SL/TP orders are not being incorrectly canceled as orphaned orders
 */

console.log('🧪 Testing Stop Loss / Take Profit Preservation Fix...');

async function testSLTPPreservation() {
  try {
    console.log('\n1️⃣ Testing Cleanup Logic...');
    
    // Simulate position data
    const mockPositions = [
      {
        marketIndex: 0, // SOL-PERP
        symbol: 'SOL-PERP',
        side: 'long',
        size: 1.5,
        entryPrice: 165.50
      }
    ];
    
    // Simulate orders including SL/TP
    const mockOrders = [
      {
        orderId: 1,
        marketIndex: 0, // Same market as position
        direction: 1, // SHORT (opposite to position - correct for SL)
        reduceOnly: true, // This is a Stop Loss order
        baseAssetAmount: { isZero: () => false },
        status: { open: true }
      },
      {
        orderId: 2,
        marketIndex: 0, // Same market as position  
        direction: 1, // SHORT (opposite to position - correct for TP)
        reduceOnly: true, // This is a Take Profit order
        baseAssetAmount: { isZero: () => false },
        status: { open: true }
      },
      {
        orderId: 3,
        marketIndex: 1, // Different market - truly orphaned
        direction: 0, // LONG
        reduceOnly: false, // Regular order
        baseAssetAmount: { isZero: () => false },
        status: { open: true }
      }
    ];
    
    // Test the fixed logic
    const positionMarkets = new Set(mockPositions.map(pos => pos.marketIndex));
    console.log('📊 Position markets:', Array.from(positionMarkets));
    
    // OLD BROKEN LOGIC (what was causing the bug):
    const oldOrphanedOrders = mockOrders.filter(order => 
      !positionMarkets.has(order.marketIndex) || 
      (order.reduceOnly && !positionMarkets.has(order.marketIndex))
    );
    
    // NEW FIXED LOGIC:
    const newOrphanedOrders = mockOrders.filter(order => 
      !positionMarkets.has(order.marketIndex) && !order.reduceOnly
    );
    
    console.log(`❌ OLD LOGIC would cancel: ${oldOrphanedOrders.length} orders`);
    oldOrphanedOrders.forEach(order => {
      const type = order.reduceOnly ? 'SL/TP' : 'Regular';
      console.log(`   - Order ${order.orderId} (${type}) on market ${order.marketIndex}`);
    });
    
    console.log(`✅ NEW LOGIC will cancel: ${newOrphanedOrders.length} orders`);
    newOrphanedOrders.forEach(order => {
      const type = order.reduceOnly ? 'SL/TP' : 'Regular';
      console.log(`   - Order ${order.orderId} (${type}) on market ${order.marketIndex}`);
    });
    
    // Verify the fix
    const slTpOrdersPreserved = mockOrders
      .filter(order => order.reduceOnly && positionMarkets.has(order.marketIndex))
      .filter(order => !newOrphanedOrders.includes(order));
    
    console.log(`🛡️ SL/TP orders preserved: ${slTpOrdersPreserved.length}`);
    slTpOrdersPreserved.forEach(order => {
      console.log(`   ✅ Order ${order.orderId} (SL/TP) preserved for market ${order.marketIndex}`);
    });
    
    console.log('\n2️⃣ Testing API Endpoints...');
    
    // Test cleanup API with mock data
    console.log('📡 Testing cleanup-orders API...');
    
    const baseUrl = 'http://localhost:9001';
    
    // Test positions endpoint
    try {
      const positionsResponse = await fetch(`${baseUrl}/api/drift/positions`);
      const positionsData = await positionsResponse.json();
      console.log(`✅ Positions API: ${positionsData.success ? 'Working' : 'Failed'}`);
      
      if (positionsData.success) {
        console.log(`   📊 Found ${positionsData.positions?.length || 0} positions`);
      }
    } catch (error) {
      console.log(`❌ Positions API error: ${error.message}`);
    }
    
    // Test orders endpoint
    try {
      const ordersResponse = await fetch(`${baseUrl}/api/drift/orders`);
      const ordersData = await ordersResponse.json();
      console.log(`✅ Orders API: ${ordersData.success ? 'Working' : 'Failed'}`);
      
      if (ordersData.success) {
        console.log(`   📋 Found ${ordersData.orders?.length || 0} orders`);
        
        // Analyze order types
        const orders = ordersData.orders || [];
        const reduceOnlyOrders = orders.filter(order => order.reduceOnly);
        const regularOrders = orders.filter(order => !order.reduceOnly);
        
        console.log(`   🛡️ Reduce-only orders (SL/TP): ${reduceOnlyOrders.length}`);
        console.log(`   📈 Regular orders: ${regularOrders.length}`);
      }
    } catch (error) {
      console.log(`❌ Orders API error: ${error.message}`);
    }
    
    console.log('\n3️⃣ Testing Position Monitor...');
    
    try {
      const monitorResponse = await fetch(`${baseUrl}/api/automation/position-monitor`);
      const monitorData = await monitorResponse.json();
      
      if (monitorData.success) {
        const monitor = monitorData.monitor;
        console.log(`✅ Position Monitor: Working`);
        console.log(`   📊 Has Position: ${monitor.hasPosition}`);
        console.log(`   🧹 Cleanup Triggered: ${monitor.orphanedOrderCleanup?.triggered || false}`);
        console.log(`   📝 Message: ${monitor.orphanedOrderCleanup?.message || 'N/A'}`);
      } else {
        console.log(`❌ Position Monitor failed: ${monitorData.error}`);
      }
    } catch (error) {
      console.log(`❌ Position Monitor error: ${error.message}`);
    }
    
    console.log('\n✅ Testing Complete!');
    console.log('\n📋 Summary of Fixes:');
    console.log('   🛡️ Stop Loss and Take Profit orders are now preserved');
    console.log('   🧹 Only truly orphaned orders (non-reduce-only) will be cleaned up');
    console.log('   📊 Position monitor is more conservative about cleanup');
    console.log('   ⚠️ Background cleanup services should be stopped to prevent interference');
    
  } catch (error) {
    console.error('❌ Test failed:', error);
  }
}

// Run the test
testSLTPPreservation();
