import axios from 'axios';
import { CandleData } from './backtestApi';
import { getApiBaseUrl } from './apiConfig';

const API_BASE_URL = getApiBaseUrl();

/**
 * 보조지표 데이터 인터페이스 (백엔드 IndicatorDataDto와 동일)
 */
export interface IndicatorData {
  time: string;
  macdLine?: number;
  macdSignal?: number;
  macdHistogram?: number;
  stochasticK?: number;
  stochasticD?: number;
  rsi?: number;
  obv?: number;
  obvSignal?: number;     // OBV Signal Line (이동평균)
  // ❌ EMA 사용하지 않음 - SMA만 사용
  // ema5?: number;
  // ema10?: number;
  // ema20?: number;
  // ema60?: number;
  // ema120?: number;
}

/**
 * 시그널 분석 요청 인터페이스
 * ✅ 개선: 이미 계산된 indicatorData를 전송하여 중복 계산 방지 및 정합성 보장
 */
export interface SignalAnalysisRequest {
  symbol: string;
  interval: string;
  candleData: CandleData[];
  uptrendStrategyId?: number;
  downtrendStrategyId?: number;
  
  // ✅ 핵심 개선: 프론트엔드에서 계산한 지표 데이터 전송
  indicatorData?: IndicatorData[];
  
  // 추세 판단 MA 설정 (프론트엔드에서 선택)
  trendShortMA?: number;
  trendMediumMA?: number;
  trendLongMA?: number;
  
  // MACD 파라미터 (indicatorData가 없을 때 사용)
  macdFastPeriod?: number;
  macdSlowPeriod?: number;
  macdSignalPeriod?: number;
  
  // Stochastic 파라미터 (indicatorData가 없을 때 사용)
  stochasticKPeriod?: number;
  stochasticDPeriod?: number;
  stochasticSlowing?: number;
  
  // Williams %R 파라미터 (indicatorData가 없을 때 사용)
  williamsRPeriod?: number;
  
  // RSI 파라미터 (indicatorData가 없을 때 사용)
  rsiPeriod?: number;
  rsiOversold?: number;
  rsiOverbought?: number;
  
  // CCI 파라미터
  cciOversold?: number;    // CCI 침체 기준 (기본값: -100)
  cciMiddle?: number;      // CCI 중앙 기준 (기본값: 0)
  cciOverbought?: number;  // CCI 과열 기준 (기본값: 100)
}

/**
 * 캔들 시그널 정보
 */
export interface CandleSignal {
  time: string;
  isBuyPoint: boolean;
  isSellPoint: boolean;
  signal: 'BUY' | 'SELL' | 'HOLD';
  strategyName?: string;
  trendStatus?: string;
  matchedConditions?: string[];
}

/**
 * 시그널 분석 응답 인터페이스
 */
export interface SignalAnalysisResponse {
  success: boolean;
  message?: string;
  signals: CandleSignal[];
  buySignalCount: number;
  sellSignalCount: number;
}

/**
 * 전략 기반 시그널 분석
 * ✅ 개선: 이미 계산된 indicatorData를 전송하여 중복 계산 방지 및 정합성 보장
 * 
 * @param request - 시그널 분석 요청
 *   - indicatorData: 프론트엔드에서 이미 계산한 지표 데이터 (권장)
 *   - candleData: 시간 매칭용 캔들 데이터
 */
export const analyzeSignals = async (request: SignalAnalysisRequest): Promise<SignalAnalysisResponse> => {
  console.log('📊 시그널 분석 요청:', {
    symbol: request.symbol,
    interval: request.interval,
    candleCount: request.candleData?.length,
    indicatorDataCount: request.indicatorData?.length,
    hasPreCalculatedIndicators: !!request.indicatorData,
    uptrendStrategyId: request.uptrendStrategyId,
    downtrendStrategyId: request.downtrendStrategyId
  });
  
  try {
    const response = await axios.post<SignalAnalysisResponse>(
      `${API_BASE_URL}/strategy-rules/analyze-signals`,
      request
    );
    
    // ✅ 검증: 시간 매칭 정확성 확인
    validateSignalTimeMatching(request.candleData, response.data.signals);
    
    // ✅ 검증: 중복 시그널 확인
    validateNoDuplicateSignals(response.data.signals);
    
    console.log('✅ 시그널 분석 완료:', {
      success: response.data.success,
      buySignals: response.data.buySignalCount,
      sellSignals: response.data.sellSignalCount,
      totalSignals: response.data.signals?.length,
      usedPreCalculatedData: !!request.indicatorData
    });
    
    return response.data;
  } catch (error: any) {
    console.error('❌ 시그널 분석 실패:', error.response?.data || error.message);
    throw error;
  }
};

/**
 * ✅ 시간 매칭 정확성 검증
 * 백엔드에서 반환한 시그널의 시간이 요청한 캔들 데이터의 시간과 정확히 일치하는지 확인
 */
function validateSignalTimeMatching(candleData: any[], signals: CandleSignal[]): void {
  if (!signals || signals.length === 0) return;
  
  const candleTimeSet = new Set(candleData.map(c => c.time));
  const unmatchedSignals = signals.filter(s => !candleTimeSet.has(s.time));
  
  if (unmatchedSignals.length > 0) {
    console.warn('⚠️ 시간 매칭 오류: 다음 시그널의 시간이 캔들 데이터에 없습니다:', 
                unmatchedSignals.map(s => s.time));
    console.warn('   → 해당 시그널은 무시됩니다.');
  } else {
    console.log('✅ 시간 매칭 검증 통과: 모든 시그널이 정확한 캔들 시간과 매칭됨');
  }
}

/**
 * ✅ 중복 시그널 검증
 * 동일한 시간에 BUY와 SELL이 동시에 발생하거나, 동일한 시간에 중복 시그널이 있는지 확인
 */
function validateNoDuplicateSignals(signals: CandleSignal[]): void {
  if (!signals || signals.length === 0) return;
  
  // 1. 동일 시간에 BUY와 SELL 동시 발생 확인
  const conflictingSignals = signals.filter(s => s.isBuyPoint && s.isSellPoint);
  if (conflictingSignals.length > 0) {
    console.error('❌ 시그널 충돌: 동일 시간에 BUY와 SELL이 동시 발생:', 
                 conflictingSignals.map(s => s.time));
  }
  
  // 2. 동일 시간에 중복 시그널 확인
  const timeCount = new Map<string, number>();
  signals.forEach(s => {
    timeCount.set(s.time, (timeCount.get(s.time) || 0) + 1);
  });
  
  const duplicates = Array.from(timeCount.entries()).filter(([_, count]) => count > 1);
  if (duplicates.length > 0) {
    console.error('❌ 중복 시그널: 동일 시간에 여러 시그널 존재:', 
                 duplicates.map(([time, count]) => `${time} (${count}개)`));
  }
  
  if (conflictingSignals.length === 0 && duplicates.length === 0) {
    console.log('✅ 중복 검증 통과: 모든 시그널이 고유하며 충돌 없음');
  }
}

