/**
 * Trade Signal Generator
 * Converts badge combinations into actionable trade signals
 */

import { getMoneynessContext, isGammaSqueezeSetup } from '../utils/moneynessHelper.js';

/**
 * Generate trade signal from badge combinations
 * @param {Object} row - Flow row with badges and context
 * @returns {Object} Trade signal with entry, stop, target, confidence
 */
export function generateTradeSignal(row) {
  const badges = row.badges || row.badgesRaw || {};
  const round = badges.round || '';
  const more = badges.more || '';
  const flash = badges.flash || '';
  
  const hasDiamond = more.includes('💎');
  const hasStar = more.includes('⭐');
  const hasMoney = more.includes('💰');
  const hasFlash = flash === '⚡';
  const tapeAligned = row.tapeAligned || row.tape_alignment === 1;
  const rocketScore = row.rocketScore || row.rocket_score || 0;
  const direction = row.direction || '';
  const currentPrice = row.u_close || row.spot_num || row.Price || 0;
  
  // Get moneyness context (use existing if available, otherwise calculate)
  const moneyness = row.moneynessContext || getMoneynessContext(row);
  const isGamma = row.isGammaSqueezeSetup !== undefined 
    ? row.isGammaSqueezeSetup 
    : isGammaSqueezeSetup(row);
  
  // Pattern 1: 🟢 + 💎 + ⭐ + 💰 + ⚡ = BUY SIGNAL
  if (round === '🟢' && hasDiamond && hasStar && hasMoney && hasFlash) {
    // Check if this is a gamma squeeze setup (Deep OTM calls with full badges)
    if (isGamma || (moneyness.category === 'DEEP_OTM' && row.cp_norm === 'CALL')) {
      return {
        signal: 'BUY',
        type: 'GAMMA_SQUEEZE_SETUP',
        confidence: Math.min(calculateConfidence(row, 'BUY') + 10, 95), // Boost confidence for gamma setups
        entry: generateEntryStrategy(row, 'BUY'),
        stop: generateStopLoss(row, 'BUY'),
        target: generateTarget(row, 'BUY'),
        reasoning: `Gamma squeeze setup: Deep OTM calls (${moneyness.distancePct}% OTM) + full institutional flow. Market makers short gamma = forced buying on price rise.`,
        timeHorizon: 'INTRADAY',
        invalidation: generateInvalidation(row, 'BUY')
      };
    }
    
    // Regular institutional FOMO
    return {
      signal: 'BUY',
      type: 'INSTITUTIONAL_FOMO',
      confidence: calculateConfidence(row, 'BUY'),
      entry: generateEntryStrategy(row, 'BUY'),
      stop: generateStopLoss(row, 'BUY'),
      target: generateTarget(row, 'BUY'),
      reasoning: 'Institutional FOMO: Full badge alignment with aggressive flow',
      timeHorizon: 'INTRADAY',
      invalidation: generateInvalidation(row, 'BUY')
    };
  }
  
  // Pattern 2: 🔴 + 💎 + ⭐ + 💰 = SHORT SIGNAL (Institutional Distribution)
  if (round === '🔴' && hasDiamond && hasStar && hasMoney) {
    return {
      signal: 'SHORT',
      type: 'INSTITUTIONAL_DISTRIBUTION',
      confidence: calculateConfidence(row, 'SHORT'),
      entry: generateEntryStrategy(row, 'SHORT'),
      stop: generateStopLoss(row, 'SHORT'),
      target: generateTarget(row, 'SHORT'),
      reasoning: 'Institutional Distribution: Bearish flow with ITM dominance',
      timeHorizon: 'INTRADAY',
      invalidation: generateInvalidation(row, 'SHORT')
    };
  }
  
  // Pattern 3: 🟢 but TapeAlign = blank = TRAP WARNING
  if (round === '🟢' && !tapeAligned) {
    return {
      signal: 'WAIT',
      type: 'TRAP_WARNING',
      confidence: 30,
      entry: null,
      stop: null,
      target: null,
      reasoning: 'Flow bullish but price NOT confirming = potential reversal trap',
      timeHorizon: 'N/A',
      invalidation: 'Wait for tape alignment or price confirmation'
    };
  }
  
  // Pattern 4: 🟢 + 💎 but NO ⚡ = SLOW ACCUMULATION
  if (round === '🟢' && hasDiamond && !hasFlash) {
    return {
      signal: 'BUY',
      type: 'SLOW_ACCUMULATION',
      confidence: calculateConfidence(row, 'BUY') * 0.7, // Lower confidence
      entry: generateEntryStrategy(row, 'BUY', 'SWING'),
      stop: generateStopLoss(row, 'BUY', 'SWING'),
      target: generateTarget(row, 'BUY', 'SWING'),
      reasoning: 'Slow accumulation: Build position over 2-3 days (swing trade, not scalp)',
      timeHorizon: 'SWING',
      invalidation: generateInvalidation(row, 'BUY')
    };
  }
  
  // Pattern 5: 🔴 + 💎 but NO ⚡ = SLOW DISTRIBUTION
  if (round === '🔴' && hasDiamond && !hasFlash) {
    return {
      signal: 'SHORT',
      type: 'SLOW_DISTRIBUTION',
      confidence: calculateConfidence(row, 'SHORT') * 0.7,
      entry: generateEntryStrategy(row, 'SHORT', 'SWING'),
      stop: generateStopLoss(row, 'SHORT', 'SWING'),
      target: generateTarget(row, 'SHORT', 'SWING'),
      reasoning: 'Slow distribution: Build position over 2-3 days (swing trade)',
      timeHorizon: 'SWING',
      invalidation: generateInvalidation(row, 'SHORT')
    };
  }
  
  // Default: Weak signal or no clear pattern
  return {
    signal: 'NEUTRAL',
    type: 'NO_CLEAR_PATTERN',
    confidence: Math.min(calculateConfidence(row, direction), 40),
    entry: null,
    stop: null,
    target: null,
    reasoning: 'No clear badge pattern match',
    timeHorizon: 'N/A',
    invalidation: 'Wait for stronger signal'
  };
}

