/**
 * Support/Resistance Calculator
 * Calculates pivot points and swing highs/lows for chart overlay
 */

/**
 * Calculate pivot points (Standard, Fibonacci, Camarilla)
 */
export function calculatePivotPoints(high, low, close) {
  if (!high || !low || !close) return null;

  const pivot = (high + low + close) / 3;
  const range = high - low;

  return {
    // Standard Pivot Points
    pivot: pivot,
    r1: 2 * pivot - low,
    r2: pivot + range,
    r3: high + 2 * (pivot - low),
    s1: 2 * pivot - high,
    s2: pivot - range,
    s3: low - 2 * (high - pivot),
    
    // Fibonacci Pivot Points
    fibR1: pivot + 0.382 * range,
    fibR2: pivot + 0.618 * range,
    fibR3: pivot + 1.0 * range,
    fibS1: pivot - 0.382 * range,
    fibS2: pivot - 0.618 * range,
    fibS3: pivot - 1.0 * range,
    
    // Camarilla Pivot Points
    camR1: close + range * 1.1 / 12,
    camR2: close + range * 1.1 / 6,
    camR3: close + range * 1.1 / 4,
    camR4: close + range * 1.1 / 2,
    camS1: close - range * 1.1 / 12,
    camS2: close - range * 1.1 / 6,
    camS3: close - range * 1.1 / 4,
    camS4: close - range * 1.1 / 2,
  };
}

/**
 * Detect swing highs and lows from price data
 * @param {Array} candles - Array of {time, high, low, close}
 * @param {number} lookback - Number of periods to look back/forward for swing detection
 * @returns {Object} {swingHighs: [], swingLows: []}
 */
export function detectSwingPoints(candles, lookback = 5) {
  if (!candles || candles.length < lookback * 2 + 1) {
    return { swingHighs: [], swingLows: [] };
  }

  const swingHighs = [];
  const swingLows = [];

  for (let i = lookback; i < candles.length - lookback; i++) {
    const current = candles[i];
    let isSwingHigh = true;
    let isSwingLow = true;

    // Check if current high is higher than surrounding highs
    for (let j = i - lookback; j <= i + lookback; j++) {
      if (j !== i) {
        if (candles[j].high >= current.high) {
          isSwingHigh = false;
        }
        if (candles[j].low <= current.low) {
          isSwingLow = false;
        }
      }
    }

    if (isSwingHigh) {
      swingHighs.push({
        price: current.high,
        time: current.time,
        strength: calculateSwingStrength(candles, i, 'high', lookback)
      });
    }

    if (isSwingLow) {
      swingLows.push({
        price: current.low,
        time: current.time,
        strength: calculateSwingStrength(candles, i, 'low', lookback)
      });
    }
  }

  return { swingHighs, swingLows };
}

/**
 * Calculate strength of swing point based on:
 * - How many times it was tested
 * - Volume at the point
 * - Time since formation
 */
function calculateSwingStrength(candles, index, type, lookback) {
  const swingPrice = type === 'high' ? candles[index].high : candles[index].low;
  let touches = 1; // The swing point itself
  let volume = candles[index].volume || 0;

  // Count how many times price came close to this level
  for (let i = Math.max(0, index - 50); i < Math.min(candles.length, index + 50); i++) {
    if (i !== index) {
      const distance = Math.abs(
        (type === 'high' ? candles[i].high : candles[i].low) - swingPrice
      ) / swingPrice;
      
      if (distance < 0.01) { // Within 1%
        touches++;
        volume += candles[i].volume || 0;
      }
    }
  }

  // Strength score: 1-10
  let strength = Math.min(10, Math.floor(touches / 2) + Math.min(5, Math.floor(volume / 1000000)));
  
  return Math.max(1, Math.min(10, strength));
}

/**
 * Identify key support/resistance levels from multiple methods
 * @param {Array} candles - Price data
 * @param {Object} dailyData - Previous day's OHLC
 * @returns {Object} Combined S/R levels with metadata
 */
