/**
 * 추세검색 카드 — 인라인 캔들 + RSI/MACD/BB
 */
import React, {
  useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState,
} from 'react';
import TradingChart from '../TradingChart';
import { pinCandleWatch } from '../../utils/backendApi';
import type {
  ChartMode, ChartType, Drawing, LegendData, OHLCVBar, Theme, Timeframe,
} from '../../types';
import { isUpbitMarket } from '../../utils/upbitApi';
import { useChartRealtimeData, type ChartRealtimeSource } from '../../hooks/useChartRealtimeData';
import { useHistoryLoader } from '../../hooks/useHistoryLoader';
import { useIndicatorSettings } from '../../hooks/useIndicatorSettings';
import type { ChartManager } from '../../utils/ChartManager';
import { timeframeToCandleType } from '../../utils/chartCandleType';
import { buildChartIndicatorConfig } from '../../utils/indicatorPaneMerge';
import { DEFAULT_DISPLAY_TIMEZONE } from '../../utils/timezone';

interface Props {
  market: string;
  timeframe: string;
  theme?: Theme;
  chartRealtimeSource?: ChartRealtimeSource;
  chartCandleAreaPriceLabels?: boolean;
  chartSeriesPriceLabels?: boolean;
  chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
  /** false — 뷰포트 밖: STOMP·히스토리 중지 (기본 true) */
  chartStreamEnabled?: boolean;
}

const noop = () => {};
const CHART_INDICATOR_TYPES = ['BollingerBands', 'RSI', 'MACD'] as const;

function toChartTimeframe(tf: string): Timeframe {
  if (tf === '1d') return '1D';
  if (tf === '1w') return '1W';
  if (tf === '1M') return '1M';
  return tf as Timeframe;
}

