/**
 * Web Worker 기반 보조지표 계산 훅
 * - 메인 스레드를 차단하지 않고 지표 계산
 * - 복잡한 계산을 백그라운드에서 처리
 */

import { useEffect, useRef, useCallback } from 'react';
import type { CandleData } from '../services/backtestApi';

interface IndicatorConfig {
  maPeriods?: number[];
  rsi?: boolean;
  rsiPeriod?: number;
  macd?: boolean;
  macdFastPeriod?: number;
  macdSlowPeriod?: number;
  macdSignalPeriod?: number;
  stochastic?: boolean;
  stochasticKPeriod?: number;
  stochasticDPeriod?: number;
}

interface WorkerMessage {
  type: string;
  data?: any;
  error?: string;
}

export function useIndicatorWorker() {
  const workerRef = useRef<Worker | null>(null);
  const callbacksRef = useRef<Map<string, (data: any) => void>>(new Map());

  // Worker 초기화
  useEffect(() => {
    try {
      const worker = new Worker('/indicator.worker.js');
      
      worker.onmessage = (event: MessageEvent<WorkerMessage>) => {
        const { type, data, error } = event.data;
        
        if (error) {
          console.error('❌ [Worker Error]:', error);
          return;
        }
        
        const callback = callbacksRef.current.get(type);
        if (callback) {
          callback(data);
          callbacksRef.current.delete(type);
        }
      };
      
      worker.onerror = (error) => {
        console.error('❌ [Worker Error]:', error);
      };
      
      workerRef.current = worker;
      console.log('✅ [Indicator Worker] 초기화 완료');
      
      return () => {
        worker.terminate();
        console.log('🛑 [Indicator Worker] 종료');
      };
    } catch (error) {
      console.error('❌ [Indicator Worker] 초기화 실패:', error);
    }
  }, []);

  /**
   * 이동평균선 계산
   */
  const calculateMA = useCallback(
    (candles: CandleData[], periods: number[]): Promise<Record<string, (number | null)[]>> => {
      return new Promise((resolve, reject) => {
        if (!workerRef.current) {
          reject(new Error('Worker not initialized'));
          return;
        }

        callbacksRef.current.set('MA_RESULT', resolve);
        
        workerRef.current.postMessage({
          type: 'CALCULATE_MA',
          data: { candles, periods },
        });

        // 타임아웃 설정 (10초)
        setTimeout(() => {
          if (callbacksRef.current.has('MA_RESULT')) {
            callbacksRef.current.delete('MA_RESULT');
            reject(new Error('MA calculation timeout'));
          }
        }, 10000);
      });
    },
    []
  );

  /**
   * RSI 계산
   */
  const calculateRSI = useCallback(
    (candles: CandleData[], period: number = 14): Promise<(number | null)[]> => {
      return new Promise((resolve, reject) => {
        if (!workerRef.current) {
          reject(new Error('Worker not initialized'));
          return;
        }

        callbacksRef.current.set('RSI_RESULT', resolve);
        
        workerRef.current.postMessage({
          type: 'CALCULATE_RSI',
          data: { candles, period },
        });

        setTimeout(() => {
          if (callbacksRef.current.has('RSI_RESULT')) {
            callbacksRef.current.delete('RSI_RESULT');
            reject(new Error('RSI calculation timeout'));
          }
        }, 10000);
      });
    },
    []
  );

  /**
   * MACD 계산
   */
  const calculateMACD = useCallback(
    (
      candles: CandleData[],
      fastPeriod: number = 12,
      slowPeriod: number = 26,
      signalPeriod: number = 9
    ): Promise<{
      macdLine: (number | null)[];
      signalLine: (number | null)[];
      histogram: (number | null)[];
    }> => {
      return new Promise((resolve, reject) => {
        if (!workerRef.current) {
          reject(new Error('Worker not initialized'));
          return;
        }

        callbacksRef.current.set('MACD_RESULT', resolve);
        
        workerRef.current.postMessage({
          type: 'CALCULATE_MACD',
          data: { candles, fastPeriod, slowPeriod, signalPeriod },
        });

        setTimeout(() => {
          if (callbacksRef.current.has('MACD_RESULT')) {
            callbacksRef.current.delete('MACD_RESULT');
            reject(new Error('MACD calculation timeout'));
          }
        }, 10000);
      });
    },
    []
  );

  /**
   * Stochastic 계산
   */
  const calculateStochastic = useCallback(
    (
      candles: CandleData[],
      kPeriod: number = 14,
      dPeriod: number = 3
    ): Promise<{
      stochK: (number | null)[];
      stochD: (number | null)[];
    }> => {
      return new Promise((resolve, reject) => {
        if (!workerRef.current) {
          reject(new Error('Worker not initialized'));
          return;
        }

        callbacksRef.current.set('STOCHASTIC_RESULT', resolve);
        
        workerRef.current.postMessage({
          type: 'CALCULATE_STOCHASTIC',
          data: { candles, kPeriod, dPeriod },
        });

        setTimeout(() => {
          if (callbacksRef.current.has('STOCHASTIC_RESULT')) {
            callbacksRef.current.delete('STOCHASTIC_RESULT');
            reject(new Error('Stochastic calculation timeout'));
          }
        }, 10000);
      });
    },
    []
  );

  /**
   * 모든 지표 한 번에 계산
   */
  const calculateAll = useCallback(
    (candles: CandleData[], config: IndicatorConfig): Promise<Record<string, any>> => {
      return new Promise((resolve, reject) => {
        if (!workerRef.current) {
          reject(new Error('Worker not initialized'));
          return;
        }

        callbacksRef.current.set('ALL_RESULT', resolve);
        
        workerRef.current.postMessage({
          type: 'CALCULATE_ALL',
          data: { candles, config },
        });

        setTimeout(() => {
          if (callbacksRef.current.has('ALL_RESULT')) {
            callbacksRef.current.delete('ALL_RESULT');
            reject(new Error('Indicator calculation timeout'));
          }
        }, 15000);
      });
    },
    []
  );

  return {
    calculateMA,
    calculateRSI,
    calculateMACD,
    calculateStochastic,
    calculateAll,
  };
}
