/**
 * AI-Driven DCA (Dollar Cost Averaging) Manager
 * 
 * Intelligently adds to positions when market shows reversal potential
 * Manages risk by respecting leverage limits and adjusting stop loss/take profit
 */

import AILeverageCalculator from './ai-leverage-calculator'

interface DCAAnalysisParams {
  currentPosition: {
    side: 'long' | 'short'
    size: number
    entryPrice: number
    currentPrice: number
    unrealizedPnl: number
    stopLoss: number
    takeProfit: number
  }
  accountStatus: {
    accountValue: number
    availableBalance: number
    leverage: number
    liquidationPrice: number
  }
  marketData: {
    price: number
    priceChange24h: number
    volume: number
    rsi?: number
    support?: number
    resistance?: number
  }
  maxLeverageAllowed: number
}

interface DCAResult {
  shouldDCA: boolean
  dcaAmount: number
  newAveragePrice: number
  newStopLoss: number
  newTakeProfit: number
  newLeverage: number
  newLiquidationPrice: number
  riskAssessment: 'LOW' | 'MEDIUM' | 'HIGH'
  reasoning: string
  confidence: number
}

export class AIDCAManager {
  
  /**
   * Analyze if DCA opportunity exists and calculate optimal DCA parameters
   */
  static analyzeDCAOpportunity(params: DCAAnalysisParams): DCAResult {
    const {
      currentPosition,
      accountStatus,
      marketData,
      maxLeverageAllowed
    } = params

    console.log('🔄 AI DCA Analysis:', {
      position: `${currentPosition.side} ${currentPosition.size} @ $${currentPosition.entryPrice}`,
      currentPrice: `$${marketData.price}`,
      pnl: `$${currentPosition.unrealizedPnl.toFixed(2)}`,
      availableBalance: `$${accountStatus.availableBalance.toFixed(2)}`
    })

    // Step 1: Analyze reversal potential
    const reversalAnalysis = this.analyzeReversalPotential(currentPosition, marketData)
    
    if (!reversalAnalysis.hasReversalPotential) {
      return {
        shouldDCA: false,
        dcaAmount: 0,
        newAveragePrice: currentPosition.entryPrice,
        newStopLoss: currentPosition.stopLoss,
        newTakeProfit: currentPosition.takeProfit,
        newLeverage: accountStatus.leverage,
        newLiquidationPrice: accountStatus.liquidationPrice,
        riskAssessment: 'HIGH',
        reasoning: reversalAnalysis.reasoning,
        confidence: 0
      }
    }

    // Step 2: Calculate safe DCA amount
    const dcaCalculation = this.calculateSafeDCAAmount(
      currentPosition,
      accountStatus,
      marketData,
      maxLeverageAllowed
    )

    if (dcaCalculation.dcaAmount === 0) {
      return {
        shouldDCA: false,
        dcaAmount: 0,
        newAveragePrice: currentPosition.entryPrice,
        newStopLoss: currentPosition.stopLoss,
        newTakeProfit: currentPosition.takeProfit,
        newLeverage: accountStatus.leverage,
        newLiquidationPrice: accountStatus.liquidationPrice,
        riskAssessment: 'HIGH',
        reasoning: dcaCalculation.reasoning,
        confidence: 0
      }
    }

    // Step 3: Calculate new position parameters
    const newPositionSize = currentPosition.size + dcaCalculation.dcaAmount
    const newAveragePrice = this.calculateNewAveragePrice(
      currentPosition.size,
      currentPosition.entryPrice,
      dcaCalculation.dcaAmount,
      marketData.price
    )

    // Step 4: Calculate new stop loss and take profit
    const newSLTP = this.calculateNewStopLossAndTakeProfit(
      currentPosition.side,
      newAveragePrice,
      newPositionSize,
      marketData,
      reversalAnalysis.confidence
    )

    // Step 5: Calculate new leverage and liquidation price
    const newLeverage = this.calculateNewLeverage(
      newPositionSize,
      newAveragePrice,
      accountStatus.accountValue,
      dcaCalculation.dcaAmount
    )

    const newLiquidationPrice = this.calculateNewLiquidationPrice(
      newAveragePrice,
      newLeverage,
      currentPosition.side
    )

    // Step 6: Final risk assessment
    const riskAssessment = this.assessDCARisk(
      newLeverage,
      newLiquidationPrice,
      newSLTP.stopLoss,
      accountStatus.availableBalance,
      dcaCalculation.dcaAmount
    )

    const result: DCAResult = {
      shouldDCA: true,
      dcaAmount: dcaCalculation.dcaAmount,
      newAveragePrice,
      newStopLoss: newSLTP.stopLoss,
      newTakeProfit: newSLTP.takeProfit,
      newLeverage,
      newLiquidationPrice,
      riskAssessment,
      reasoning: this.generateDCAReasoning(reversalAnalysis, dcaCalculation, newAveragePrice, newLeverage),
      confidence: reversalAnalysis.confidence
    }

    console.log('🚀 DCA Recommendation:', {
      shouldDCA: result.shouldDCA,
      dcaAmount: `$${result.dcaAmount.toFixed(2)}`,
      newAverage: `$${result.newAveragePrice.toFixed(4)}`,
      newSL: `$${result.newStopLoss.toFixed(4)}`,
      newTP: `$${result.newTakeProfit.toFixed(4)}`,
      newLeverage: `${result.newLeverage.toFixed(1)}x`,
      riskLevel: result.riskAssessment,
      confidence: `${result.confidence}%`
    })

    return result
  }