const TrendSearchCardChart: React.FC<Props> = ({
  market,
  timeframe,
  theme = 'dark',
  chartRealtimeSource = 'BACKEND_STOMP',
  chartCandleAreaPriceLabels = true,
  chartSeriesPriceLabels = true,
  chartPaneSeparator,
  chartStreamEnabled = true,
}) => {
  const chartTf = toChartTimeframe(timeframe);
  const { getParams, getVisualConfig } = useIndicatorSettings();

  const indicators = useMemo(
    () => CHART_INDICATOR_TYPES.map(type =>
      buildChartIndicatorConfig(type, `${type}-tsd-card`, getParams, getVisualConfig),
    ).filter((c): c is NonNullable<typeof c> => c != null),
    [getParams, getVisualConfig],
  );

  const managerRef = useRef<ChartManager | null>(null);
  const canvasWrapRef = useRef<HTMLDivElement | null>(null);
  const [chartReloadTick, setChartReloadTick] = useState(0);
  const chartReloadTriggeredRef = useRef(false);
  const pendingBarRef = useRef<OHLCVBar | null>(null);
  const barsMarketRef = useRef<string | null>(null);
  const chartLiveReadyRef = useRef(false);
  const marketRef = useRef(market);
  marketRef.current = market;

  const handleCandlesReady = useCallback(() => {
    chartLiveReadyRef.current = true;
    const pending = pendingBarRef.current;
    const mgr = managerRef.current;
    if (!pending || !mgr || barsMarketRef.current !== marketRef.current) return;
    pendingBarRef.current = null;
    mgr.updateBar(pending);
  }, []);

  const applyRealtimeBar = useCallback((bar: OHLCVBar, append: boolean) => {
    if (barsMarketRef.current !== marketRef.current) return;
    if (!chartLiveReadyRef.current || !managerRef.current) {
      pendingBarRef.current = bar;
      return;
    }
    if (append) managerRef.current.appendBar(bar);
    else managerRef.current.updateBar(bar);
  }, []);

  const handleTickUpdate = useCallback((bar: OHLCVBar) => applyRealtimeBar(bar, false), [applyRealtimeBar]);
  const handleNewCandle = useCallback((bar: OHLCVBar) => applyRealtimeBar(bar, true), [applyRealtimeBar]);

  const useUpbit = isUpbitMarket(market);
  const streamActive = useUpbit && chartStreamEnabled;

  const { bars, barsMarket, isLoading } = useChartRealtimeData(
    market,
    chartTf,
    useMemo(() => ({
      onTickUpdate: handleTickUpdate,
      onNewCandle: handleNewCandle,
      enabled: streamActive,
      source: chartRealtimeSource,
    }), [handleTickUpdate, handleNewCandle, streamActive, chartRealtimeSource]),
  );

  const { isLoadingMore } = useHistoryLoader({
    symbol: market,
    timeframe: chartTf,
    isUpbit: streamActive,
    managerRef,
  });

  barsMarketRef.current = barsMarket;

  useLayoutEffect(() => {
    chartLiveReadyRef.current = false;
    pendingBarRef.current = null;
    chartReloadTriggeredRef.current = false;
  }, [market, chartTf]);

  useEffect(() => {
    const wrap = canvasWrapRef.current;
    if (!wrap) return;

    const applyPaneHeights = () => {
      const h = wrap.clientHeight;
      if (h <= 0) return;
      const mgr = managerRef.current;
      if (mgr?.hasMainSeries()) mgr.resetPaneHeights(h);
    };

    const timers = [100, 300, 800, 1500].map(delay =>
      setTimeout(() => {
        if (!canvasWrapRef.current) return;
        const h = canvasWrapRef.current.clientHeight;
        if (h <= 0) return;
        if (managerRef.current?.hasMainSeries()) managerRef.current.resetPaneHeights(h);
        else if (!chartReloadTriggeredRef.current && delay >= 800 && bars.length > 0) {
          chartReloadTriggeredRef.current = true;
          setChartReloadTick(t => t + 1);
        }
      }, delay),
    );

    const ro = new ResizeObserver(() => applyPaneHeights());
    ro.observe(wrap);

    return () => {
      timers.forEach(clearTimeout);
      ro.disconnect();
    };
  }, [market, chartTf, bars.length]);

  useEffect(() => {
    if (!streamActive) return;
    void pinCandleWatch(market, timeframeToCandleType(chartTf));
  }, [market, chartTf, streamActive]);

  return (
    <div className="vtd-card-chart-panel vtd-card-chart-panel--fill">
      <div
        ref={canvasWrapRef}
        className="vtd-card-chart-canvas slot-chart-wrap vtd-card-chart-canvas--fill"
      >
        {isLoading && <div className="vtd-card-chart-loading">차트 로딩…</div>}
        {isLoadingMore && (
          <div className="chart-history-loading">
            <div className="loading-spinner" style={{ width: 14, height: 14 }} />
            <span>과거 데이터…</span>
          </div>
        )}
        <TradingChart
          key={`${market}-${chartTf}-${chartReloadTick}`}
          chartVisible={chartStreamEnabled}
          bars={bars}
          barsMarket={barsMarket}
          market={market}
          timeframe={chartTf}
          chartType={'candlestick' as ChartType}
          theme={theme}
          mode={'chart' as ChartMode}
          indicators={indicators}
          drawingTool="cursor"
          drawings={[] as Drawing[]}
          logScale={false}
          drawingsLocked
          drawingsVisible={false}
          displayTimezone={DEFAULT_DISPLAY_TIMEZONE}
          onCrosshair={noop as (d: LegendData | null) => void}
          onManagerReady={mgr => { managerRef.current = mgr; }}
          onAddDrawing={noop as (d: Drawing) => void}
          onCandlesReady={handleCandlesReady}
          magnifierEnabled={false}
          volumeVisible
          showHoverToolbar={false}
          candleAreaPriceLabelsEnabled={chartCandleAreaPriceLabels}
          indicatorAreaPriceLabelsEnabled={chartSeriesPriceLabels}
          paneSeparatorOptions={chartPaneSeparator}
        />
      </div>
    </div>
  );
};

export default TrendSearchCardChart;