export function calculateSupportResistance(candles, dailyData = null) {
  if (!candles || candles.length === 0) {
    return {
      supports: [],
      resistances: [],
      pivotPoints: null,
      currentPrice: null
    };
  }

  const currentPrice = candles[candles.length - 1].close;
  const recentHigh = Math.max(...candles.slice(-20).map(c => c.high));
  const recentLow = Math.min(...candles.slice(-20).map(c => c.low));
  const recentClose = currentPrice;

  // Calculate pivot points
  let pivotPoints = null;
  if (dailyData) {
    pivotPoints = calculatePivotPoints(
      dailyData.high || recentHigh,
      dailyData.low || recentLow,
      dailyData.close || recentClose
    );
  } else {
    // Use recent period if no daily data
    pivotPoints = calculatePivotPoints(recentHigh, recentLow, recentClose);
  }

  // Detect swing points
  const { swingHighs, swingLows } = detectSwingPoints(candles, 5);

  // Combine and rank levels
  const allLevels = [];

  // Add pivot points
  if (pivotPoints) {
    allLevels.push(
      { price: pivotPoints.s3, type: 'support', source: 'pivot', strength: 8, label: 'S3' },
      { price: pivotPoints.s2, type: 'support', source: 'pivot', strength: 7, label: 'S2' },
      { price: pivotPoints.s1, type: 'support', source: 'pivot', strength: 9, label: 'S1' },
      { price: pivotPoints.pivot, type: 'neutral', source: 'pivot', strength: 10, label: 'Pivot' },
      { price: pivotPoints.r1, type: 'resistance', source: 'pivot', strength: 9, label: 'R1' },
      { price: pivotPoints.r2, type: 'resistance', source: 'pivot', strength: 7, label: 'R2' },
      { price: pivotPoints.r3, type: 'resistance', source: 'pivot', strength: 8, label: 'R3' }
    );
  }

  // Add swing highs (resistance)
  swingHighs.forEach(swing => {
    if (swing.price > currentPrice * 0.95 && swing.price < currentPrice * 1.15) {
      allLevels.push({
        price: swing.price,
        type: 'resistance',
        source: 'swing',
        strength: swing.strength,
        label: `Swing High`,
        time: swing.time
      });
    }
  });

  // Add swing lows (support)
  swingLows.forEach(swing => {
    if (swing.price < currentPrice * 1.05 && swing.price > currentPrice * 0.85) {
      allLevels.push({
        price: swing.price,
        type: 'support',
        source: 'swing',
        strength: swing.strength,
        label: `Swing Low`,
        time: swing.time
      });
    }
  });

  // Filter and sort levels
  const supports = allLevels
    .filter(level => level.type === 'support' && level.price < currentPrice * 1.02)
    .sort((a, b) => b.price - a.price) // Highest support first
    .slice(0, 5); // Top 5 supports

  const resistances = allLevels
    .filter(level => level.type === 'resistance' && level.price > currentPrice * 0.98)
    .sort((a, b) => a.price - b.price) // Lowest resistance first
    .slice(0, 5); // Top 5 resistances

  return {
    supports,
    resistances,
    pivotPoints,
    currentPrice,
    nearestSupport: supports[0] || null,
    nearestResistance: resistances[0] || null
  };
}

/**
 * Calculate price positioning relative to S/R levels
 */
export function calculatePricePositioning(currentPrice, srLevels) {
  if (!currentPrice || !srLevels) {
    return null;
  }

  const nearestSupport = srLevels.nearestSupport;
  const nearestResistance = srLevels.nearestResistance;

  let positioning = {
    currentPrice,
    distanceToSupport: null,
    distanceToResistance: null,
    supportPct: null,
    resistancePct: null,
    zone: 'MIDDLE', // BELOW_SUPPORT, NEAR_SUPPORT, MIDDLE, NEAR_RESISTANCE, ABOVE_RESISTANCE
    riskLevel: 'MEDIUM'
  };

  if (nearestSupport) {
    positioning.distanceToSupport = currentPrice - nearestSupport.price;
    positioning.supportPct = (positioning.distanceToSupport / currentPrice) * 100;
  }

  if (nearestResistance) {
    positioning.distanceToResistance = nearestResistance.price - currentPrice;
    positioning.resistancePct = (positioning.distanceToResistance / currentPrice) * 100;
  }

  // Determine zone
  if (nearestSupport && nearestResistance) {
    const range = nearestResistance.price - nearestSupport.price;
    const positionInRange = (currentPrice - nearestSupport.price) / range;

    if (positionInRange < 0.2) {
      positioning.zone = 'NEAR_SUPPORT';
      positioning.riskLevel = 'LOW'; // Near support = lower risk for longs
    } else if (positionInRange < 0.4) {
      positioning.zone = 'BELOW_MIDDLE';
    } else if (positionInRange < 0.6) {
      positioning.zone = 'MIDDLE';
    } else if (positionInRange < 0.8) {
      positioning.zone = 'ABOVE_MIDDLE';
    } else {
      positioning.zone = 'NEAR_RESISTANCE';
      positioning.riskLevel = 'HIGH'; // Near resistance = higher risk for longs
    }
  } else if (nearestSupport && !nearestResistance) {
    if (positioning.supportPct < 2) {
      positioning.zone = 'NEAR_SUPPORT';
      positioning.riskLevel = 'LOW';
    } else {
      positioning.zone = 'ABOVE_SUPPORT';
    }
  } else if (nearestResistance && !nearestSupport) {
    if (positioning.resistancePct < 2) {
      positioning.zone = 'NEAR_RESISTANCE';
      positioning.riskLevel = 'HIGH';
    } else {
      positioning.zone = 'BELOW_RESISTANCE';
    }
  }

  return positioning;
}

