import { NextResponse } from 'next/server'

// Helper function to get market index from symbol
function getMarketIndex(symbol) {
  const marketMap = {
    'SOL': 0,
    'BTC': 1,
    'ETH': 2,
    'APT': 3,
    'AVAX': 4,
    'BNB': 5,
    'MATIC': 6,
    'ARB': 7,
    'DOGE': 8,
    'OP': 9
  }
  
  const index = marketMap[symbol.toUpperCase()]
  if (index === undefined) {
    throw new Error(`Unsupported symbol: ${symbol}`)
  }
  
  return index
}

// Helper function to get symbol from market index
function getSymbolFromMarketIndex(marketIndex) {
  const symbols = ['SOL', 'BTC', 'ETH', 'APT', 'AVAX', 'BNB', 'MATIC', 'ARB', 'DOGE', 'OP']
  return symbols[marketIndex] || `UNKNOWN_${marketIndex}`
}

// Helper function to get trading balance with better error handling
async function getTradingBalance(driftClient) {
  try {
    const userAccount = await driftClient.getUserAccount()
    
    if (!userAccount) {
      throw new Error('User account is null')
    }
    
    console.log('📊 Raw user account data keys:', Object.keys(userAccount))
    
    // Get all spot positions
    const spotPositions = userAccount.spotPositions || []
    const usdcPosition = spotPositions.find(pos => pos.marketIndex === 0) // USDC is usually index 0
    
    // Convert BigNumber values to regular numbers
    const BN = (await import('bn.js')).default
    
    // Get collateral info - convert from BN to number
    const totalCollateral = userAccount.totalCollateral ? 
      (userAccount.totalCollateral instanceof BN ? userAccount.totalCollateral.toNumber() / 1e6 : 
       parseFloat(userAccount.totalCollateral.toString()) / 1e6) : 0
    
    const freeCollateral = userAccount.freeCollateral ? 
      (userAccount.freeCollateral instanceof BN ? userAccount.freeCollateral.toNumber() / 1e6 : 
       parseFloat(userAccount.freeCollateral.toString()) / 1e6) : 0
    
    // Get USDC balance
    const usdcBalance = usdcPosition && usdcPosition.scaledBalance ? 
      (usdcPosition.scaledBalance instanceof BN ? usdcPosition.scaledBalance.toNumber() / 1e6 : 
       parseFloat(usdcPosition.scaledBalance.toString()) / 1e6) : 0
    
    console.log('💰 Parsed balances:', {
      totalCollateral,
      freeCollateral,
      usdcBalance,
      spotPositionsCount: spotPositions.length
    })
    
    return {
      totalCollateral: totalCollateral.toString(),
      freeCollateral: freeCollateral.toString(),
      usdcBalance: usdcBalance.toString(),
      marginRatio: userAccount.marginRatio ? userAccount.marginRatio.toString() : '0',
      accountExists: true,
      spotPositions: spotPositions.map(pos => ({
        marketIndex: pos.marketIndex,
        balance: pos.scaledBalance ? 
          (pos.scaledBalance instanceof BN ? pos.scaledBalance.toNumber() / 1e6 : 
           parseFloat(pos.scaledBalance.toString()) / 1e6) : 0
      }))
    }
  } catch (error) {
    throw new Error(`Balance retrieval failed: ${error.message}`)
  }
}

