/**
 * 모의투자 대시보드 — 가상매매와 동일 3열 레이아웃(좌·중앙·우 접기/리사이즈)
 */
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import {
  loadPaperSummary,
  loadPaperTradesPaged,
  loadPaperPendingOrders,
  loadStrategies,
  resetPaperAccount,
  type PaperOrderDto,
  type PaperPositionDto,
  type PaperSummaryDto,
  type PaperTradeDto,
  type StrategyDto,
} from '../utils/backendApi';
import type { TickerData } from '../hooks/useMarketTicker';
import { coerceFiniteNumber } from '../utils/safeFormat';
import PaperInvestmentKpi from './paper/PaperInvestmentKpi';
import PaperAllocationTable from './paper/PaperAllocationTable';
import PaperPendingOrdersList from './paper/PaperPendingOrdersList';
import PaperLedgerTab from './paper/PaperLedgerTab';
import PaperAssetTrendChart from './paper/PaperAssetTrendChart';
import { computePaperMetrics } from '../utils/paperMetrics';
import { TradeSplitOrderPanel, TradeOrderbookPanelContent, TradeRightPanelBody } from './trade';
import type { Theme, TradeOrderFillRequest } from '../types';
import PaperAnalysisChart from './paper/PaperAnalysisChart';
import PaperLeftStrategyTab from './paper/PaperLeftStrategyTab';
import PaperLeftSettingsTab from './paper/PaperLeftSettingsTab';
import PaperTradeHistoryList from './paper/PaperTradeHistoryList';
import BuilderPageShell from './layout/BuilderPageShell';
import { useUpbitOrderbook } from '../hooks/useUpbitOrderbook';
import { useUpbitRecentTrades } from '../hooks/useUpbitRecentTrades';

type HistoryTab = 'open' | 'recent' | 'ledger';
type CenterTab = 'invest' | 'chart';
type RightTab = 'trade' | 'orderbook' | 'history';
type LeftTab = 'strategy' | 'settings';

interface Props {
  theme?: Theme;
  tickers?: Map<string, TickerData>;
  onGoChart?: (market: string) => void;
  refreshKey?: number;
  defaultMarket?: string;
  paperTradingEnabled?: boolean;
  paperAutoTradeEnabled?: boolean;
  onPaperOrderFilled?: () => void;
  /** 설정 → 모의투자 카테고리로 이동 */
  onOpenSettings?: () => void;
}

function buildMarkPrices(
  summary: PaperSummaryDto | null,
  tickers?: Map<string, TickerData>,
): Record<string, number> {
  const m: Record<string, number> = {};
  summary?.positions?.forEach(p => {
    const t = tickers?.get(p.symbol)?.tradePrice;
    if (t != null && t > 0) m[p.symbol] = t;
  });
  return m;
}

function positionPriceKey(
  positions: PaperPositionDto[] | undefined,
  tickers?: Map<string, TickerData>,
): string {
  if (!positions?.length) return '';
  return positions.map(p => `${p.symbol}:${tickers?.get(p.symbol)?.tradePrice ?? ''}`).join('|');
}

function coinCode(symbol: string): string {
  return symbol.replace(/^KRW-/, '');
}

