/**
 * 보조지표 계산 Web Worker
 * - 메인 스레드를 차단하지 않고 지표 계산
 * - 복잡한 계산(MA, RSI, MACD 등)을 백그라운드에서 처리
 */

self.addEventListener('message', (event) => {
  const { type, data } = event.data;

  try {
    switch (type) {
      case 'CALCULATE_MA':
        const maResult = calculateMA(data.candles, data.periods);
        self.postMessage({ type: 'MA_RESULT', data: maResult });
        break;

      case 'CALCULATE_RSI':
        const rsiResult = calculateRSI(data.candles, data.period);
        self.postMessage({ type: 'RSI_RESULT', data: rsiResult });
        break;

      case 'CALCULATE_MACD':
        const macdResult = calculateMACD(data.candles, data.fastPeriod, data.slowPeriod, data.signalPeriod);
        self.postMessage({ type: 'MACD_RESULT', data: macdResult });
        break;

      case 'CALCULATE_STOCHASTIC':
        const stochResult = calculateStochastic(data.candles, data.kPeriod, data.dPeriod);
        self.postMessage({ type: 'STOCHASTIC_RESULT', data: stochResult });
        break;

      case 'CALCULATE_ALL':
        const allResults = calculateAllIndicators(data.candles, data.config);
        self.postMessage({ type: 'ALL_RESULT', data: allResults });
        break;

      default:
        self.postMessage({ type: 'ERROR', error: 'Unknown command' });
    }
  } catch (error) {
    self.postMessage({ type: 'ERROR', error: error.message });
  }
});

/**
 * 이동평균선 계산
 */
function calculateMA(candles, periods) {
  const results = {};
  
  periods.forEach(period => {
    const ma = [];
    for (let i = 0; i < candles.length; i++) {
      if (i < period - 1) {
        ma.push(null);
      } else {
        let sum = 0;
        for (let j = 0; j < period; j++) {
          sum += candles[i - j].close;
        }
        ma.push(sum / period);
      }
    }
    results[`ma${period}`] = ma;
  });
  
  return results;
}

/**
 * RSI 계산
 */
function calculateRSI(candles, period = 14) {
  const rsi = [];
  const gains = [];
  const losses = [];
  
  for (let i = 0; i < candles.length; i++) {
    if (i === 0) {
      rsi.push(null);
      continue;
    }
    
    const change = candles[i].close - candles[i - 1].close;
    gains.push(change > 0 ? change : 0);
    losses.push(change < 0 ? Math.abs(change) : 0);
    
    if (i < period) {
      rsi.push(null);
      continue;
    }
    
    const avgGain = gains.slice(-period).reduce((a, b) => a + b, 0) / period;
    const avgLoss = losses.slice(-period).reduce((a, b) => a + b, 0) / period;
    
    if (avgLoss === 0) {
      rsi.push(100);
    } else {
      const rs = avgGain / avgLoss;
      rsi.push(100 - (100 / (1 + rs)));
    }
  }
  
  return rsi;
}

/**
 * MACD 계산
 */
function calculateMACD(candles, fastPeriod = 12, slowPeriod = 26, signalPeriod = 9) {
  // EMA 계산 헬퍼
  const calculateEMA = (values, period) => {
    const ema = [];
    const multiplier = 2 / (period + 1);
    
    for (let i = 0; i < values.length; i++) {
      if (i < period - 1) {
        ema.push(null);
      } else if (i === period - 1) {
        const sum = values.slice(0, period).reduce((a, b) => a + b, 0);
        ema.push(sum / period);
      } else {
        const value = (values[i] - ema[i - 1]) * multiplier + ema[i - 1];
        ema.push(value);
      }
    }
    
    return ema;
  };
  
  const closes = candles.map(c => c.close);
  const fastEMA = calculateEMA(closes, fastPeriod);
  const slowEMA = calculateEMA(closes, slowPeriod);
  
  const macdLine = [];
  for (let i = 0; i < candles.length; i++) {
    if (fastEMA[i] === null || slowEMA[i] === null) {
      macdLine.push(null);
    } else {
      macdLine.push(fastEMA[i] - slowEMA[i]);
    }
  }
  
  const signalLine = calculateEMA(
    macdLine.map(v => v === null ? 0 : v),
    signalPeriod
  );
  
  const histogram = [];
  for (let i = 0; i < candles.length; i++) {
    if (macdLine[i] === null || signalLine[i] === null) {
      histogram.push(null);
    } else {
      histogram.push(macdLine[i] - signalLine[i]);
    }
  }
  
  return { macdLine, signalLine, histogram };
}

/**
 * Stochastic 계산
 */
function calculateStochastic(candles, kPeriod = 14, dPeriod = 3) {
  const stochK = [];
  
  for (let i = 0; i < candles.length; i++) {
    if (i < kPeriod - 1) {
      stochK.push(null);
      continue;
    }
    
    const slice = candles.slice(i - kPeriod + 1, i + 1);
    const highest = Math.max(...slice.map(c => c.high));
    const lowest = Math.min(...slice.map(c => c.low));
    const current = candles[i].close;
    
    if (highest === lowest) {
      stochK.push(50);
    } else {
      stochK.push(((current - lowest) / (highest - lowest)) * 100);
    }
  }
  
  // %D 계산 (K의 이동평균)
  const stochD = [];
  for (let i = 0; i < stochK.length; i++) {
    if (i < dPeriod - 1 || stochK[i] === null) {
      stochD.push(null);
    } else {
      const sum = stochK.slice(i - dPeriod + 1, i + 1).reduce((a, b) => a + (b || 0), 0);
      stochD.push(sum / dPeriod);
    }
  }
  
  return { stochK, stochD };
}

/**
 * 모든 지표 한 번에 계산
 */
function calculateAllIndicators(candles, config) {
  const results = {};
  
  // MA
  if (config.maPeriods && config.maPeriods.length > 0) {
    Object.assign(results, calculateMA(candles, config.maPeriods));
  }
  
  // RSI
  if (config.rsi) {
    results.rsi = calculateRSI(candles, config.rsiPeriod || 14);
  }
  
  // MACD
  if (config.macd) {
    const macd = calculateMACD(
      candles,
      config.macdFastPeriod || 12,
      config.macdSlowPeriod || 26,
      config.macdSignalPeriod || 9
    );
    results.macdLine = macd.macdLine;
    results.macdSignal = macd.signalLine;
    results.macdHistogram = macd.histogram;
  }
  
  // Stochastic
  if (config.stochastic) {
    const stoch = calculateStochastic(
      candles,
      config.stochasticKPeriod || 14,
      config.stochasticDPeriod || 3
    );
    results.stochasticK = stoch.stochK;
    results.stochasticD = stoch.stochD;
  }
  
  return results;
}

console.log('📊 Indicator Worker initialized');