  /**
   * Analyze market conditions for reversal potential
   */
  private static analyzeReversalPotential(position: any, marketData: any): {
    hasReversalPotential: boolean
    reasoning: string
    confidence: number
  } {
    
    const priceMovement = ((marketData.price - position.entryPrice) / position.entryPrice) * 100
    const isMovingAgainstPosition = (position.side === 'long' && priceMovement < 0) || 
                                   (position.side === 'short' && priceMovement > 0)

    // Only consider DCA if price moved against us (creating discount opportunity)
    if (!isMovingAgainstPosition) {
      return {
        hasReversalPotential: false,
        reasoning: "Price moving in our favor - no DCA needed",
        confidence: 0
      }
    }

    let confidence = 0
    const reasons = []

    // Factor 1: Price drop magnitude (for longs) or rise magnitude (for shorts)
    const movementMagnitude = Math.abs(priceMovement)
    if (movementMagnitude >= 1 && movementMagnitude <= 5) {
      confidence += 30
      reasons.push(`${movementMagnitude.toFixed(1)}% movement creates DCA opportunity`)
    } else if (movementMagnitude > 5 && movementMagnitude <= 10) {
      confidence += 40
      reasons.push(`${movementMagnitude.toFixed(1)}% movement shows strong discount`)
    } else if (movementMagnitude > 10) {
      confidence += 20
      reasons.push(`${movementMagnitude.toFixed(1)}% movement may indicate trend change`)
    }

    // Factor 2: 24h price change context
    if (marketData.priceChange24h !== undefined) {
      if (position.side === 'long' && marketData.priceChange24h < -3) {
        confidence += 25
        reasons.push("24h downtrend creates long DCA opportunity")
      } else if (position.side === 'short' && marketData.priceChange24h > 3) {
        confidence += 25
        reasons.push("24h uptrend creates short DCA opportunity")
      }
    }

    // Factor 3: Support/Resistance levels
    if (marketData.support && position.side === 'long' && marketData.price <= marketData.support * 1.02) {
      confidence += 20
      reasons.push("Price near support level")
    }
    if (marketData.resistance && position.side === 'short' && marketData.price >= marketData.resistance * 0.98) {
      confidence += 20
      reasons.push("Price near resistance level")
    }

    // Factor 4: RSI oversold/overbought
    if (marketData.rsi !== undefined) {
      if (position.side === 'long' && marketData.rsi < 35) {
        confidence += 15
        reasons.push("RSI oversold - reversal likely")
      } else if (position.side === 'short' && marketData.rsi > 65) {
        confidence += 15
        reasons.push("RSI overbought - reversal likely")
      }
    }

    // Minimum confidence threshold for DCA
    const hasReversalPotential = confidence >= 50

    return {
      hasReversalPotential,
      reasoning: hasReversalPotential 
        ? reasons.join(", ")
        : `Insufficient reversal signals (${confidence}% confidence)`,
      confidence
    }
  }