/**
 * Calculate confidence percentage based on multiple factors
 */
function calculateConfidence(row, direction) {
  let confidence = 50; // Base confidence
  
  const rocketScore = row.rocketScore || row.rocket_score || 0;
  const tapeAligned = row.tapeAligned || row.tape_alignment === 1;
  const hasCatalyst = row.near_alert_type || row.catalyst_flag;
  const premium = row.premium_num || 0;
  const netPremium = (row.bull_total || 0) - (row.bear_total || 0);
  
  // Flow trend contribution (0-15 points)
  const flowTrend = row.flowTrendRaw || row.flowTrend?.full;
  if (flowTrend) {
    if (flowTrend.trend === 'SURGING') {
      confidence += 15; // Strong boost for surging flow
    } else if (flowTrend.trend === 'STABLE') {
      confidence += 5; // Small boost for stable flow
    } else if (flowTrend.trend === 'FADING') {
      confidence -= 10; // Penalty for fading flow
    } else if (flowTrend.trend === 'DEAD') {
      confidence -= 20; // Strong penalty for dead flow
    }
  }
  
  // Rocket score contribution (0-30 points)
  confidence += Math.min(rocketScore * 4, 30);
  
  // Tape alignment (10 points)
  if (tapeAligned) confidence += 10;
  
  // Catalyst presence (10 points)
  if (hasCatalyst) confidence += 10;
  
  // Premium size (0-10 points)
  if (premium > 1000000) confidence += 10;
  else if (premium > 500000) confidence += 7;
  else if (premium > 200000) confidence += 5;
  
  // Net premium strength (0-10 points)
  const absNetPrem = Math.abs(netPremium);
  if (absNetPrem > 2000000) confidence += 10;
  else if (absNetPrem > 1000000) confidence += 7;
  else if (absNetPrem > 500000) confidence += 5;
  
  // Cap at 95% max, floor at 5% min
  return Math.max(5, Math.min(Math.round(confidence), 95));
}

