import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import BacktestAnalysisChart from '../backtest/BacktestAnalysisChart';
import {
  loadBacktestSettings,
  loadStrategy,
  runBacktest,
  type BacktestSignal,
  type StrategyDto,
} from '../../utils/backendApi';
import { loadAnalysisCandles } from '../../utils/analysisChartData';
import { normalizeChartTimeframe } from '../../utils/backtestUiUtils';
import { resolveStrategyPrimaryTimeframe } from '../../utils/strategyToChartIndicators';
import { resolveEvaluationFromLoadedBars } from '../../utils/backtestWarmup';
import type { OHLCVBar, Theme } from '../../types';
import { useIndicatorSettings } from '../../hooks/useIndicatorSettings';
import {
  DEFAULT_PAPER_OVERLAY_VISIBILITY,
  type PaperOverlayToggleKey,
  type PaperOverlayVisibility,
} from '../../utils/paperChartOverlayVisibility';

const BAR_COUNT = 300;
const HISTORY_BACKTEST_DEBOUNCE_MS = 450;

interface Props {
  market: string;
  strategyId?: number | null;
  theme?: Theme;
  /** 위젯 임베드 시 하단 줌/패닝 툴바 숨김 */
  showHoverToolbar?: boolean;
}

/**
 * 모의투자 차트 탭 — 전략 백테스트 시그널 + 캔들·보조지표 (백테스팅 분석 차트와 동일)
 * 좌측(과거) 스크롤 시 추가 캔들·보조지표 로드 후 전체 구간 시그널 재계산.
 */
