/**
 * GoldenChart Command Center — Standard + System/Tech
 * (기존 테마·내용 유지, 카드 레이아웃·정렬만 정돈)
 */
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { Theme } from '../types';
import {
  loadDashboardSummary,
  type DashboardSummaryDto,
  type ProcessMonitorDto,
  type SystemMonitorDto,
} from '../utils/backendApi';
import DashboardGauge from './dashboard/DashboardGauge';
import DashboardSegmentBar from './dashboard/DashboardSegmentBar';
import DashboardSparkChart from './dashboard/DashboardSparkChart';
import DashboardIndicatorBar from './dashboard/DashboardIndicatorBar';
import '../styles/strategyEditorTheme.css';
import '../styles/dashboardCommand.css';

interface Props {
  theme: Theme;
  onGoChart?: (market: string) => void;
}

const STATUS_LABEL: Record<string, string> = {
  healthy: '정상',
  degraded: '주의',
  down: '중단',
  disabled: '비활성',
};

const fmtKrw = (n: number) =>
  n >= 1e8 ? `${(n / 1e8).toFixed(2)}억` : n >= 1e4 ? `${(n / 1e4).toFixed(0)}만` : n.toLocaleString('ko-KR');

const fmtPct = (v: number) => `${v >= 0 ? '+' : ''}${(v * 100).toFixed(1)}%`;

function formatAgo(ms: number): string {
  if (!ms) return '—';
  const sec = Math.floor((Date.now() - ms) / 1000);
  if (sec < 60) return `${sec}초 전`;
  if (sec < 3600) return `${Math.floor(sec / 60)}분 전`;
  return `${Math.floor(sec / 3600)}시간 전`;
}

function statusClass(s: string): string {
  if (s === 'healthy') return 'gc-proc--ok';
  if (s === 'degraded') return 'gc-proc--warn';
  if (s === 'down') return 'gc-proc--down';
  return 'gc-proc--off';
}

function healthLevel(mon: SystemMonitorDto): 'green' | 'yellow' | 'red' {
  if (!mon.pipelineEnabled) return 'red';
  if (mon.jvm.heapPct > 85 || mon.queue.dropped > 0 || mon.staleMarkets.length > 5) return 'yellow';
  if (mon.processes.some(p => p.status === 'down')) return 'red';
  if (mon.processes.some(p => p.status === 'degraded')) return 'yellow';
  return 'green';
}

const ProcessCard: React.FC<{ proc: ProcessMonitorDto }> = ({ proc }) => (
  <article className={`gc-proc ${statusClass(proc.status)}`}>
    <header className="gc-proc-head">
      <span className="gc-proc-layer">{proc.layer}</span>
      <span className={`gc-proc-badge ${statusClass(proc.status)}`}>{STATUS_LABEL[proc.status] ?? proc.status}</span>
    </header>
    <h3 className="gc-proc-name">{proc.name}</h3>
    <ul className="gc-proc-metrics">
      {Object.entries(proc.metrics).slice(0, 4).map(([k, v]) => (
        <li key={k}><span>{k}</span><strong>{String(v ?? '—')}</strong></li>
      ))}
    </ul>
  </article>
);

const HISTORY_LEN = 48;

