/**
 * 매매 시그널 알림 행 — 캔들·지표 미니 차트 카드
 */
import React, {
  useCallback, useEffect, useLayoutEffect, useMemo, useRef, useState,
} from 'react';
import TradingChart from '../TradingChart';
import type { IndicatorConfig } from '../../types';
import type {
  ChartMode, ChartType, Drawing, LegendData, OHLCVBar, Theme, Timeframe,
} from '../../types';
import { isUpbitMarket } from '../../utils/upbitApi';
import { useChartRealtimeData } from '../../hooks/useChartRealtimeData';
import type { ChartRealtimeSource } from '../../hooks/useChartRealtimeData';
import { useHistoryLoader } from '../../hooks/useHistoryLoader';
import { useAppSettings } from '../../hooks/useAppSettings';
import type { ChartManager } from '../../utils/ChartManager';
import { pinCandleWatch } from '../../utils/backendApi';
import { timeframeToCandleType } from '../../utils/chartCandleType';
import { DEFAULT_DISPLAY_TIMEZONE } from '../../utils/timezone';
import { useIndicatorSettings } from '../../hooks/useIndicatorSettings';
import { useSessionCandleOverlayControls } from '../../hooks/useSessionCandleOverlayControls';
import { ensurePaperChartOverlays } from '../../utils/strategyToChartIndicators';
import { mergeGlobalDefaultsOntoChartIndicators } from '../../utils/indicatorMainConfig';
import { barsMeetObvVolumeRequirement } from '../../utils/obvChartBars';
import { enrichIndicatorConfig } from '../../utils/indicatorRegistry';
import {
  applyNotificationSignalMarkers,
  type TradeSignalChartMarker,
} from '../../utils/tradeSignalChartMarkers';

interface Props {
  market: string;
  timeframe: Timeframe;
  theme?: Theme;
  indicators?: IndicatorConfig[];
  enabled?: boolean;
  /** 전체보기 모드 — 부모 높이에 맞춤 */
  fillHeight?: boolean;
  /** STOMP/WS 실시간 봉 수신 시 (목록 행 형광 플래시 등) */
  onRealtimeActivity?: () => void;
  /** 알림 발생 시점 매매 시그널 (캔들 마커) */
  signalMarker?: TradeSignalChartMarker;
}

const noop = () => {};