const PaperTradingPage: React.FC<Props> = ({
  theme = 'dark',
  tickers,
  refreshKey = 0,
  defaultMarket = 'KRW-BTC',
  paperTradingEnabled = true,
  paperAutoTradeEnabled = false,
  onPaperOrderFilled,
  onOpenSettings,
}) => {
  const [strategies, setStrategies] = useState<StrategyDto[]>([]);
  const [summary, setSummary] = useState<PaperSummaryDto | null>(null);
  const [trades, setTrades] = useState<PaperTradeDto[]>([]);
  const [pendingOrders, setPendingOrders] = useState<PaperOrderDto[]>([]);
  const [dataRefreshKey, setDataRefreshKey] = useState(0);
  const [initialLoading, setInitialLoading] = useState(true);
  const [selectedMarket, setSelectedMarket] = useState(defaultMarket);
  const [centerTab, setCenterTab] = useState<CenterTab>('invest');
  const [historyTab, setHistoryTab] = useState<HistoryTab>('recent');
  const [rightTab, setRightTab] = useState<RightTab>('trade');
  const [leftTab, setLeftTab] = useState<LeftTab>('strategy');
  const [fillBuy, setFillBuy] = useState<TradeOrderFillRequest | null>(null);
  const [fillSell, setFillSell] = useState<TradeOrderFillRequest | null>(null);
  const orderAnchorRef = useRef<HTMLDivElement>(null);

  const tickersRef = useRef(tickers);
  tickersRef.current = tickers;
  const summaryRef = useRef(summary);
  summaryRef.current = summary;

  const loadData = useCallback(async (opts?: { focusHistory?: boolean }) => {
    try {
      const base = await loadPaperSummary();
      const marks = buildMarkPrices(base, tickersRef.current);
      const full = Object.keys(marks).length > 0 ? await loadPaperSummary(marks) : base;
      setSummary(full);
      const tradePage = await loadPaperTradesPaged({ page: 0, size: 100 });
      setTrades(tradePage.content);
      setPendingOrders(await loadPaperPendingOrders());
      setDataRefreshKey(k => k + 1);
    } finally {
      setInitialLoading(false);
    }
    if (opts?.focusHistory) setRightTab('history');
  }, []);

  useEffect(() => {
    void Promise.all([
      loadData(),
      loadStrategies().then(setStrategies).catch(() => setStrategies([])),
    ]);
  }, [loadData]);

  useEffect(() => { if (refreshKey > 0) void loadData(); }, [refreshKey, loadData]);

  const priceKey = positionPriceKey(summary?.positions, tickers);
  const lastPriceKeyRef = useRef('');
  useEffect(() => {
    if (!priceKey || initialLoading || priceKey === lastPriceKeyRef.current) return;
    lastPriceKeyRef.current = priceKey;
    let cancelled = false;
    (async () => {
      const marks = buildMarkPrices(summaryRef.current, tickersRef.current);
      if (!Object.keys(marks).length) return;
      try {
        const full = await loadPaperSummary(marks);
        if (!cancelled) setSummary(full);
      } catch { /* ignore */ }
    })();
    return () => { cancelled = true; };
  }, [priceKey, initialLoading]);

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

  const metrics = useMemo(() => computePaperMetrics(trades, summary), [trades, summary]);
  const s = summary;

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

  const selectedAlloc = useMemo(
    () => s?.allocations?.find(a => a.symbol === selectedMarket),
    [s?.allocations, selectedMarket],
  );

  const orderableCash = s?.orderableCash ?? s?.cashBalance ?? 0;

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

  const { orderbook, wsStatus: obWsStatus, spread } = useUpbitOrderbook(selectedMarket);
  const { trades: recentTrades, strength: tradeStrength } = useUpbitRecentTrades(selectedMarket);
  const selectedTicker = tickers?.get(selectedMarket);
  const orderbookPrevClose = selectedTicker
    ? (selectedTicker.tradePrice ?? 0) - (selectedTicker.changePrice ?? 0)
    : 0;
  const orderbookTickerInfo = selectedTicker ? {
    tradePrice: selectedTicker.tradePrice,
    changeRate: selectedTicker.changeRate,
    changePrice: selectedTicker.changePrice,
    accTradePrice24: selectedTicker.accTradePrice24,
    accTradeVolume24: selectedTicker.accTradeVolume24,
    highPrice: selectedTicker.highPrice,
    lowPrice: selectedTicker.lowPrice,
    openingPrice: selectedTicker.openingPrice,
  } : undefined;

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

  const handleReset = useCallback(async () => {
    if (!window.confirm('모의투자 계좌를 초기화합니다. 계속할까요?')) return;
    const res = await resetPaperAccount();
    if (res) {
      setSummary(res);
      setTrades([]);
      setPendingOrders([]);
    }
  }, []);

  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>
  );

  const leftTabs = (
    <div className="bps-left-tabs">
      <button type="button" className={`bps-left-tab${leftTab === 'strategy' ? ' bps-left-tab--on' : ''}`} onClick={() => setLeftTab('strategy')}>전략</button>
      <button type="button" className={`bps-left-tab${leftTab === 'settings' ? ' bps-left-tab--on' : ''}`} onClick={() => setLeftTab('settings')}>설정</button>
    </div>
  );

  return (
    <BuilderPageShell
      theme={theme}
      title="투자관리"
      subtitle="Investment Management"
      pageClassName="bps-page--vtd bps-page--ptd"
      loading={initialLoading}
      loadingText="투자관리 대시보드 로딩…"
      collapsiblePanels
      leftStorageKey="ptd-left-width"
      leftDefaultWidth={380}
      leftCollapsedStorageKey="ptd-left-open"
      rightStorageKey="ptd-right-width"
      rightDefaultWidth={440}
      rightCollapsedStorageKey="ptd-right-open"
      headerCenter={!paperTradingEnabled ? (
        <span className="bps-header-status-text" role="status">
          모의투자가 꺼져 있습니다. 설정에서 활성화하세요.
        </span>
      ) : undefined}
      headerCenterMode="between"
      headerActions={(
        <>
          <button type="button" className="bps-btn bps-btn--ghost" onClick={() => void loadData()}>새로고침</button>
          <button type="button" className="bps-btn bps-btn--danger" onClick={() => void handleReset()}>계좌 초기화</button>
        </>
      )}
      leftTabs={leftTabs}
      left={leftTab === 'strategy' ? (
        <PaperLeftStrategyTab
          market={selectedMarket}
          summary={s}
          paperAutoTradeEnabled={paperAutoTradeEnabled}
          onMarketSelect={handleSelectMarket}
        />
      ) : (
        <PaperLeftSettingsTab
          onOpenSettings={onOpenSettings}
          onSettingsSaved={() => void loadData()}
          onAccountReset={() => { setSummary(null); setTrades([]); void loadData(); }}
        />
      )}
      centerHead={(
        <div className="ptd-center-head">
          <div className="ptd-tabs ptd-tabs--center">
            <button type="button" className={`ptd-tab${centerTab === 'invest' ? ' active' : ''}`} onClick={() => setCenterTab('invest')}>투자금 관리</button>
            <button type="button" className={`ptd-tab${centerTab === 'chart' ? ' active' : ''}`} onClick={() => setCenterTab('chart')}>차트</button>
          </div>
          <span className="bps-center-head-title">{coinCode(selectedMarket)} / KRW</span>
        </div>
      )}
      center={centerTab === 'invest' ? (
        <div className="ptd-card ptd-invest-card ptd-center-fill">
          <PaperInvestmentKpi summary={s} />
          <PaperAllocationTable
            allocations={s?.allocations ?? []}
            selectedMarket={selectedMarket}
            onSelectMarket={handleSelectMarket}
            onChanged={() => void loadData()}
          />
          <div className="ptd-invest-metrics">
            <PaperAssetTrendChart refreshKey={dataRefreshKey} />
            <div className="ptd-metrics-grid">
              <MetricCard label="MDD" value={`${metrics.mddPct.toFixed(2)}%`} tone="down" />
              <MetricCard label="Sharpe Ratio" value={metrics.sharpeRatio.toFixed(2)} tone="up" />
              <MetricCard label="Win Rate" value={`${metrics.winRatePct.toFixed(0)}%`} tone="up" />
              <MetricCard label="Profit Factor" value={metrics.profitFactor.toFixed(2)} tone="up" />
            </div>
          </div>
        </div>
      ) : (
        <div className="ptd-card ptd-chart-card ptd-center-fill">
          <PaperAnalysisChart market={selectedMarket} theme={theme} />
        </div>
      )}
      rightTabs={rightTabs}
      right={(
        <TradeRightPanelBody anchorRef={orderAnchorRef} embeddedInShell>
          {rightTab === 'trade' ? (
            <TradeSplitOrderPanel
              market={selectedMarket}
              tradePrice={tradePrice}
              availableKrw={orderableCash}
              availableSymbolBuyKrw={selectedAlloc?.availableBuyKrw}
              fillBuy={fillBuy}
              fillSell={fillSell}
              searchAnchorRef={orderAnchorRef}
              onMarketSelect={handleSelectMarket}
              paperTradingEnabled={paperTradingEnabled}
              paperAutoTradeEnabled={paperAutoTradeEnabled}
              onPaperOrderFilled={() => void loadData({ focusHistory: true })}
            />
          ) : rightTab === 'orderbook' ? (
            <TradeOrderbookPanelContent
              market={selectedMarket}
              asks={orderbook.asks}
              bids={orderbook.bids}
              totalAskSize={orderbook.totalAskSize}
              totalBidSize={orderbook.totalBidSize}
              wsStatus={obWsStatus}
              bestAsk={spread.bestAsk}
              bestBid={spread.bestBid}
              spread={spread.spread}
              spreadPct={spread.pct}
              prevClose={orderbookPrevClose}
              tickerInfo={orderbookTickerInfo}
              recentTrades={recentTrades}
              tradeStrength={tradeStrength ?? undefined}
              onRowClick={handleOrderbookRowClick}
            />
          ) : (
            <div className="ptd-right-history">
              <div className="ptd-tabs ptd-tabs--history">
                <button type="button" className={`ptd-tab${historyTab === 'open' ? ' active' : ''}`} onClick={() => setHistoryTab('open')}>미체결</button>
                <button type="button" className={`ptd-tab${historyTab === 'recent' ? ' active' : ''}`} onClick={() => setHistoryTab('recent')}>체결</button>
                <button type="button" className={`ptd-tab${historyTab === 'ledger' ? ' active' : ''}`} onClick={() => setHistoryTab('ledger')}>원장</button>
              </div>
              <div className="ptd-right-history-body">
                {historyTab === 'open' ? (
                  <PaperPendingOrdersList orders={pendingOrders} onChanged={() => void loadData()} />
                ) : historyTab === 'ledger' ? (
                  <PaperLedgerTab refreshKey={dataRefreshKey} />
                ) : (
                  <PaperTradeHistoryList
                    trades={trades}
                    strategyNames={strategyNames}
                    tickers={tickers}
                    onSelectMarket={handleSelectMarket}
                    emptyText="체결 내역이 없습니다."
                    className="ptd-trade-history--fill"
                  />
                )}
              </div>
            </div>
          )}
        </TradeRightPanelBody>
      )}
    />
  );
};

function MetricCard({ label, value, tone }: {
  label: string; value: string; tone: 'up' | 'down';
}) {
  return (
    <div className={`ptd-metric ptd-metric--${tone}`}>
      <span className="ptd-metric-label">{label}</span>
      <span className="ptd-metric-value">{value}</span>
    </div>
  );
}

export default PaperTradingPage;
