/*
 * Holy Grail · Spectrum LIVE patch
 * CCB-00-07 — 將 window.HG2Atoms.Spectrum 從假動畫覆寫成 WebSocket 訂閱版
 *
 * 載入順序：必須在 hg2-atoms.jsx 之後、hg2-hub.jsx 之前
 *
 * 機制：
 *   1. 監視 active pilder（觀察 .hub-crumb 內 PLD-XXX 文字 + window.HG2.PILDERS 反查 id）
 *   2. 為每個 active pilder 開一條 WebSocket 到 /v1/resonance/{id}
 *   3. WS frame.bars 寫進全域 store + 通知所有訂閱 React component
 *   4. 覆寫 window.HG2Atoms.Spectrum 為 LiveSpectrum：
 *      - 有 WS frame  → 用 server 真實 bars + 顯示 ◆ LIVE 字樣
 *      - 沒有 WS frame → fallback 到原本演算法（保證不退化）
 */

(function () {
  if (!window.HG2Atoms || !window.HG2Atoms.Spectrum) {
    console.warn('[HG2/resonance-live] HG2Atoms.Spectrum 不存在，patch 取消');
    return;
  }

  // ── 全域 store ─────────────────────────────────────────
  const ResonanceStore = {
    frame: null,           // 最新 WS frame
    pilderId: null,        // 當前訂閱的 pilder id
    ws: null,
    subscribers: new Set(),
    lastFrameAt: 0,
  };

  function notify() {
    ResonanceStore.subscribers.forEach((fn) => fn());
  }

  function openWS(id) {
    if (ResonanceStore.ws) {
      try { ResonanceStore.ws.close(); } catch (_) {}
      ResonanceStore.ws = null;
    }
    if (!id) {
      ResonanceStore.frame = null;
      notify();
      return;
    }
    const url = (location.protocol === 'https:' ? 'wss://' : 'ws://') +
                location.host + '/v1/resonance/' + encodeURIComponent(id);
    const ws = new WebSocket(url);
    ResonanceStore.ws = ws;

    ws.onopen = () => {
      console.log('%c[HG2/resonance] WS open · ' + id,
        'color:#6FB8FF;font-weight:bold');
    };
    ws.onmessage = (e) => {
      try {
        const d = JSON.parse(e.data);
        if (d.kind === 'hello') {
          console.log('%c[HG2/resonance] hello · ' + d.pilder_code +
                      ' · ' + d.rate_hz + 'Hz · state=' + d.initial_state,
                      'color:' + d.theme.energy);
          return;
        }
        if (d.kind === 'frame') {
          ResonanceStore.frame = d;
          ResonanceStore.lastFrameAt = performance.now();
          notify();
        }
      } catch (err) {
        console.warn('[HG2/resonance] parse error', err);
      }
    };
    ws.onerror = (e) => {
      console.warn('[HG2/resonance] WS error', e);
    };
    ws.onclose = () => {
      ResonanceStore.frame = null;
      notify();
    };
  }

  // ── 監視 active pilder（以 hub-crumb 顯示的 PLD-code 為準）──
  function pollActive() {
    const codeEl = document.querySelector('.hub-crumb .energy');
    if (!codeEl) return;
    const code = (codeEl.textContent || '').trim();
    const pilders = (window.HG2 && window.HG2.PILDERS) || [];
    const p = pilders.find((x) => x.code === code);
    if (!p) return;
    if (p.id !== ResonanceStore.pilderId) {
      ResonanceStore.pilderId = p.id;
      openWS(p.id);
    }
  }
  setInterval(pollActive, 250);

  // ── 覆寫 Spectrum 元件 ─────────────────────────────────
  const OriginalSpectrum = window.HG2Atoms.Spectrum;
  const { useState, useEffect, useRef } = React;

  function LiveSpectrum({ stable = true, intensity = 1 }) {
    const [, force] = useState(0);
    const tickRef = useRef(0);

    useEffect(() => {
      const fn = () => {
        tickRef.current += 1;
        force(tickRef.current);
      };
      ResonanceStore.subscribers.add(fn);
      return () => { ResonanceStore.subscribers.delete(fn); };
    }, []);

    const frame = ResonanceStore.frame;
    const isStale = frame && (performance.now() - ResonanceStore.lastFrameAt > 2000);
    const isLive = !!frame && !isStale;

    // Fallback：沒 WS 資料時退回原本動畫（教練看 mock 模式仍可動）
    if (!isLive) {
      return React.createElement(
        'div',
        { style: { position: 'relative', width: '100%', height: '100%' } },
        React.createElement(OriginalSpectrum, { stable, intensity }),
        React.createElement(
          'div',
          {
            style: {
              position: 'absolute', top: 4, right: 4,
              fontFamily: 'JetBrains Mono, monospace', fontSize: 9,
              letterSpacing: '0.16em', color: '#FF4D4D',
              padding: '2px 6px', border: '1px solid rgba(255,77,77,0.55)',
            },
          },
          isStale ? '◯ STALE' : '◯ MOCK'
        )
      );
    }

    // LIVE 渲染
    const W = 600, H = 150;
    const bars = frame.bars || [];
    const N = bars.length || 56;
    const energy = (frame.theme && frame.theme.energy) || 'var(--energy)';
    const isWarden = frame.warden_pulse;

    const labelColor = isWarden ? 'var(--gold)' : energy;
    const labelText = isWarden
      ? '◆ WARDEN · ' + (frame.state || '').toUpperCase()
      : '◆ LIVE · ' + (frame.state || '').toUpperCase() + ' · ' +
        (frame.intensity * 100).toFixed(0) + '%';

    return React.createElement(
      'div',
      { style: { position: 'relative', width: '100%', height: '100%' } },
      React.createElement(
        'svg',
        {
          viewBox: '0 0 ' + W + ' ' + H,
          preserveAspectRatio: 'none',
          style: { width: '100%', height: '100%' },
        },
        React.createElement(
          'defs', null,
          React.createElement(
            'linearGradient',
            { id: 'v2-spec-live', x1: 0, x2: 0, y1: 0, y2: 1 },
            React.createElement('stop', { offset: '0%', stopColor: energy, stopOpacity: 0.95 }),
            React.createElement('stop', { offset: '100%', stopColor: energy, stopOpacity: 0.08 })
          )
        ),
        [0.25, 0.5, 0.75].map((p, i) =>
          React.createElement('line', {
            key: 'g' + i,
            x1: 0, x2: W, y1: H * p, y2: H * p,
            stroke: 'var(--hair)', strokeDasharray: '2 4',
          })
        ),
        bars.map((h, i) => {
          const x = (i / N) * W;
          const bh = Math.max(2, Math.min(H - 4, H * 0.85 * Math.max(0.05, h)));
          return React.createElement('rect', {
            key: i,
            x: x + 1.5, y: H - bh,
            width: W / N - 3, height: bh,
            fill: isWarden && bh > H * 0.4 ? 'var(--gold)' : 'url(#v2-spec-live)',
          });
        })
      ),
      // LIVE 標籤
      React.createElement(
        'div',
        {
          style: {
            position: 'absolute', top: 4, right: 4,
            fontFamily: 'JetBrains Mono, monospace', fontSize: 9,
            letterSpacing: '0.16em', color: labelColor,
            padding: '2px 6px',
            border: '1px solid ' + labelColor,
            background: 'rgba(0,0,0,0.4)',
          },
        },
        labelText
      )
    );
  }

  window.HG2Atoms.Spectrum = LiveSpectrum;
  window.HG2_RESONANCE = ResonanceStore;  // expose for debug
  console.log('%c[HG2/resonance-live] Spectrum patched · subscribing to /v1/resonance',
    'color:#E8C268;font-weight:bold');
})();
