/**
 * Realtime Data WebSocket Hook (Backend 연결)
 * - Backend의 RealtimeWebSocketHandler와 연결
 * - 캔들 생성 로직 없음 (Backend에서 처리)
 * - 자동 재연결
 * - 멀티 타임프레임 지원
 */
import { useState, useEffect, useRef, useCallback } from 'react';
import { getApiBaseUrl } from '../services/apiConfig';

interface Candle {
  time: number;          // timestamp (ms)
  open: number;
  high: number;
  low: number;
  close: number;
  volume: number;
  is_closed?: boolean;   // 캔들 완료 여부
  trade_count?: number;  // trade 횟수
}

interface Indicators {
  // RSI
  rsi_14?: number;
  
  // EMA
  ema_9?: number;
  ema_21?: number;
  
  // MACD
  macd?: number;
  macd_signal?: number;
  macd_histogram?: number;
  
  // Bollinger Bands
  bb_upper?: number;
  bb_middle?: number;
  bb_lower?: number;
  
  // Stochastic
  stoch_k?: number;
  stoch_d?: number;
  
  // ADX
  adx?: number;
  plus_di?: number;
  minus_di?: number;
  
  // Moving Averages
  ma_5?: number;
  ma_10?: number;
  ma_20?: number;
  ma_60?: number;
  ma_120?: number;
  
  // Ichimoku Cloud
  ichimoku_tenkan?: number;
  ichimoku_kijun?: number;
  ichimoku_senkou_a?: number;
  ichimoku_senkou_b?: number;
  ichimoku_chikou?: number;
}

interface UseRealtimeWebSocketOptions {
  market: string;
  timeframe: string;
  enabled?: boolean;
  onData?: (data: { candles: Candle[]; indicators?: Indicators; isUpdate?: boolean }) => void;
  onError?: (error: any) => void;
}

type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'error';

