/**
 * 가상투자 대시보드 — 모의투자 레이아웃 기반, 다종목 전략 모니터링
 */
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  loadPaperSummary,
  loadPaperTrades,
  loadStrategies,
  saveLiveStrategySettings,
  type PaperSummaryDto,
  type PaperTradeDto,
  type StrategyDto,
} from '../utils/backendApi';
import type { Theme, TradeOrderFillRequest } from '../types';
import type { TickerData } from '../hooks/useMarketTicker';
import TradeOrderPanel from './TradeOrderPanel';
import PaperCompactOrderbook from './paper/PaperCompactOrderbook';
import PaperSplitPanel from './paper/PaperSplitPanel';
import PaperTradeHistoryList from './paper/PaperTradeHistoryList';
import BuilderPageShell from './layout/BuilderPageShell';
import VirtualLeftTargetPanel from './virtual/VirtualLeftTargetPanel';
import VirtualTargetGrid from './virtual/VirtualTargetGrid';
import {
  VirtualSessionHeaderControls,
  VirtualViewHeaderControls,
} from './virtual/VirtualGridUnifiedHeader';
import type { VirtualCardDisplayMode } from './virtual/VirtualTargetCard';
import { useVirtualIndicatorSnapshots } from '../hooks/useVirtualIndicatorSnapshots';
import { useVirtualAutoTrade } from '../hooks/useVirtualAutoTrade';
import { useVirtualTargetLiveStatus } from '../hooks/useVirtualTargetLiveStatus';
import type { ChartRealtimeSource } from '../hooks/useChartRealtimeData';
import {
  loadVirtualSession,
  loadVirtualTargets,
  saveVirtualSession,
  saveVirtualTargets,
  loadVirtualCardViewMode,
  saveVirtualCardViewMode,
  type VirtualSessionConfig,
  type VirtualTargetItem,
  type VirtualCardViewMode,
} from '../utils/virtualTradingStorage';
import { useAppSettings, resolveAppDefaults } from '../hooks/useAppSettings';
import { coerceFiniteNumber } from '../utils/safeFormat';
import {
  syncVirtualTargetsToBackend,
  stopVirtualLiveOnBackend,
} from '../utils/virtualLiveStrategySync';
import '../styles/virtualTradingDashboard.css';

type RightTab = 'trade' | 'orderbook' | 'history';

interface Props {
  theme?: Theme;
  tickers?: Map<string, TickerData>;
  defaultMarket?: string;
  paperTradingEnabled?: boolean;
  paperAutoTradeEnabled?: boolean;
  paperAutoTradeBudgetPct?: number;
  onPaperAutoTradeEnabled?: (enabled: boolean) => void;
  onPaperOrderFilled?: () => void;
}