const TradeSignalMiniChart: React.FC<Props> = ({
  market,
  timeframe,
  theme = 'dark',
  indicators = [],
  enabled = true,
  fillHeight = false,
  onRealtimeActivity,
  signalMarker,
}) => {
  const { getParams, getVisualConfig, settingsLoaded, settingsRevision } = useIndicatorSettings();
  const { defaults: appDefaults } = useAppSettings();
  const appChartSource = (appDefaults.chartRealtimeSource ?? 'BACKEND_STOMP') as ChartRealtimeSource;
  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 signalMarkerRef = useRef(signalMarker);
  signalMarkerRef.current = signalMarker;

  const baseIndicators = useMemo(
    () => mergeGlobalDefaultsOntoChartIndicators(
      ensurePaperChartOverlays(indicators, getParams, getVisualConfig),
      getParams,
      getVisualConfig,
    ).map(enrichIndicatorConfig),
    [indicators, getParams, getVisualConfig, settingsRevision],
  );

  const needsDeepObv = useMemo(
    () => baseIndicators.some(i => i.type === 'OBV'),
    [baseIndicators],
  );

  /** 메인 차트와 동일 소스 — STOMP(+ volume 없으면 Upbit 폴백). deepObvHistory 로 장기 봉 확보 */
  const chartRealtimeSource: ChartRealtimeSource = appChartSource;

  const {
    indicators: chartIndicators,
    candleOverlayToggles,
    handleToggleCandleOverlay,
    syncToManager,
  } = useSessionCandleOverlayControls(managerRef, baseIndicators);

  const applySignalMarkers = useCallback((attempt = 0) => {
    const mgr = managerRef.current;
    if (!mgr?.hasMainSeries()) {
      if (attempt < 80) requestAnimationFrame(() => applySignalMarkers(attempt + 1));
      return;
    }
    applyNotificationSignalMarkers(mgr, signalMarkerRef.current, false);
  }, []);

  const syncChartLayout = useCallback(() => {
    const wrap = canvasWrapRef.current;
    const mgr = managerRef.current;
    if (!wrap || !mgr?.hasMainSeries()) return;
    const chartWrap = wrap.querySelector<HTMLElement>('.tv-chart-wrap');
    const w = chartWrap?.clientWidth ?? wrap.clientWidth;
    const h = chartWrap?.clientHeight ?? wrap.clientHeight;
    if (w <= 0 || h <= 0) return;
    mgr.syncLayout(w, h);
  }, []);

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

  const handleManagerReady = useCallback((mgr: ChartManager) => {
    managerRef.current = mgr;
    syncToManager(mgr);
    applySignalMarkers();
  }, [syncToManager, applySignalMarkers]);

  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);
    onRealtimeActivity?.();
  }, [applyRealtimeBar, onRealtimeActivity]);

  const handleNewCandle = useCallback((bar: OHLCVBar) => {
    applyRealtimeBar(bar, true);
    onRealtimeActivity?.();
  }, [applyRealtimeBar, onRealtimeActivity]);

  const useUpbit = isUpbitMarket(market);

  const { bars, barsMarket, isLoading } = useChartRealtimeData(
    market,
    timeframe,
    useMemo(() => ({
      onTickUpdate: handleTickUpdate,
      onNewCandle: handleNewCandle,
      enabled: enabled && useUpbit,
      source: chartRealtimeSource,
      deepObvHistory: needsDeepObv,
    }), [handleTickUpdate, handleNewCandle, enabled, useUpbit, needsDeepObv, chartRealtimeSource]),
  );

  const { isLoadingMore } = useHistoryLoader({
    symbol: market,
    timeframe,
    /** OBV — 백엔드 history volume=0 봉 prepend 시 본선 왜곡 방지 */
    isUpbit: useUpbit && enabled && !needsDeepObv,
    managerRef,
  });

  barsMarketRef.current = barsMarket;
  const barsReady = bars.length >= 2 && barsMarket === market;

  const obvBarsReady = useMemo(() => {
    if (!needsDeepObv) return true;
    if (bars.length < 2) return false;
    return barsMeetObvVolumeRequirement(bars);
  }, [needsDeepObv, bars]);

  const chartDataReady = barsReady && obvBarsReady && settingsLoaded;

  useLayoutEffect(() => {
    chartLiveReadyRef.current = false;
    pendingBarRef.current = null;
    chartReloadTriggeredRef.current = false;
    managerRef.current?.clearBacktestMarkers();
  }, [market, timeframe, enabled]);

  useEffect(() => {
    if (!enabled) {
      managerRef.current?.clearBacktestMarkers();
      return;
    }
    applySignalMarkers();
  }, [enabled, signalMarker, applySignalMarkers, barsReady]);

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

    const timers = [200, 600, 1200].map(delay =>
      setTimeout(() => {
        if (!canvasWrapRef.current) return;
        if (managerRef.current?.hasMainSeries()) {
          syncChartLayout();
        } else if (!chartReloadTriggeredRef.current && delay >= 600 && chartDataReady) {
          chartReloadTriggeredRef.current = true;
          setChartReloadTick(t => t + 1);
        }
      }, delay),
    );

    const ro = new ResizeObserver(() => syncChartLayout());
    ro.observe(wrap);
    return () => {
      timers.forEach(clearTimeout);
      ro.disconnect();
    };
  }, [market, timeframe, enabled, chartDataReady, syncChartLayout, fillHeight]);

  useEffect(() => {
    if (!enabled || !chartDataReady) return;
    if (!managerRef.current?.hasMainSeries() && !chartReloadTriggeredRef.current) {
      chartReloadTriggeredRef.current = true;
      setChartReloadTick(t => t + 1);
    }
  }, [enabled, chartDataReady]);

  useEffect(() => {
    if (!enabled) return;
    const t = setTimeout(() => syncChartLayout(), 80);
    return () => clearTimeout(t);
  }, [fillHeight, enabled, syncChartLayout]);

  useEffect(() => {
    if (!enabled || !useUpbit) return;
    void pinCandleWatch(market, timeframeToCandleType(timeframe));
    if (timeframeToCandleType(timeframe) !== '1m') {
      void pinCandleWatch(market, '1m');
    }
  }, [market, timeframe, enabled, useUpbit]);

  if (!enabled) {
    return (
      <div className={`tnl-mini-chart-placeholder${fillHeight ? ' tnl-mini-chart-placeholder--fill' : ''}`}>
        차트 대기
      </div>
    );
  }

  return (
    <div
      ref={canvasWrapRef}
      className={[
        'tnl-mini-chart-canvas',
        'slot-chart-wrap',
        fillHeight ? 'tnl-mini-chart-canvas--fill' : '',
      ].filter(Boolean).join(' ')}
    >
      {(!settingsLoaded || isLoading) && <div className="tnl-mini-chart-loading">로딩…</div>}
      {needsDeepObv && !isLoading && !obvBarsReady && (
        <div className="tnl-mini-chart-loading">OBV 거래량 데이터 로딩…</div>
      )}
      {isLoadingMore && (
        <div className="chart-history-loading">
          <div className="loading-spinner" style={{ width: 12, height: 12 }} />
        </div>
      )}
      {chartDataReady && (
      <TradingChart
        key={`${market}-${timeframe}-${chartReloadTick}-${chartRealtimeSource}-${needsDeepObv ? 'obv' : 'std'}-${settingsRevision}-${chartIndicators.map(i => i.id).join(',')}`}
        chartVisible
        bars={bars}
        barsMarket={barsMarket}
        market={market}
        timeframe={timeframe}
        chartType={'candlestick' as ChartType}
        theme={theme}
        mode={'chart' as ChartMode}
        indicators={chartIndicators}
        drawingTool="cursor"
        drawings={[] as Drawing[]}
        logScale={false}
        drawingsLocked
        drawingsVisible={false}
        onCrosshair={noop as (d: LegendData | null) => void}
        onManagerReady={handleManagerReady}
        onAddDrawing={noop as (d: Drawing) => void}
        onCandlesReady={handleCandlesReady}
        magnifierEnabled={false}
        volumeVisible={false}
        showHoverToolbar={false}
        seriesPriceLabelsEnabled={false}
        paneLayoutClamp
        showPaneLegend
        showChartRightToolbar={false}
        showCandleOverlayControls
        candleOverlayToggles={candleOverlayToggles}
        onToggleCandleOverlay={handleToggleCandleOverlay}
        crosshairInfoVisible={false}
      />
      )}
    </div>
  );
};

export default TradeSignalMiniChart;
