/**
 * 백테스팅 실행 훅.
 *
 * 사용법:
 * const { signals, stats, analysis, running, run, clear } = useBacktest();
 *
 * await run({ strategyId, bars, timeframe });
 */
import { useState, useCallback, useRef } from 'react';
import type { OHLCVBar } from '../types';
import {
  runBacktest,
  type BacktestSignal,
  type BacktestStats,
  type BacktestAnalysis,
  type BacktestSettingsDto,
} from '../utils/backendApi';

export interface BacktestResult {
  signals:   BacktestSignal[];
  stats:     BacktestStats | null;
  analysis:  BacktestAnalysis | null;
  resultId?: number;
  /** 백테스팅 실행 당시 차트 종목·타임프레임 (마커 표시 범위 검증용) */
  symbol?:    string;
  timeframe?: string;
  /** 실행마다 증가 — 동일 시그널 배열 참조여도 차트 마커 재적용 트리거 */
  runSeq:     number;
}

const EMPTY_SIGNALS: BacktestSignal[] = [];

export function useBacktest() {
  const [result,  setResult]  = useState<BacktestResult | null>(null);
  const [running, setRunning] = useState(false);
  const [error,   setError]   = useState<string | null>(null);
  const runSeqRef = useRef(0);
  /** 종목·타임프레임 변경 등으로 진행 중인 run 을 무효화할 때 증가 */
  const runGenRef = useRef(0);

  const invalidateRuns = useCallback(() => {
    runGenRef.current += 1;
  }, []);

  const run = useCallback(async (opts: {
    strategyId?:      number;
    buyCondition?:    unknown;
    sellCondition?:   unknown;
    bars:             OHLCVBar[];
    timeframe:        string;
    indicatorParams?: Record<string, Record<string, unknown>>;
    settings?:        BacktestSettingsDto;
    symbol?:          string;
    strategyName?:    string;
  }) => {
    const runGen = runGenRef.current;
    setRunning(true);
    setError(null);
    try {
      const req = {
        strategyId:      opts.strategyId,
        buyCondition:    opts.buyCondition,
        sellCondition:   opts.sellCondition,
        bars:            opts.bars.map(b => ({
          time:   b.time,
          open:   b.open,
          high:   b.high,
          low:    b.low,
          close:  b.close,
          volume: b.volume,
        })),
        timeframe:       opts.timeframe,
        indicatorParams: opts.indicatorParams,
        settings:        opts.settings,
        symbol:          opts.symbol,
        strategyName:    opts.strategyName,
      };
      const res = await runBacktest(req);
      if (runGen !== runGenRef.current) return null;
      if (!res) {
        setError('백테스팅 요청에 실패했습니다.');
        return null;
      }
      runSeqRef.current += 1;
      const r: BacktestResult = {
        signals:   [...res.signals],
        stats:     res.stats,
        analysis:  res.analysis ?? null,
        resultId:  res.resultId,
        symbol:    opts.symbol,
        timeframe: opts.timeframe,
        runSeq:    runSeqRef.current,
      };
      setResult(r);
      return r;
    } catch (e: unknown) {
      const msg = e instanceof Error ? e.message : '알 수 없는 오류';
      setError(msg);
      return null;
    } finally {
      setRunning(false);
    }
  }, []);

  const clear = useCallback(() => {
    setResult(null);
    setError(null);
  }, []);

  return {
    signals:         result?.signals    ?? EMPTY_SIGNALS,
    stats:           result?.stats      ?? null,
    analysis:        result?.analysis   ?? null,
    resultSymbol:    result?.symbol     ?? null,
    resultTimeframe: result?.timeframe  ?? null,
    runSeq:          result?.runSeq     ?? 0,
    result,
    running,
    error,
    run,
    clear,
    invalidateRuns,
  };
}