const VirtualTradingPage: React.FC<Props> = ({
  theme = 'dark',
  tickers,
  defaultMarket = 'KRW-BTC',
  paperTradingEnabled = true,
  paperAutoTradeEnabled = false,
  paperAutoTradeBudgetPct = 95,
  onPaperAutoTradeEnabled,
  onPaperOrderFilled,
}) => {
  const [targets, setTargets] = useState<VirtualTargetItem[]>(() => loadVirtualTargets());
  const [session, setSession] = useState<VirtualSessionConfig>(() => loadVirtualSession());
  const [strategies, setStrategies] = useState<StrategyDto[]>([]);
  const [summary, setSummary] = useState<PaperSummaryDto | null>(null);
  const [trades, setTrades] = useState<PaperTradeDto[]>([]);
  const [loading, setLoading] = useState(true);
  const [selectedMarket, setSelectedMarket] = useState(defaultMarket);
  const [rightTab, setRightTab] = useState<RightTab>('trade');
  const [fillBuy, setFillBuy] = useState<TradeOrderFillRequest | null>(null);
  const [fillSell, setFillSell] = useState<TradeOrderFillRequest | null>(null);
  const [viewMode, setViewMode] = useState<VirtualCardViewMode>(() => loadVirtualCardViewMode());
  const [globalDisplayMode, setGlobalDisplayMode] = useState<VirtualCardDisplayMode>('signal');
  const [focusMarket, setFocusMarket] = useState<string | null>(null);
  const orderAnchorRef = useRef<HTMLDivElement>(null);
  const { settings: appSettings } = useAppSettings();
  const appChartDefaults = resolveAppDefaults(appSettings);
  const chartRealtimeSource = (appChartDefaults.chartRealtimeSource
    ?? 'BACKEND_STOMP') as ChartRealtimeSource;
  const chartSeriesPriceLabels = appChartDefaults.chartSeriesPriceLabels;
  const chartLiveReceiveHighlight = appChartDefaults.chartLiveReceiveHighlight;

  useEffect(() => {
    void Promise.all([
      loadStrategies().then(setStrategies).catch(() => setStrategies([])),
      loadPaperSummary().then(setSummary),
      loadPaperTrades().then(setTrades),
    ]).finally(() => setLoading(false));
  }, []);

  useEffect(() => { saveVirtualTargets(targets); }, [targets]);
  useEffect(() => { saveVirtualSession(session); }, [session]);
  useEffect(() => { saveVirtualCardViewMode(viewMode); }, [viewMode]);

  const strategyNames = useMemo(
    () => Object.fromEntries(strategies.map(s => [s.id, s.name])),
    [strategies],
  );

  const refreshPaperData = useCallback(async (opts?: { focusHistory?: boolean }) => {
    try {
      const [sum, tr] = await Promise.all([loadPaperSummary(), loadPaperTrades()]);
      setSummary(sum);
      setTrades(tr);
    } catch { /* ignore */ }
    onPaperOrderFilled?.();
    if (opts?.focusHistory) setRightTab('history');
  }, [onPaperOrderFilled]);

  const handleGlobalDisplayModeChange = useCallback((mode: VirtualCardDisplayMode) => {
    setGlobalDisplayMode(mode);
  }, []);

  const targetRefs = useMemo(() =>
    targets.map(t => ({
      market: t.market,
      strategyId: t.strategyId ?? session.globalStrategyId,
    })),
  [targets, session.globalStrategyId]);

  const snapshots = useVirtualIndicatorSnapshots(targetRefs, strategies, session.running);
  const { statusByMarket: liveStatusByMarket, lastTickAtByMarket } = useVirtualTargetLiveStatus(
    targetRefs,
    session.running,
  );

  useVirtualAutoTrade({
    enabled: paperTradingEnabled && paperAutoTradeEnabled,
    session,
    targets,
    snapshots,
    tickers,
    paperAutoTradeBudgetPct,
    positions: summary?.positions,
    onFilled: () => void refreshPaperData({ focusHistory: true }),
  });

  const mergedLiveStatus = useMemo(() => {
    if (!session.running) return liveStatusByMarket;
    const merged = { ...liveStatusByMarket };
    const now = Date.now();
    for (const [market, snap] of Object.entries(snapshots)) {
      if (snap?.updatedAt && now - snap.updatedAt < 8000) {
        merged[market] = 'live';
      }
    }
    return merged;
  }, [liveStatusByMarket, snapshots, session.running]);

  const posQty = useMemo(() => {
    const p = summary?.positions?.find(x => x.symbol === selectedMarket);
    return coerceFiniteNumber(p?.quantity) ?? 0;
  }, [summary?.positions, selectedMarket]);

  const tradePrice = useMemo(
    () => coerceFiniteNumber(tickers?.get(selectedMarket)?.tradePrice),
    [tickers, selectedMarket],
  );

  const handleSelectMarket = useCallback((market: string) => {
    setSelectedMarket(market);
    const price = tickers?.get(market)?.tradePrice;
    if (price != null && price > 0) {
      const seq = Date.now();
      setFillBuy({ market, price, side: 'buy', seq });
      setFillSell({ market, price, side: 'sell', seq: seq + 1 });
    }
    setRightTab('trade');
  }, [tickers]);

  const handleTargetsChange = useCallback((items: VirtualTargetItem[]) => {
    setTargets(items);
    if (items.length > 0 && !items.some(t => t.market === selectedMarket)) {
      handleSelectMarket(items[0].market);
    }
  }, [selectedMarket, handleSelectMarket]);

  const handleGlobalStrategyChange = useCallback((strategyId: number | null) => {
    const next = { ...session, globalStrategyId: strategyId };
    setSession(next);
    if (session.running && strategyId) {
      void syncVirtualTargetsToBackend(targets, next, true);
    }
  }, [session, targets]);

  const handleStart = useCallback(async () => {
    if (targets.length === 0) {
      window.alert('투자대상 종목을 먼저 추가하세요.');
      return;
    }
    if (!session.globalStrategyId) {
      window.alert('투자전략을 선택하세요.');
      return;
    }
    try {
      await syncVirtualTargetsToBackend(targets, session, true);
      setSession(s => ({ ...s, running: true }));
    } catch {
      window.alert('가상투자 시작 설정 저장에 실패했습니다.');
    }
  }, [targets, session]);

  const handleStop = useCallback(async () => {
    try {
      await stopVirtualLiveOnBackend(targets, session);
    } catch { /* ignore */ }
    setSession(s => ({ ...s, running: false }));
  }, [targets, session]);

  const handleObPick = useCallback((price: number, rowType: 'ask' | 'bid') => {
    const side = rowType === 'ask' ? 'buy' : 'sell';
    const req: TradeOrderFillRequest = { market: selectedMarket, price, side, seq: Date.now() };
    if (side === 'buy') setFillBuy(req); else setFillSell(req);
    setRightTab('trade');
  }, [selectedMarket]);

  const handleTargetStrategyChange = useCallback(async (market: string, strategyId: number | null) => {
    setTargets(prev => prev.map(t =>
      t.market === market ? { ...t, strategyId } : t,
    ));
    if (!session.running || !strategyId) return;
    try {
      await saveLiveStrategySettings({
        market,
        strategyId,
        isLiveCheck: true,
        executionType: session.executionType,
        positionMode: session.positionMode,
        skipWatchlistSync: true,
      });
    } catch {
      window.alert('종목 전략 변경 저장에 실패했습니다.');
    }
  }, [session]);

  const resyncRunningSession = useCallback(async (nextSession: VirtualSessionConfig) => {
    if (!session.running || targets.length === 0) return;
    try {
      await syncVirtualTargetsToBackend(targets, nextSession, true);
    } catch {
      window.alert('가상투자 설정 동기화에 실패했습니다.');
    }
  }, [session.running, targets]);

  const handleExecutionTypeChange = useCallback((executionType: VirtualSessionConfig['executionType']) => {
    const next = { ...session, executionType };
    setSession(next);
    void resyncRunningSession(next);
  }, [session, resyncRunningSession]);

  const handlePositionModeChange = useCallback((positionMode: VirtualSessionConfig['positionMode']) => {
    const next = { ...session, positionMode };
    setSession(next);
    void resyncRunningSession(next);
  }, [session, resyncRunningSession]);

  const rightTabs = (
    <div className="bps-right-tabs">
      <button type="button" className={`bps-right-tab${rightTab === 'trade' ? ' bps-right-tab--on' : ''}`} onClick={() => setRightTab('trade')}>매매</button>
      <button type="button" className={`bps-right-tab${rightTab === 'orderbook' ? ' bps-right-tab--on' : ''}`} onClick={() => setRightTab('orderbook')}>호가</button>
      <button type="button" className={`bps-right-tab${rightTab === 'history' ? ' bps-right-tab--on' : ''}`} onClick={() => setRightTab('history')}>
        거래{trades.length > 0 ? ` (${trades.length})` : ''}
      </button>
    </div>
  );

  return (
    <BuilderPageShell
      theme={theme}
      title="가상투자"
      subtitle="Virtual Trading"
      pageClassName="bps-page--vtd"
      loading={loading}
      loadingText="가상투자 대시보드 로딩…"
      collapsiblePanels
      headerCenter={(
        <VirtualSessionHeaderControls
          session={session}
          strategies={strategies}
          onStrategyChange={handleGlobalStrategyChange}
          onExecutionTypeChange={handleExecutionTypeChange}
          onPositionModeChange={handlePositionModeChange}
          onStart={() => void handleStart()}
          onStop={() => void handleStop()}
          paperAutoTradeEnabled={paperAutoTradeEnabled}
          onPaperAutoTradeEnabled={onPaperAutoTradeEnabled}
          paperTradingEnabled={paperTradingEnabled}
        />
      )}
      headerActions={(
        <VirtualViewHeaderControls
          session={session}
          viewMode={viewMode}
          onViewModeChange={setViewMode}
          globalDisplayMode={globalDisplayMode}
          onGlobalDisplayModeChange={handleGlobalDisplayModeChange}
          showSignalChartToggle={!focusMarket}
        />
      )}
      leftStorageKey="vtd-left-width"
      leftDefaultWidth={380}
      leftCollapsedStorageKey="vtd-left-open"
      rightStorageKey="vtd-right-width"
      rightDefaultWidth={380}
      rightCollapsedStorageKey="vtd-right-open"
      left={(
        <VirtualLeftTargetPanel
          targets={targets}
          globalStrategyId={session.globalStrategyId}
          strategies={strategies}
          selectedMarket={selectedMarket}
          tickers={tickers}
          onTargetsChange={handleTargetsChange}
          onSelectMarket={handleSelectMarket}
          onTargetStrategyChange={(market, strategyId) => void handleTargetStrategyChange(market, strategyId)}
        />
      )}
      center={(
        <VirtualTargetGrid
          targets={targets}
          strategies={strategies}
          snapshots={snapshots}
          session={session}
          onTargetStrategyChange={(market, strategyId) => void handleTargetStrategyChange(market, strategyId)}
          liveStatusByMarket={mergedLiveStatus}
          lastTickAtByMarket={lastTickAtByMarket}
          selectedMarket={selectedMarket}
          onSelectMarket={handleSelectMarket}
          theme={theme}
          chartRealtimeSource={chartRealtimeSource}
          chartSeriesPriceLabels={chartSeriesPriceLabels}
          chartLiveReceiveHighlight={chartLiveReceiveHighlight}
          tickers={tickers}
          viewMode={viewMode}
          globalDisplayMode={globalDisplayMode}
          onFocusMarketChange={setFocusMarket}
        />
      )}
      rightTabs={rightTabs}
      right={(
        <div className="ptd-right-body" ref={orderAnchorRef}>
          {rightTab === 'trade' ? (
            <PaperSplitPanel
              className="ptd-split-panel--right"
              topTitle="매수"
              bottomTitle="매도"
              top={(
                <div className="ptd-order-card">
                  <TradeOrderPanel
                    side="buy"
                    market={selectedMarket}
                    tradePrice={tradePrice}
                    availableKrw={coerceFiniteNumber(summary?.cashBalance) ?? 0}
                    fillRequest={fillBuy}
                    searchAnchorRef={orderAnchorRef}
                    onMarketSelect={handleSelectMarket}
                    showSymbolField
                    paperTradingEnabled={paperTradingEnabled}
                    paperAutoTradeEnabled={paperAutoTradeEnabled}
                    onPaperOrderFilled={() => void refreshPaperData({ focusHistory: true })}
                  />
                </div>
              )}
              bottom={(
                <div className="ptd-order-card">
                  <TradeOrderPanel
                    side="sell"
                    market={selectedMarket}
                    tradePrice={tradePrice}
                    availableCoinQty={posQty}
                    fillRequest={fillSell}
                    onMarketSelect={handleSelectMarket}
                    showSymbolField={false}
                    paperTradingEnabled={paperTradingEnabled}
                    paperAutoTradeEnabled={paperAutoTradeEnabled}
                    onPaperOrderFilled={() => void refreshPaperData({ focusHistory: true })}
                  />
                </div>
              )}
            />
          ) : rightTab === 'orderbook' ? (
            <PaperSplitPanel
              className="ptd-split-panel--right"
              topTitle="매도 호가"
              bottomTitle="매수 호가"
              top={(
                <PaperCompactOrderbook
                  market={selectedMarket}
                  onPick={handleObPick}
                  section="asks"
                  fillHeight
                  hideHeader
                  depth={10}
                />
              )}
              bottom={(
                <PaperCompactOrderbook
                  market={selectedMarket}
                  onPick={handleObPick}
                  section="bids"
                  fillHeight
                  hideHeader
                  depth={10}
                />
              )}
            />
          ) : (
            <PaperTradeHistoryList
              trades={trades}
              strategyNames={strategyNames}
              onSelectMarket={handleSelectMarket}
              emptyText="수동·자동 매매 체결 내역이 없습니다."
              className="ptd-trade-history--fill"
            />
          )}
        </div>
      )}
    />
  );
};

export default VirtualTradingPage;