  /**
   * Calculate safe DCA amount respecting leverage and liquidation limits
   */
  private static calculateSafeDCAAmount(
    position: any,
    accountStatus: any,
    marketData: any,
    maxLeverageAllowed: number
  ): { dcaAmount: number, reasoning: string } {
    
    // Use AI Leverage Calculator to determine safe additional position size
    const currentStopLossPrice = position.side === 'long' 
      ? position.entryPrice * (1 - position.stopLoss / 100)
      : position.entryPrice * (1 + position.stopLoss / 100)

    const leverageResult = AILeverageCalculator.calculateOptimalLeverage({
      accountValue: accountStatus.accountValue,
      availableBalance: accountStatus.availableBalance,
      entryPrice: marketData.price, // Current price for DCA entry
      stopLossPrice: currentStopLossPrice, // Keep same SL initially
      side: position.side,
      maxLeverageAllowed,
      safetyBuffer: 0.15 // More conservative for DCA
    })

    // Calculate maximum safe DCA amount
    const maxDCAUSD = accountStatus.availableBalance * 0.5 // Use up to 50% of available balance
    const leveragedDCAAmount = maxDCAUSD * leverageResult.recommendedLeverage
    const dcaTokenAmount = leveragedDCAAmount / marketData.price

    // Ensure DCA doesn't make position too large relative to account
    const currentPositionValue = position.size * position.entryPrice
    const maxPositionValue = accountStatus.accountValue * 3 // Max 3x account value
    const remainingCapacity = maxPositionValue - currentPositionValue

    const finalDCAAmount = Math.min(
      dcaTokenAmount,
      remainingCapacity / marketData.price,
      position.size * 0.5 // Max 50% of current position size
    )

    if (finalDCAAmount < 0.01) {
      return {
        dcaAmount: 0,
        reasoning: "Insufficient available balance or position capacity for safe DCA"
      }
    }

    return {
      dcaAmount: finalDCAAmount,
      reasoning: `Safe DCA: ${finalDCAAmount.toFixed(4)} tokens using ${leverageResult.recommendedLeverage.toFixed(1)}x leverage`
    }
  }

  /**
   * Calculate new average price after DCA
   */
  private static calculateNewAveragePrice(
    currentSize: number,
    currentPrice: number,
    dcaSize: number,
    dcaPrice: number
  ): number {
    const totalValue = (currentSize * currentPrice) + (dcaSize * dcaPrice)
    const totalSize = currentSize + dcaSize
    return totalValue / totalSize
  }

  /**
   * Calculate new stop loss and take profit for the averaged position
   */
  private static calculateNewStopLossAndTakeProfit(
    side: 'long' | 'short',
    newAveragePrice: number,
    newPositionSize: number,
    marketData: any,
    confidence: number
  ): { stopLoss: number, takeProfit: number } {
    
    // Adjust SL/TP based on confidence and position size
    const baseStopLossPercent = 3 // Base 3% stop loss
    const baseTakeProfitPercent = confidence > 70 ? 8 : 6 // Higher TP if very confident

    // Make SL tighter for larger positions
    const positionSizeMultiplier = Math.min(newPositionSize / 5, 1.5) // Cap at 1.5x
    const adjustedSLPercent = baseStopLossPercent / positionSizeMultiplier

    let stopLoss: number
    let takeProfit: number

    if (side === 'long') {
      stopLoss = newAveragePrice * (1 - adjustedSLPercent / 100)
      takeProfit = newAveragePrice * (1 + baseTakeProfitPercent / 100)
    } else {
      stopLoss = newAveragePrice * (1 + adjustedSLPercent / 100)
      takeProfit = newAveragePrice * (1 - baseTakeProfitPercent / 100)
    }

    return { stopLoss, takeProfit }
  }

  /**
   * Calculate new effective leverage after DCA
   */
  private static calculateNewLeverage(
    newPositionSize: number,
    newAveragePrice: number,
    accountValue: number,
    dcaAmount: number
  ): number {
    const totalPositionValue = newPositionSize * newAveragePrice
    return totalPositionValue / accountValue
  }

  /**
   * Calculate new liquidation price
   */
  private static calculateNewLiquidationPrice(
    averagePrice: number,
    leverage: number,
    side: 'long' | 'short'
  ): number {
    if (side === 'long') {
      return averagePrice * (1 - 1/leverage)
    } else {
      return averagePrice * (1 + 1/leverage)
    }
  }

  /**
   * Assess risk of DCA operation
   */
  private static assessDCARisk(
    newLeverage: number,
    liquidationPrice: number,
    stopLoss: number,
    availableBalance: number,
    dcaAmount: number
  ): 'LOW' | 'MEDIUM' | 'HIGH' {
    
    const liquidationBuffer = Math.abs(liquidationPrice - stopLoss) / stopLoss * 100
    const balanceUsagePercent = (dcaAmount * liquidationPrice) / availableBalance * 100

    if (newLeverage <= 3 && liquidationBuffer >= 15 && balanceUsagePercent <= 30) return 'LOW'
    if (newLeverage <= 6 && liquidationBuffer >= 10 && balanceUsagePercent <= 50) return 'MEDIUM'
    
    return 'HIGH'
  }

  /**
   * Generate reasoning for DCA decision
   */
  private static generateDCAReasoning(
    reversalAnalysis: any,
    dcaCalculation: any,
    newAveragePrice: number,
    newLeverage: number
  ): string {
    return `${reversalAnalysis.reasoning}. ${dcaCalculation.reasoning}. New average: $${newAveragePrice.toFixed(4)} with ${newLeverage.toFixed(1)}x leverage.`
  }
}

export default AIDCAManager