/**
 * Generate entry strategy
 */
function generateEntryStrategy(row, direction, timeHorizon = 'INTRADAY') {
  const currentPrice = row.u_close || row.spot_num || row.Price || 0;
  const rthOpen = row.rth_open || currentPrice;
  const session = row.session_bucket || 'RTH';
  
  if (!currentPrice || currentPrice === 0) {
    return {
      primary: 'Price data unavailable',
      aggressive: null,
      notes: 'Wait for price data'
    };
  }
  
  if (direction === 'BUY') {
    if (timeHorizon === 'SWING') {
      return {
        primary: `Build position on pullbacks to $${(currentPrice * 0.98).toFixed(2)}`,
        aggressive: `Enter at $${currentPrice.toFixed(2)} if momentum continues`,
        notes: 'Accumulate over 2-3 days'
      };
    }
    
    // Intraday: Wait for VWAP pullback
    const vwapPullback = currentPrice * 0.995; // ~0.5% below current
    const openingRangeHigh = rthOpen * 1.01; // 1% above RTH open
    
    return {
      primary: `Wait for pullback to $${vwapPullback.toFixed(2)} (VWAP retest)`,
      aggressive: `Market order if breaks $${openingRangeHigh.toFixed(2)} (opening range high)`,
      notes: 'Enter on retest for better risk/reward'
    };
  } else if (direction === 'SHORT') {
    if (timeHorizon === 'SWING') {
      return {
        primary: `Build position on rallies to $${(currentPrice * 1.02).toFixed(2)}`,
        aggressive: `Enter at $${currentPrice.toFixed(2)} if momentum continues`,
        notes: 'Accumulate over 2-3 days'
      };
    }
    
    // Intraday: Wait for rally into VWAP or resistance
    const vwapRally = currentPrice * 1.005; // ~0.5% above current
    const openingRangeLow = rthOpen * 0.99; // 1% below RTH open
    
    return {
      primary: `Wait for rally to $${vwapRally.toFixed(2)} (VWAP or resistance)`,
      aggressive: `Market order if breaks $${openingRangeLow.toFixed(2)} (opening range low)`,
      notes: 'Enter on rally for better risk/reward'
    };
  }
  
  return null;
}

/**
 * Generate stop loss levels
 */
function generateStopLoss(row, direction, timeHorizon = 'INTRADAY') {
  const currentPrice = row.u_close || row.spot_num || row.Price || 0;
  const rthOpen = row.rth_open || currentPrice;
  
  if (!currentPrice || currentPrice === 0) {
    return {
      tight: 'Price data unavailable',
      wide: 'Price data unavailable'
    };
  }
  
  if (direction === 'BUY') {
    const tightStop = currentPrice * 0.992; // -0.8%
    const wideStop = Math.min(currentPrice * 0.985, rthOpen * 0.985); // -1.5% or below opening range low
    
    return {
      tight: `$${tightStop.toFixed(2)} (-0.8% risk)`,
      wide: `$${wideStop.toFixed(2)} (-1.5% risk or below opening range low)`,
      riskPct: timeHorizon === 'SWING' ? 2.0 : 1.5
    };
  } else if (direction === 'SHORT') {
    const tightStop = currentPrice * 1.008; // +0.8%
    const wideStop = Math.max(currentPrice * 1.015, rthOpen * 1.015); // +1.5% or above opening range high
    
    return {
      tight: `$${tightStop.toFixed(2)} (+0.8% risk)`,
      wide: `$${wideStop.toFixed(2)} (+1.5% risk or above opening range high)`,
      riskPct: timeHorizon === 'SWING' ? 2.0 : 1.5
    };
  }
  
  return null;
}