const PaperAnalysisChart: React.FC<Props> = ({
  market, strategyId, theme = 'dark', showHoverToolbar = true,
}) => {
  const { getParams } = useIndicatorSettings();
  const [signals, setSignals] = useState<BacktestSignal[]>([]);
  const [strategy, setStrategy] = useState<StrategyDto | undefined>();
  const [timeframe, setTimeframe] = useState('1h');
  const [running, setRunning] = useState(false);
  const [historyLoading, setHistoryLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  /** 종목 변경해도 유지 — 투자관리 차트 탭 세션 전용 (DB·설정 저장 없음) */
  const [overlayVisibility, setOverlayVisibility] = useState<PaperOverlayVisibility>(
    () => ({ ...DEFAULT_PAPER_OVERLAY_VISIBILITY }),
  );
  const toTimeSec = useMemo(() => Math.floor(Date.now() / 1000), [market, strategyId]);
  const backtestGenRef = useRef(0);
  const historyDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);
  const strategyRef = useRef(strategy);
  const strategyIdRef = useRef(strategyId);
  strategyRef.current = strategy;
  strategyIdRef.current = strategyId;

  useEffect(() => {
    if (!strategyId) {
      setStrategy(undefined);
      setSignals([]);
      setError('가상매매 투자대상에 종목 전략 또는 기본 전략이 설정되어 있지 않습니다.');
      return;
    }
    let cancelled = false;
    setError(null);
    void loadStrategy(strategyId).then(s => {
      if (!cancelled) setStrategy(s ?? undefined);
    });
    return () => { cancelled = true; };
  }, [strategyId]);

  const runSignalsForBars = useCallback(async (
    bars: OHLCVBar[],
    tf: string,
    strat: StrategyDto,
    sid: number,
  ) => {
    const sym = market.startsWith('KRW-') ? market : `KRW-${market}`;
    if (bars.length < 10) {
      setSignals([]);
      setError('캔들 데이터가 부족합니다.');
      return;
    }
    const gen = ++backtestGenRef.current;
    setRunning(true);
    setError(null);
    try {
      const btSettings = await loadBacktestSettings();
      const indicatorParams = Object.fromEntries(
        ['RSI', 'MACD', 'CCI', 'SMA', 'EMA', 'IchimokuCloud', 'Stochastic', 'ADX', 'MFI', 'NewPsychological'].map(t => [
          t,
          getParams(t) as Record<string, unknown>,
        ]),
      );
      const { evaluationBarCount } = resolveEvaluationFromLoadedBars(
        bars.length,
        strat.buyCondition,
        strat.sellCondition,
        indicatorParams,
      );
      const res = await runBacktest({
        strategyId: sid,
        bars: bars.map(b => ({
          time: b.time,
          open: b.open,
          high: b.high,
          low: b.low,
          close: b.close,
          volume: b.volume,
        })),
        timeframe: tf,
        symbol: sym,
        strategyName: strat.name,
        settings: btSettings,
        indicatorParams,
        evaluationBarCount,
      });
      if (gen !== backtestGenRef.current) return;
      if (!res) {
        setSignals([]);
        setError('시그널 계산에 실패했습니다.');
        return;
      }
      setSignals(res.signals);
    } catch (e) {
      if (gen !== backtestGenRef.current) return;
      setSignals([]);
      setError(e instanceof Error ? e.message : '차트 분석 실패');
    } finally {
      if (gen === backtestGenRef.current) setRunning(false);
    }
  }, [market, getParams]);

  useEffect(() => {
    if (!strategyId || !strategy) {
      setSignals([]);
      return;
    }
    let cancelled = false;
    const tf = normalizeChartTimeframe(resolveStrategyPrimaryTimeframe(strategy));
    setTimeframe(tf);
    setError(null);

    void (async () => {
      try {
        const sym = market.startsWith('KRW-') ? market : `KRW-${market}`;
        const bars = await loadAnalysisCandles(sym, tf, toTimeSec, BAR_COUNT);
        if (cancelled) return;
        await runSignalsForBars(bars, tf, strategy, strategyId);
      } catch (e) {
        if (!cancelled) {
          setSignals([]);
          setError(e instanceof Error ? e.message : '차트 분석 실패');
          setRunning(false);
        }
      }
    })();

    return () => {
      cancelled = true;
      ++backtestGenRef.current;
    };
  }, [market, strategyId, strategy, toTimeSec, runSignalsForBars]);

  const handleToggleOverlay = useCallback((key: PaperOverlayToggleKey) => {
    setOverlayVisibility(prev => ({ ...prev, [key]: !prev[key] }));
  }, []);

  const handleHistoryBarsLoaded = useCallback((bars: OHLCVBar[]) => {
    const strat = strategyRef.current;
    const sid = strategyIdRef.current;
    if (!strat || !sid) return;
    const tf = normalizeChartTimeframe(resolveStrategyPrimaryTimeframe(strat));
    if (historyDebounceRef.current) clearTimeout(historyDebounceRef.current);
    historyDebounceRef.current = setTimeout(() => {
      historyDebounceRef.current = null;
      void runSignalsForBars(bars, tf, strat, sid);
    }, HISTORY_BACKTEST_DEBOUNCE_MS);
  }, [runSignalsForBars]);

  useEffect(() => () => {
    if (historyDebounceRef.current) clearTimeout(historyDebounceRef.current);
  }, []);

  if (!strategyId) {
    return (
      <div className="ptd-analysis-chart ptd-analysis-chart--empty">
        <p className="ptd-muted">
          가상매매 투자대상 목록에서 종목별 전략 또는 기본 전략을 설정하면 차트에 매매 시그널이 표시됩니다.
        </p>
      </div>
    );
  }

  const statusBusy = running || historyLoading;

  return (
    <div className="ptd-analysis-chart ptd-analysis-chart--backtest">
      {statusBusy && (
        <div className="ptd-analysis-chart-status">
          {historyLoading && !running ? '과거 캔들 로드 중…' : '전략 시그널 계산 중…'}
        </div>
      )}
      {error && !statusBusy && (
        <div className="ptd-analysis-chart-status ptd-analysis-chart-status--err">{error}</div>
      )}
      <BacktestAnalysisChart
        symbol={market}
        timeframe={timeframe}
        toTimeSec={toTimeSec}
        barCount={BAR_COUNT}
        signals={signals}
        strategyId={strategyId}
        theme={theme}
        onHistoryBarsLoaded={handleHistoryBarsLoaded}
        onHistoryLoadingChange={setHistoryLoading}
        overlayVisibility={overlayVisibility}
        onToggleOverlay={handleToggleOverlay}
        showHoverToolbar={showHoverToolbar}
      />
    </div>
  );
};

export default PaperAnalysisChart;