const getRealtimeWsEndpoint = (): string => {
  const envWsUrl = process.env.REACT_APP_WS_URL;
  if (envWsUrl) {
    const base = envWsUrl.replace(/\/+$/, '');
    if (/\/ws\//i.test(base) || /\/api\/ws\//i.test(base)) return base;
    return `${base}/api/ws/realtime`;
  }
  const apiBase = getApiBaseUrl().replace(/\/+$/, '');
  const wsBase = apiBase.replace(/^http:\/\//i, 'ws://').replace(/^https:\/\//i, 'wss://');
  return `${wsBase}/ws/realtime`;
};

const REALTIME_WS_ENDPOINT = getRealtimeWsEndpoint();

export const useRealtimeWebSocket = ({
  market,
  timeframe,
  enabled = true,
  onData,
  onError,
}: UseRealtimeWebSocketOptions) => {
  const [status, setStatus] = useState<ConnectionStatus>('disconnected');
  const [candles, setCandles] = useState<Candle[]>([]);
  const [indicators, setIndicators] = useState<Indicators>({});
  
  const wsRef = useRef<WebSocket | null>(null);
  const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
  const reconnectAttemptsRef = useRef(0);
  const onDataRef = useRef(onData);
  const onErrorRef = useRef(onError);

  // Ref 업데이트
  useEffect(() => {
    onDataRef.current = onData;
    onErrorRef.current = onError;
  }, [onData, onError]);

  /**
   * 초기 데이터 로드 (REST API)
   */
  const loadInitialData = useCallback(async () => {
    try {
      const response = await fetch(
        `${getApiBaseUrl().replace(/\/$/, '')}/realtime/candles?market=${market}&timeframe=${timeframe}&limit=200`
      );
      
      if (!response.ok) throw new Error(`HTTP ${response.status}`);
      
      const result = await response.json();
      
      if (result.success && result.data && result.data.length > 0) {
        // Backend에서 timestamp, open, high, low, close, volume 형식으로 반환
        const candlesData = result.data.map((item: any) => ({
          time: item.timestamp,
          open: item.open,
          high: item.high,
          low: item.low,
          close: item.close,
          volume: item.volume,
        }));
        
        setCandles(candlesData);
        
        // 마지막 캔들의 지표 (있다면)
        const lastIndicators = result.data[result.data.length - 1].indicators || {};
        setIndicators(lastIndicators);
        
        onDataRef.current?.({ candles: candlesData, indicators: lastIndicators });
        
        console.log('[Realtime WS] Initial data loaded:', candlesData.length, 'candles');
      }
    } catch (error) {
      console.error('[Realtime WS] Failed to load initial data:', error);
      onErrorRef.current?.(error);
    }
  }, [market, timeframe]);

  /**
   * WebSocket 연결
   */
  const connect = useCallback(() => {
    if (!enabled) {
      console.log('[Realtime WS] WebSocket disabled');
      return;
    }
    
    if (wsRef.current) {
      const state = wsRef.current.readyState;
      if (state === WebSocket.CONNECTING || state === WebSocket.OPEN) {
        console.log(`[Realtime WS] Already connecting/connected (readyState: ${state})`);
        return;
      }
    }
    
    setStatus('connecting');
    console.log(`[Realtime WS] Connecting to ${REALTIME_WS_ENDPOINT}...`);
    console.log(`[Realtime WS] Market: ${market}, Timeframe: ${timeframe}`);
    
    const ws = new WebSocket(REALTIME_WS_ENDPOINT);
    
    ws.onopen = () => {
      console.log('✅ [Realtime WS] Connected successfully!');
      setStatus('connected');
      reconnectAttemptsRef.current = 0;
      
      // 구독 요청
      const subscribeMsg = {
        type: 'subscribe',
        market,
        timeframe,
      };
      ws.send(JSON.stringify(subscribeMsg));
      
      console.log(`📡 [Realtime WS] Subscription request sent:`, subscribeMsg);
      
      // 초기 데이터 로드
      loadInitialData();
    };
    
    ws.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        
        if (data.type === 'connected') {
          console.log(`[Realtime WS] Connection confirmed: ${data.sessionId}`);
        }
        else if (data.type === 'subscribed') {
          console.log(`[Realtime WS] Subscription confirmed: ${data.market} ${data.timeframe}`);
        }
        else if (data.type === 'update') {
          // 실시간 업데이트
          const newCandle: Candle = data.candle;
          const newIndicators = data.indicators || {};
          
          console.log(`📊 [Realtime WS] Update received:`, {
            time: newCandle.time,
            close: newCandle.close,
            volume: newCandle.volume,
            is_closed: newCandle.is_closed,
          });
          
          setCandles((prevCandles) => {
            const updated = [...prevCandles];
            
            if (updated.length === 0) {
              const result = [newCandle];
              onDataRef.current?.({ 
                candles: result, 
                indicators: newIndicators,
                isUpdate: true
              });
              return result;
            }
            
            const lastCandle = updated[updated.length - 1];
            
            // 과거 데이터 무시
            if (newCandle.time < lastCandle.time) {
              console.warn(`⚠️ [Realtime WS] Old candle ignored: new=${newCandle.time}, last=${lastCandle.time}`);
              return updated;
            }
            
            if (lastCandle.time === newCandle.time) {
              // 현재 캔들 업데이트
              updated[updated.length - 1] = newCandle;
              console.log(`✅ [Realtime WS] Candle updated: ${newCandle.time}`);
            } else if (newCandle.time > lastCandle.time) {
              // 새 캔들 추가
              updated.push(newCandle);
              console.log(`✅ [Realtime WS] New candle added: ${newCandle.time}`);
              
              // 최대 200개 유지
              if (updated.length > 200) {
                updated.shift();
              }
            }
            
            onDataRef.current?.({ 
              candles: updated, 
              indicators: newIndicators,
              isUpdate: true
            });
            
            return updated;
          });
          
          setIndicators(newIndicators);
        }
        else if (data.type === 'pong') {
          // Ping/Pong
        }
        else if (data.type === 'error') {
          console.error('[Realtime WS] Server error:', data.message);
          onErrorRef.current?.(new Error(data.message));
        }
        
      } catch (error) {
        console.error('[Realtime WS] Message parsing error:', error);
        onErrorRef.current?.(error);
      }
    };
    
    ws.onerror = (event) => {
      console.error('❌ [Realtime WS] WebSocket error:', event);
      setStatus('error');
      onErrorRef.current?.(event);
    };
    
    ws.onclose = (event) => {
      console.log(`🔌 [Realtime WS] WebSocket closed: Code ${event.code}, Reason: "${event.reason || 'No reason'}"`);
      
      if (wsRef.current === ws) {
        wsRef.current = null;
      } else {
        console.log('[Realtime WS] Already cleaned up by disconnect(), skipping reconnect');
        return;
      }
      
      setStatus('disconnected');
      
      // 자동 재연결
      const MAX_RETRIES = 3;
      
      if (enabled && !reconnectTimeoutRef.current && reconnectAttemptsRef.current < MAX_RETRIES) {
        const delay = Math.min(1000 * Math.pow(2, reconnectAttemptsRef.current), 10000);
        reconnectAttemptsRef.current += 1;
        
        console.log(`🔄 [Realtime WS] Auto-reconnect attempt #${reconnectAttemptsRef.current}/${MAX_RETRIES} in ${delay}ms...`);
        
        reconnectTimeoutRef.current = setTimeout(() => {
          reconnectTimeoutRef.current = null;
          connect();
        }, delay);
      } else if (reconnectAttemptsRef.current >= MAX_RETRIES) {
        console.error(`❌ [Realtime WS] ${MAX_RETRIES}회 재연결 실패`);
      }
    };
    
    wsRef.current = ws;
    
  }, [enabled, market, timeframe, loadInitialData]);

  /**
   * 연결 해제
   */
  const disconnect = useCallback(() => {
    console.log('[Realtime WS] Disconnect called');
    
    if (reconnectTimeoutRef.current) {
      clearTimeout(reconnectTimeoutRef.current);
      reconnectTimeoutRef.current = null;
    }
    
    if (wsRef.current) {
      const ws = wsRef.current;
      wsRef.current = null;
      
      try {
        if (ws.readyState === WebSocket.OPEN) {
          ws.send(JSON.stringify({ type: 'unsubscribe' }));
        }
        
        ws.onopen = null;
        ws.onmessage = null;
        ws.onerror = null;
        ws.onclose = null;
        
        if (ws.readyState !== WebSocket.CLOSED) {
          ws.close();
        }
        
        console.log('[Realtime WS] WebSocket cleaned up');
      } catch (error) {
        console.error('[Realtime WS] Error during disconnect:', error);
      }
    }
    
    setStatus('disconnected');
  }, []);

  /**
   * Ping 전송
   */
  const sendPing = useCallback(() => {
    if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {
      wsRef.current.send(JSON.stringify({ type: 'ping' }));
    }
  }, []);

  // 자동 연결/해제
  useEffect(() => {
    console.log(`🔌 [Realtime WS useEffect] enabled=${enabled}, market=${market}, timeframe=${timeframe}`);
    
    if (enabled) {
      connect();
    } else {
      disconnect();
    }
    
    return () => {
      disconnect();
    };
  }, [enabled, market, timeframe, connect, disconnect]);

  // Keepalive (30초마다 ping)
  useEffect(() => {
    if (status !== 'connected') return;
    
    const interval = setInterval(() => {
      sendPing();
    }, 30000);
    
    return () => clearInterval(interval);
  }, [status, sendPing]);

  return {
    status,
    candles,
    indicators,
    connect,
    disconnect,
  };
};