/**
 * Generate profit targets
 */
function generateTarget(row, direction, timeHorizon = 'INTRADAY') {
  const currentPrice = row.u_close || row.spot_num || row.Price || 0;
  const strike = row.strike_num || currentPrice;
  
  if (!currentPrice || currentPrice === 0) {
    return {
      t1: 'Price data unavailable',
      t2: null,
      t3: null
    };
  }
  
  if (direction === 'BUY') {
    // T1: +1.5%, take 50%
    const t1 = currentPrice * 1.015;
    // T2: +2.3%, take 30%
    const t2 = currentPrice * 1.023;
    // T3: Next gamma strike or +3.4%, runner 20%
    const t3 = timeHorizon === 'SWING' 
      ? currentPrice * 1.034 
      : Math.max(strike * 1.01, currentPrice * 1.034);
    
    return {
      t1: `$${t1.toFixed(2)} (+1.5%, take 50%)`,
      t2: `$${t2.toFixed(2)} (+2.3%, take 30%)`,
      t3: `$${t3.toFixed(2)} (${timeHorizon === 'SWING' ? '+3.4%' : 'Next gamma strike or +3.4%'}, runner 20%)`
    };
  } else if (direction === 'SHORT') {
    // T1: -1.5%, take 50%
    const t1 = currentPrice * 0.985;
    // T2: -2.3%, take 30%
    const t2 = currentPrice * 0.977;
    // T3: Prior day low or -3.4%, runner 20%
    const priorLow = row.prior_close ? row.prior_close * 0.97 : currentPrice * 0.966;
    const t3 = timeHorizon === 'SWING' 
      ? currentPrice * 0.966 
      : Math.min(priorLow, currentPrice * 0.966);
    
    return {
      t1: `$${t1.toFixed(2)} (-1.5%, take 50%)`,
      t2: `$${t2.toFixed(2)} (-2.3%, take 30%)`,
      t3: `$${t3.toFixed(2)} (${timeHorizon === 'SWING' ? '-3.4%' : 'Prior day low or -3.4%'}, runner 20%)`
    };
  }
  
  return null;
}

/**
 * Generate invalidation conditions
 */
function generateInvalidation(row, direction) {
  const currentPrice = row.u_close || row.spot_num || row.Price || 0;
  const stopLevel = direction === 'BUY' 
    ? currentPrice * 0.985 
    : currentPrice * 1.015;
  
  const conditions = [];
  
  if (direction === 'BUY') {
    conditions.push(`If breaks below $${stopLevel.toFixed(2)}, INSTITUTIONS WRONG → Exit immediately`);
    conditions.push('If no follow-through in 30min → Exit breakeven');
    conditions.push('If new bearish flow appears → Reverse bias');
  } else {
    conditions.push(`If breaks above $${stopLevel.toFixed(2)}, INSTITUTIONS WRONG → Exit immediately`);
    conditions.push('If no follow-through in 30min → Exit breakeven');
    conditions.push('If new bullish flow appears → Reverse bias');
  }
  
  return conditions;
}

/**
 * Format trade signal for display
 */
export function formatTradeSignal(signal) {
  if (!signal || signal.signal === 'NEUTRAL') {
    return {
      display: 'NEUTRAL',
      color: 'gray',
      icon: '⚪'
    };
  }
  
  const icons = {
    'BUY': '🟢',
    'SHORT': '🔴',
    'WAIT': '⚠️',
    'NEUTRAL': '⚪'
  };
  
  const colors = {
    'BUY': 'green',
    'SHORT': 'red',
    'WAIT': 'yellow',
    'NEUTRAL': 'gray'
  };
  
  return {
    display: `${icons[signal.signal]} ${signal.signal} (${signal.confidence}%)`,
    color: colors[signal.signal],
    icon: icons[signal.signal],
    full: signal
  };
}