export async function POST(request) {
  try {
    console.log('🌊 Drift leverage trading endpoint...')

    // Check if environment is configured
    if (!process.env.SOLANA_PRIVATE_KEY) {
      return NextResponse.json({
        success: false,
        error: 'Drift not configured - missing SOLANA_PRIVATE_KEY'
      }, { status: 400 })
    }

    const { 
      action = 'get_balance', 
      symbol = 'SOL', 
      amount, 
      side, 
      leverage = 1,
      stopLoss = true,
      takeProfit = true,
      stopLossPercent = 2, // Default 2%
      takeProfitPercent = 4 // Default 4%
    } = await request.json()

    // Import Drift SDK components
    const { DriftClient, initialize } = await import('@drift-labs/sdk')
    const { Connection, Keypair } = await import('@solana/web3.js')

    // Initialize connection with Helius
    const heliusApiKey = '5e236449-f936-4af7-ae38-f15e2f1a3757'
    const rpcUrl = `https://mainnet.helius-rpc.com/?api-key=${heliusApiKey}`
    const connection = new Connection(rpcUrl, 'confirmed')
    
    console.log('🌐 Using mainnet with Helius RPC')

    const privateKeyArray = JSON.parse(process.env.SOLANA_PRIVATE_KEY)
    const keypair = Keypair.fromSecretKey(new Uint8Array(privateKeyArray))
    
    // Create wallet using manual interface (most reliable)
    const wallet = {
      publicKey: keypair.publicKey,
      signTransaction: async (tx) => {
        if (typeof tx.partialSign === 'function') {
          tx.partialSign(keypair)
        } else if (typeof tx.sign === 'function') {
          tx.sign([keypair])
        }
        return tx
      },
      signAllTransactions: async (txs) => {
        return txs.map(tx => {
          if (typeof tx.partialSign === 'function') {
            tx.partialSign(keypair)
          } else if (typeof tx.sign === 'function') {
            tx.sign([keypair])
          }
          return tx
        })
      }
    }

    console.log('🔐 Connecting to Drift with wallet:', keypair.publicKey.toString())

    // Initialize Drift SDK
    const env = 'mainnet-beta'
    const sdkConfig = initialize({ env })
    
    const driftClient = new DriftClient({
      connection,
      wallet,
      programID: sdkConfig.DRIFT_PROGRAM_ID,
      opts: {
        commitment: 'confirmed',
      },
    })

    try {
      // Subscribe to drift client
      await driftClient.subscribe()
      console.log('✅ Connected to Drift successfully')

      // Handle action
      let result = {}

      if (action === 'get_balance') {
        try {
          // Simple and direct approach
          console.log('🔍 Getting user account...')
          const userAccount = await driftClient.getUserAccount()
          
          if (userAccount) {
            console.log('✅ User account found, getting balance...')
            result = await getTradingBalance(driftClient)
            console.log('✅ Balance retrieved successfully')
          } else {
            console.log('❌ User account is null')
            result = {
              message: 'User account exists but returns null',
              accountExists: false
            }
          }
        } catch (error) {
          console.log('❌ Error getting user account:', error.message)
          
          // Check wallet SOL balance as fallback
          const walletBalance = await connection.getBalance(keypair.publicKey)
          const solBalance = walletBalance / 1e9
          
          result = {
            message: 'Cannot access user account data',
            error: error.message,
            solBalance: solBalance,
            walletAddress: keypair.publicKey.toString(),
            suggestion: 'Account may need to be accessed through Drift UI first or deposit USDC directly'
          }
        }
      } else if (action === 'place_order') {
        // Place a leverage order with stop loss and take profit
        if (!amount || !side) {
          result = {
            error: 'Missing required parameters: amount and side'
          }
        } else {
          try {
            const { OrderType, PositionDirection, OrderTriggerCondition } = await import('@drift-labs/sdk')
            const BN = (await import('bn.js')).default
            
            const marketIndex = getMarketIndex(symbol)
            
            // Get current market price for stop loss/take profit calculations
            const perpMarketAccount = driftClient.getPerpMarketAccount(marketIndex)
            const currentPrice = Number(perpMarketAccount.amm.lastMarkPriceTwap) / 1e6
            
            console.log(`📊 Current ${symbol} price: $${currentPrice}`)
            
            // For perpetual futures: amount is USD position size, apply leverage
            // Example: $32 position with 10x leverage = $320 position value
            const leveragedPositionSize = amount * leverage
            console.log(`💰 Applying ${leverage}x leverage: $${amount} → $${leveragedPositionSize}`)
            
            // Convert leveraged USD position to SOL base asset amount
            const solTokenAmount = leveragedPositionSize / currentPrice
            const baseAssetAmount = new BN(Math.floor(solTokenAmount * 1e9))
            
            console.log(`💰 Position size conversion:`, {
              usdPositionSize: amount,
              leverage: leverage,
              leveragedPositionSize: leveragedPositionSize,
              solPrice: currentPrice,
              solTokenAmount: solTokenAmount,
              calculatedBaseAsset: solTokenAmount * 1e9,
              flooredBaseAsset: Math.floor(solTokenAmount * 1e9),
              baseAssetAmount: baseAssetAmount.toString()
            })
            
            // Determine direction
            const direction = side.toLowerCase() === 'buy' ? PositionDirection.LONG : PositionDirection.SHORT
            
            console.log(`📊 Placing ${side} order:`, {
              symbol,
              marketIndex,
              usdAmount: amount,
              solAmount: solTokenAmount,
              leverage,
              currentPrice,
              baseAssetAmount: baseAssetAmount.toString()
            })

            // 1. Place main perpetual market order
            console.log('🚀 Placing main market order...')
            const mainOrderTx = await driftClient.placePerpOrder({
              orderType: OrderType.MARKET,
              marketIndex,
              direction,
              baseAssetAmount,
              reduceOnly: false,
            })

            console.log('✅ Main order placed:', mainOrderTx)
            
            // Wait for main order to fill
            await new Promise(resolve => setTimeout(resolve, 5000))

            // 2. Calculate stop loss and take profit prices using config percentages
            // NO ARTIFICIAL MINIMUMS: AI can freely choose appropriate percentages
            const stopLossPercentCalc = stopLossPercent / 100 // Use exact percentage from AI analysis
            const takeProfitPercentCalc = takeProfitPercent / 100 // Use exact percentage from AI analysis
            
            let stopLossPrice, takeProfitPrice
            
            if (direction === PositionDirection.LONG) {
              stopLossPrice = currentPrice * (1 - stopLossPercentCalc)
              takeProfitPrice = currentPrice * (1 + takeProfitPercentCalc)
            } else {
              stopLossPrice = currentPrice * (1 + stopLossPercentCalc)
              takeProfitPrice = currentPrice * (1 - takeProfitPercentCalc)
            }
            
            console.log(`🎯 Risk management:`, {
              stopLossPrice: stopLossPrice.toFixed(4),
              takeProfitPrice: takeProfitPrice.toFixed(4),
              stopLossPercent: `${stopLossPercentCalc * 100}%`,
              takeProfitPercent: `${takeProfitPercentCalc * 100}%`,
              priceDifference: Math.abs(currentPrice - stopLossPrice).toFixed(4)
            })

            let stopLossTx = null, takeProfitTx = null

                        // 3. Place stop loss order
            if (stopLoss) {
              try {
                console.log('🛡️ Placing stop loss order...')
                
                const stopLossTriggerPrice = new BN(Math.floor(stopLossPrice * 1e6))
                
                const stopLossOrderPrice = direction === PositionDirection.LONG 
                  ? new BN(Math.floor(stopLossPrice * 0.995 * 1e6)) // LONG: order below trigger
                  : new BN(Math.floor(stopLossPrice * 1.005 * 1e6)) // SHORT: order above trigger
                
                console.log(`🛡️ Stop Loss Details:`, {
                  orderType: 'TRIGGER_LIMIT',
                  triggerPrice: (stopLossTriggerPrice.toNumber() / 1e6).toFixed(4),
                  orderPrice: (stopLossOrderPrice.toNumber() / 1e6).toFixed(4),
                  direction: direction === PositionDirection.LONG ? 'SHORT' : 'LONG',
                  baseAssetAmount: baseAssetAmount.toString(),
                  currentPrice: currentPrice,
                  stopLossPrice: stopLossPrice
                })
                
                stopLossTx = await driftClient.placePerpOrder({
                  orderType: OrderType.TRIGGER_LIMIT,
                  marketIndex,
                  direction: direction === PositionDirection.LONG ? PositionDirection.SHORT : PositionDirection.LONG,
                  baseAssetAmount,
                  price: stopLossOrderPrice,
                  triggerPrice: stopLossTriggerPrice,
                  triggerCondition: direction === PositionDirection.LONG ? OrderTriggerCondition.BELOW : OrderTriggerCondition.ABOVE,
                  reduceOnly: true,
                })
                
                console.log('✅ Stop loss placed:', stopLossTx)
              } catch (slError) {
                console.warn('⚠️ Stop loss failed:', slError.message)
                console.warn('🛡️ Stop loss failure details:', {
                  stopLossPrice,
                  currentPrice,
                  priceDiff: Math.abs(currentPrice - stopLossPrice),
                  percentDiff: ((Math.abs(currentPrice - stopLossPrice) / currentPrice) * 100).toFixed(2) + '%',
                  error: slError.message
                })
              }
            }

            // 4. Place take profit order  
            if (takeProfit) {
              try {
                console.log('🎯 Placing take profit order...')
                
                const takeProfitTriggerPrice = new BN(Math.floor(takeProfitPrice * 1e6))
                const takeProfitOrderPrice = new BN(Math.floor(takeProfitPrice * 1.005 * 1e6)) // 0.5% slippage for execution
                
                console.log('🎯 Take Profit Details:', {
                  takeProfitPrice: takeProfitPrice.toFixed(4),
                  triggerPrice: (Number(takeProfitTriggerPrice) / 1e6).toFixed(4),
                  orderPrice: (Number(takeProfitOrderPrice) / 1e6).toFixed(4),
                  baseAssetAmount: baseAssetAmount.toString()
                })
                
                takeProfitTx = await driftClient.placePerpOrder({
                  orderType: OrderType.TRIGGER_LIMIT,
                  marketIndex,
                  direction: direction === PositionDirection.LONG ? PositionDirection.SHORT : PositionDirection.LONG,
                  baseAssetAmount,
                  price: takeProfitOrderPrice,
                  triggerPrice: takeProfitTriggerPrice,
                  reduceOnly: true,
                })
                
                console.log('✅ Take profit placed successfully:', takeProfitTx)
              } catch (tpError) {
                console.error('❌ Take profit placement failed:', {
                  error: tpError.message,
                  code: tpError.code,
                  logs: tpError.logs || 'No logs available'
                })
              }
            }

            // 5. Get final position after all orders
            const userAccount = await driftClient.getUserAccount()
            const position = userAccount.perpPositions.find(pos => pos.marketIndex === marketIndex && !pos.baseAssetAmount.isZero())

            // 6. Create learning record for AI feedback loop
            try {
              const { PrismaClient } = await import('@prisma/client')
              const prisma = new PrismaClient()
              
              // Create trade record for learning
              const tradeRecord = await prisma.trade.create({
                data: {
                  userId: 'default-user', // Use existing user
                  symbol: symbol,
                  side: side.toLowerCase(),
                  amount: amount,
                  price: currentPrice,
                  entryPrice: currentPrice,
                  stopLoss: stopLoss ? stopLossPrice : null,
                  takeProfit: takeProfit ? takeProfitPrice : null,
                  leverage: leverage,
                  timeframe: '1h', // Default timeframe
                  status: 'EXECUTED',
                  driftTxId: mainOrderTx,
                  isAutomated: true,
                  tradingMode: 'REAL',
                  executionTime: new Date(),
                  learningData: JSON.stringify({
                    stopLossTransactionId: stopLossTx,
                    takeProfitTransactionId: takeProfitTx,
                    stopLossPercent,
                    takeProfitPercent,
                    marketIndex,
                    orderExecutionData: {
                      mainOrderSuccess: !!mainOrderTx,
                      stopLossSuccess: !!stopLossTx,
                      takeProfitSuccess: !!takeProfitTx,
                      platform: 'DRIFT_PROTOCOL'
                    }
                  })
                }
              })
              
              console.log(`📚 Created learning record for trade: ${tradeRecord.id}`)
              
              await prisma.$disconnect()
            } catch (learningError) {
              console.warn('⚠️ Failed to create learning record:', learningError.message)
            }

            result = {
              success: true,
              transactionId: mainOrderTx,
              stopLossTransactionId: stopLossTx,
              takeProfitTransactionId: takeProfitTx,
              symbol,
              side,
              amount,
              leverage,
              currentPrice,
              stopLossPrice: stopLoss ? stopLossPrice : null,
              takeProfitPrice: takeProfit ? takeProfitPrice : null,
              riskManagement: {
                stopLoss: !!stopLossTx,
                takeProfit: !!takeProfitTx,
                stopLossPercent,
                takeProfitPercent
              },
              position: position ? {
                marketIndex: position.marketIndex,
                baseAssetAmount: position.baseAssetAmount.toString(),
                quoteAssetAmount: position.quoteAssetAmount.toString(),
                avgEntryPrice: (Number(position.quoteAssetAmount) / Number(position.baseAssetAmount) * 1e9).toFixed(4)
              } : null
            }
          } catch (orderError) {
            console.log('❌ Failed to place order:', orderError.message)
            result = {
              success: false,
              error: 'Failed to place order',
              details: orderError.message
            }
          }
        }
      } else {
        result = { message: `Action ${action} not yet implemented` }
      }

      // Clean up connection
      await driftClient.unsubscribe()

      return NextResponse.json({
        success: true,
        action,
        result,
        timestamp: Date.now()
      })

    } catch (driftError) {
      console.error('❌ Drift trading error:', driftError)
      
      try {
        await driftClient.unsubscribe()
      } catch (cleanupError) {
        console.warn('⚠️ Cleanup error:', cleanupError.message)
      }
      
      return NextResponse.json({
        success: false,
        error: 'Drift trading failed',
        details: driftError.message
      }, { status: 500 })
    }

  } catch (error) {
    console.error('❌ Trading API error:', error)
    
    return NextResponse.json({
      success: false,
      error: 'Internal server error',
      details: error.message
    }, { status: 500 })
  }
}