const DashboardPage: React.FC<Props> = ({ theme, onGoChart }) => {
  const [data, setData] = useState<DashboardSummaryDto | null>(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState<string | null>(null);
  const tickHistory = useRef<number[]>([]);
  const wsHistory = useRef<number[]>([]);
  const [, bump] = useState(0);

  const pushHistory = useCallback((ref: React.MutableRefObject<number[]>, v: number) => {
    ref.current = [...ref.current.slice(-(HISTORY_LEN - 1)), v];
  }, []);

  const refresh = useCallback(() => {
    setLoading(true);
    loadDashboardSummary()
      .then(d => {
        if (d?.systemMonitor) {
          pushHistory(tickHistory, d.systemMonitor.traffic.ticksProcessedPerSec ?? 0);
          pushHistory(wsHistory, d.systemMonitor.traffic.wsMessagesPerSec ?? 0);
          bump(n => n + 1);
        }
        setData(d);
        setError(null);
      })
      .catch(e => setError((e as Error).message))
      .finally(() => setLoading(false));
  }, [pushHistory]);

  useEffect(() => {
    refresh();
    const id = window.setInterval(refresh, 5_000);
    return () => window.clearInterval(id);
  }, [refresh]);

  const mon = data?.systemMonitor;
  const app = data?.app as Record<string, unknown> | undefined;
  const health = mon ? healthLevel(mon) : 'yellow';

  const latencyMs = useMemo(() => {
    if (!mon) return 0;
    const tps = mon.traffic.ticksProcessedPerSec ?? 0;
    return tps > 0 ? Math.max(12, Math.round(1000 / Math.max(tps, 1))) : 45;
  }, [mon]);

  const stompConnections = data?.monitoredMarkets ?? 0;

  const ta4jPct = mon && mon.memory.maxBarsPerSeries > 0
    ? Math.min(100, (mon.memory.totalBars / (mon.memory.series * mon.memory.maxBarsPerSeries || 1)) * 100)
    : 0;

  return (
    <div className={`gc-dash-page se-page se-page--${theme}`}>
      <header className="gc-dash-header">
        <div className="gc-dash-header-left">
          <span className="gc-dash-badge">[01] Standard Dashboard</span>
          <h1 className="gc-dash-title">GoldenChart Command Center</h1>
          <p className="gc-dash-sub">실시간 투자 분석 · 파이프라인 모니터링 · 시스템 헬스체크</p>
        </div>
        <div className="gc-dash-header-right">
          <span className="gc-dash-stat">Global Latency: <strong>{latencyMs}ms</strong></span>
          <span className="gc-dash-stat">Active Markets: <strong>{stompConnections}</strong></span>
          {mon && (
            <span className="gc-dash-stat">
              Pipeline <strong className={mon.pipelineEnabled ? 'up' : 'down'}>{mon.pipelineEnabled ? 'ON' : 'OFF'}</strong>
              {mon.sampledAtMs ? ` · ${formatAgo(mon.sampledAtMs)}` : ''}
            </span>
          )}
          <button type="button" className="gc-dash-btn" onClick={refresh} disabled={loading}>
            {loading ? '갱신…' : '새로고침'}
          </button>
        </div>
      </header>

      {error && <p className="gc-dash-error">{error}</p>}

      {data && mon && (
        <div className="gc-dash-body">
          {/* ── LEFT ── */}
          <aside className="gc-dash-col gc-dash-col--left">
            <section className="gc-dash-card gc-dash-card--glow">
              <h2 className="gc-dash-card-title">포트폴리오</h2>
              <div className="gc-dash-card-inner">
                <div className="gc-dash-kpi-hero">
                  <div className="gc-dash-kpi-block">
                    <span className="gc-dash-kpi-label">모의 총자산</span>
                    <strong className="gc-dash-kpi-val">{fmtKrw(data.paper.totalAsset)}</strong>
                    <span className={`gc-dash-kpi-sub ${data.paper.totalReturnPct >= 0 ? 'up' : 'down'}`}>
                      {fmtPct(data.paper.totalReturnPct)}
                    </span>
                  </div>
                  <div className="gc-dash-kpi-block">
                    <span className="gc-dash-kpi-label">실거래 KRW</span>
                    <strong className="gc-dash-kpi-val">{fmtKrw(data.live.krwBalance)}</strong>
                    <span className="gc-dash-kpi-sub">{data.live.configured ? '연동됨' : '미설정'}</span>
                  </div>
                </div>
                <ul className="gc-dash-kv">
                  <li><span>모의 현금</span><strong>{fmtKrw(data.paper.cashBalance)}</strong></li>
                  <li><span>보유 종목</span><strong>{data.paper.positions?.length ?? 0}</strong></li>
                  <li><span>관심종목</span><strong>{data.watchlistCount}</strong></li>
                  <li><span>전략 감시</span><strong>{data.monitoredMarkets}</strong></li>
                </ul>
              </div>
            </section>

            <section className="gc-dash-card">
              <h2 className="gc-dash-card-title">시스템 상태</h2>
              <div className="gc-dash-card-inner gc-dash-card-inner--center">
                <div className={`gc-traffic-light gc-traffic-light--${health}`} aria-label="시스템 상태">
                  <span className="gc-traffic-bulb gc-traffic-bulb--r" />
                  <span className="gc-traffic-bulb gc-traffic-bulb--y" />
                  <span className="gc-traffic-bulb gc-traffic-bulb--g" />
                </div>
                <p className="gc-traffic-caption">
                  {health === 'green' ? '정상 운영' : health === 'yellow' ? '주의 필요' : '점검 필요'}
                </p>
              </div>
            </section>

            <section className="gc-dash-card">
              <h2 className="gc-dash-card-title">리소스 인디케이터</h2>
              <div className="gc-dash-card-inner">
                <div className="gc-ind-grid">
                  <DashboardIndicatorBar label="JVM Heap" pct={mon.jvm.heapPct} />
                  <DashboardIndicatorBar label="Event Queue" pct={(mon.queue.fillRatio ?? 0) * 100} />
                  <DashboardIndicatorBar label="Ta4j Cache" pct={ta4jPct} />
                  <DashboardIndicatorBar label="WS Load" pct={Math.min(100, (mon.traffic.wsMessagesPerSec ?? 0) * 2)} />
                </div>
              </div>
            </section>

            <section className="gc-dash-card gc-dash-card--compact">
              <h2 className="gc-dash-card-title">매매 모드</h2>
              <div className="gc-dash-card-inner">
                <ul className="gc-dash-kv">
                  <li><span>운영 모드</span><strong>{String(app?.tradingMode ?? '—')}</strong></li>
                  <li><span>실거래 자동</span><strong>{app?.liveAutoTradeEnabled ? 'ON' : 'OFF'}</strong></li>
                  <li><span>모의 자동</span><strong>{app?.paperAutoTradeEnabled ? 'ON' : 'OFF'}</strong></li>
                  <li><span>FCM</span><strong>{data.fcm.pushEnabled ? (data.fcm.available ? '활성' : '미연결') : 'OFF'}</strong></li>
                </ul>
              </div>
            </section>
          </aside>

          {/* ── CENTER ── */}
          <main className="gc-dash-col gc-dash-col--center">
            <section className="gc-dash-card gc-dash-card--wide">
              <h2 className="gc-dash-card-title">[04] 데이터 파이프라인 · Ta4j 엔진</h2>
              <div className="gc-dash-card-inner">
                <div className="gc-infra-grid">
                  <DashboardSegmentBar
                    label="Ta4jStorage"
                    valueLabel={`${mon.memory.markets}종목 · ${mon.memory.totalBars.toLocaleString()}봉`}
                    pct={ta4jPct}
                    tone="green"
                  />
                  <DashboardSegmentBar
                    label="Event Queue"
                    valueLabel={`${mon.queue.pending} / ${mon.queue.capacity?.toLocaleString() ?? '—'}`}
                    pct={(mon.queue.fillRatio ?? 0) * 100}
                    tone={mon.queue.fillRatio > 0.7 ? 'amber' : 'cyan'}
                  />
                  <DashboardSegmentBar
                    label="Order Worker"
                    valueLabel={`${mon.orders.executed} executed · ${mon.orders.failed} fail`}
                    pct={Math.min(100, mon.orders.ratePerSecond * 10)}
                    tone="cyan"
                  />
                  <DashboardSegmentBar
                    label="Tick Worker"
                    valueLabel={`${mon.workers.processed.toLocaleString()} processed`}
                    pct={mon.workers.active ? 85 : 20}
                    tone={mon.workers.active ? 'green' : 'red'}
                  />
                </div>
              </div>
            </section>

            <section className="gc-dash-card gc-dash-card--chart">
              <div className="gc-dash-card-inner">
                <DashboardSparkChart series={tickHistory.current} label="Tick 처리량 (실시간)" height={160} />
              </div>
            </section>

            <section className="gc-dash-card gc-dash-card--wide">
              <h2 className="gc-dash-card-title">멀티스레드 프로세스</h2>
              <div className="gc-dash-card-inner">
                <div className="gc-proc-grid">
                  {mon.processes.map(p => <ProcessCard key={p.id} proc={p} />)}
                </div>
              </div>
            </section>

            {mon.staleMarkets.length > 0 && (
              <section className="gc-dash-card gc-dash-card--warn">
                <h2 className="gc-dash-card-title">틱 정체 종목 ({mon.staleMarkets.length})</h2>
                <div className="gc-dash-card-inner">
                  <div className="gc-stale-chips">
                    {mon.staleMarkets.slice(0, 8).map(s => (
                      <button key={s.market} type="button" className="gc-stale-chip" onClick={() => onGoChart?.(s.market)}>
                        {s.market.replace('KRW-', '')} · {s.lastTickAgeSec}s
                      </button>
                    ))}
                  </div>
                </div>
              </section>
            )}
          </main>

          {/* ── RIGHT ── */}
          <aside className="gc-dash-col gc-dash-col--right">
            <section className="gc-dash-card gc-dash-card--glow">
              <h2 className="gc-dash-card-title">성과 · 리스크</h2>
              <div className="gc-dash-card-inner">
                <div className="gc-gauge-grid">
                  <DashboardGauge
                    label="JVM Heap"
                    value={`${mon.jvm.heapPct}%`}
                    pct={mon.jvm.heapPct}
                    tone={mon.jvm.heapPct > 85 ? 'red' : 'green'}
                  />
                  <DashboardGauge
                    label="Queue Fill"
                    value={`${Math.round((mon.queue.fillRatio ?? 0) * 100)}%`}
                    pct={(mon.queue.fillRatio ?? 0) * 100}
                    tone={(mon.queue.fillRatio ?? 0) > 0.7 ? 'amber' : 'cyan'}
                  />
                  <DashboardGauge
                    label="모의 수익률"
                    value={fmtPct(data.paper.totalReturnPct)}
                    pct={Math.min(100, Math.abs(data.paper.totalReturnPct) * 200)}
                    max={100}
                    tone={data.paper.totalReturnPct >= 0 ? 'green' : 'red'}
                  />
                  <DashboardGauge
                    label="WS msg/s"
                    value={String(mon.traffic.wsMessagesPerSec ?? 0)}
                    pct={Math.min(100, (mon.traffic.wsMessagesPerSec ?? 0) * 3)}
                    tone="cyan"
                  />
                </div>
              </div>
            </section>

            <section className="gc-dash-card gc-dash-card--chart-sm">
              <div className="gc-dash-card-inner">
                <DashboardSparkChart series={wsHistory.current} label="WebSocket 수신" height={80} />
              </div>
            </section>

            <section className="gc-dash-card gc-dash-card--flex">
              <h2 className="gc-dash-card-title">최근 시그널 · 체결</h2>
              <div className="gc-dash-card-inner gc-dash-card-inner--flex">
                {data.recentSignals.length === 0 ? (
                  <p className="gc-dash-muted">최근 시그널 없음</p>
                ) : (
                  <ul className="gc-signal-list">
                    {data.recentSignals.slice(0, 12).map(s => {
                      const buy = s.signalType === 'BUY';
                      return (
                        <li key={s.id} className={`gc-signal-item gc-signal-item--${buy ? 'buy' : 'sell'}`}>
                          <span className="gc-signal-arrow">{buy ? '▲' : '▼'}</span>
                          <button type="button" className="gc-signal-main" onClick={() => onGoChart?.(s.market)}>
                            <strong>{buy ? 'BUY' : 'SELL'}</strong>
                            <span>{s.market.replace('KRW-', '')}</span>
                            <span className="gc-signal-price">@ {s.price?.toLocaleString('ko-KR')}</span>
                          </button>
                          <span className="gc-signal-time">{s.createdAt?.slice(11, 16) ?? ''}</span>
                        </li>
                      );
                    })}
                  </ul>
                )}
              </div>
            </section>
          </aside>
        </div>
      )}
    </div>
  );
};

export default DashboardPage;
