// ===== React UI 層:Loading / HUD / 名牌 / 轉場 / 橫向相簿 / Tweaks =====
const { useState, useEffect, useRef, useCallback } = React;

const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
  "outfit": "#d6263c",
  "volume": 70,
  "flicker": true,
  "sway": true
}/*EDITMODE-END*/;

const TOPICS = window.CASINO_CONTENT.topics;
const PROFILE = window.CASINO_CONTENT.profile;
const FUTURE_IDX = window.FUTURE_TOPIC_INDEX;

function App() {
  const [t, setTweak] = useTweaks(TWEAK_DEFAULTS);
  const [phase, setPhase] = useState('loading');      // loading | playing
  const [gameState, setGameState] = useState('loading');
  const [nameCard, setNameCard] = useState(false);
  const [transition, setTransition] = useState(null); // topic index
  const [gallery, setGallery] = useState(null);       // topic index
  const [finale, setFinale] = useState(false);
  const [muted, setMuted] = useState(false);
  // 拉霸紀錄只存在記憶體:重新整理網頁就會歸零
  const [visited, setVisited] = useState([]);
  const gameRef = useRef(null);
  const visitedRef = useRef(visited);
  visitedRef.current = visited;

  // 建立 3D 場景
  useEffect(() => {
    let cancelled = false;
    document.fonts.ready.then(() => {
      if (cancelled || gameRef.current) return;
      const game = new window.CasinoGame(document.getElementById('scene'));
      gameRef.current = game;
      window.__game = game;
      game.on('state', (s) => setGameState(s));
      game.on('spinRequest', () => requestSpinRef.current());
      game.on('spinResult', (idx) => {
        setTransition(idx);
        setTimeout(() => {
          setGallery(idx);
          setTransition(null);
        }, 1500);
      });
    });
    return () => { cancelled = true; };
  }, []);

  // 決定下一個主題:未來展望壓軸,其餘隨機不重複
  const requestSpin = useCallback(() => {
    const v = visitedRef.current;
    const remaining = TOPICS.map((tp, i) => i).filter((i) => !v.includes(TOPICS[i].id));
    if (remaining.length === 0) { setFinale(true); window.CasinoSound.jackpot(); return; }
    let pick;
    const nonFuture = remaining.filter((i) => i !== FUTURE_IDX);
    if (nonFuture.length === 0) pick = FUTURE_IDX;
    else pick = nonFuture[Math.floor(Math.random() * nonFuture.length)];
    gameRef.current.spin(pick);
  }, []);
  const requestSpinRef = useRef(requestSpin);
  requestSpinRef.current = requestSpin;

  // 進相簿時記錄進度(只記在記憶體)
  useEffect(() => {
    if (gallery == null) return;
    const id = TOPICS[gallery].id;
    setVisited((v) => (v.includes(id) ? v : [...v, id]));
  }, [gallery]);

  // 任一覆蓋層開啟時,封鎖 3D 場景的鍵盤操作
  const overlayOpen = nameCard || transition != null || gallery != null || finale;
  useEffect(() => {
    const g = gameRef.current;
    if (g) g.setUIBlocked(phase !== 'playing' || overlayOpen);
  }, [phase, overlayOpen]);

  // Tweaks 套用到 3D / 音效
  useEffect(() => {
    const g = gameRef.current;
    if (g && g.character) g.character.setBodyColor(parseInt(t.outfit.slice(1), 16));
  }, [t.outfit, gameState]);
  useEffect(() => { window.CasinoSound.setVolume(t.volume / 100); }, [t.volume]);
  useEffect(() => { window.NEON_FLICKER = t.flicker; }, [t.flicker]);
  useEffect(() => { window.CAMERA_SWAY = t.sway; }, [t.sway]);

  // Esc:先關覆蓋層,沒有覆蓋層且坐著時 → 起身
  useEffect(() => {
    const onKey = (e) => {
      if (e.key !== 'Escape') return;
      if (gallery != null) { setGallery(null); return; }
      if (nameCard) { setNameCard(false); return; }
      if (finale) { setFinale(false); return; }
      if (phase === 'playing' && gameState === 'ready') {
        gameRef.current && gameRef.current.standUp();
      }
    };
    window.addEventListener('keydown', onKey);
    return () => window.removeEventListener('keydown', onKey);
  }, [phase, gameState, gallery, nameCard, finale]);

  const enter = () => {
    window.CasinoSound.unlock();
    window.CasinoSound.startAmbient();
    window.CasinoSound.jackpot();
    setPhase('playing');
    gameRef.current && gameRef.current.enter();
  };

  const toggleMute = () => {
    setMuted((m) => { window.CasinoSound.setMuted(!m); return !m; });
  };

  const resetProgress = () => {
    setVisited([]);
    setFinale(false);
    window.CasinoSound.click();
  };

  const hint = (() => {
    if (phase !== 'playing' || transition != null || gallery != null) return null;
    if (gameState === 'roam') {
      return (
        <span>
          <kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> 移動&ensp;·&ensp;
          <kbd>Space</kbd> 跳躍&ensp;·&ensp;走近拉霸機按 <kbd>F</kbd> 入座
        </span>
      );
    }
    if (gameState === 'ready') {
      return visited.length >= TOPICS.length
        ? <span>全部主題都分享完了!<kbd>Space</kbd> 再轉一次&ensp;·&ensp;<kbd>Esc</kbd> 起身</span>
        : <span><kbd>Space</kbd> 拉霸&ensp;·&ensp;<kbd>Esc</kbd> 起身離開</span>;
    }
    return null;
  })();

  return (
    <React.Fragment>
      {phase === 'loading' && <LoadingScreen onEnter={enter} />}

      {phase === 'playing' && (
        <div className="hud">
          <button className="hud-btn hud-left" onClick={() => { setNameCard(true); window.CasinoSound.whoosh(); }}>♠ 名牌</button>
          <div className="hud-right">
            {visited.length > 0 && <button className="hud-btn" onClick={resetProgress} title="重置拉霸進度">↺</button>}
            <button className="hud-btn" onClick={toggleMute}>{muted ? '🔇' : '🔊'}</button>
          </div>
          {hint && <div className="hint">{hint}</div>}
          <div className="progress">
            {TOPICS.map((tp) => (
              <div key={tp.id} className={'p-chip' + (visited.includes(tp.id) ? ' lit' : '')}
                   style={visited.includes(tp.id) ? { color: tp.color, borderColor: tp.color } : null}
                   title={tp.name}>
                <span>{tp.symbol}</span>
              </div>
            ))}
          </div>
        </div>
      )}

      {nameCard && <NameCard onClose={() => setNameCard(false)} />}
      {transition != null && <Transition topic={TOPICS[transition]} />}
      {gallery != null && <Gallery topic={TOPICS[gallery]} onClose={() => { setGallery(null); window.CasinoSound.click(); }} />}
      {finale && <Finale onClose={() => setFinale(false)} onReset={resetProgress} />}

      <TweaksPanel>
        <TweakSection label="人物" />
        <TweakColor label="服裝顏色" value={t.outfit}
                    options={['#d6263c', '#7a3ce8', '#1f8a5b', '#2a6fdb']}
                    onChange={(v) => setTweak('outfit', v)} />
        <TweakSection label="氣氛" />
        <TweakSlider label="音量" value={t.volume} min={0} max={100} step={5} unit="%"
                     onChange={(v) => setTweak('volume', v)} />
        <TweakToggle label="霓虹閃爍" value={t.flicker} onChange={(v) => setTweak('flicker', v)} />
        <TweakToggle label="鏡頭微晃" value={t.sway} onChange={(v) => setTweak('sway', v)} />
      </TweaksPanel>
    </React.Fragment>
  );
}

// ---------- Loading ----------
function LoadingScreen({ onEnter }) {
  const [ready, setReady] = useState(false);
  useEffect(() => { const id = setTimeout(() => setReady(true), 1600); return () => clearTimeout(id); }, []);
  return (
    <div className="loading">
      <div className="neon-frame">
        <div className="neon-title">CASINO</div>
        <div className="neon-sub">自 我 介 紹 之 夜</div>
        <div className="neon-deco">★ ♠ ♦ ♥ ♣ ★</div>
      </div>
      <div className="loading-controls">
        <span><kbd>W</kbd><kbd>A</kbd><kbd>S</kbd><kbd>D</kbd> 移動</span>
        <span><kbd>Space</kbd> 跳躍 / 拉霸</span>
        <span><kbd>F</kbd> 入座</span>
        <span><kbd>Esc</kbd> 起身</span>
      </div>
      <button className={'enter-btn' + (ready ? ' show' : '')} onClick={onEnter}>進 場</button>
      <div className="loading-tip">建議開聲音 🔊 體驗最佳</div>
    </div>
  );
}

// ---------- 名牌 ----------
function NameCard({ onClose }) {
  return (
    <div className="overlay" onClick={onClose}>
      <div className="vip-card" onClick={(e) => e.stopPropagation()}>
        <div className="vip-head">
          <span className="vip-tag">VIP 會員卡</span>
          <button className="x-btn" onClick={onClose}>✕</button>
        </div>
        <div className="vip-body">
          <div className="vip-avatar">
            <image-slot id="avatar-photo" shape="circle" readonly="" placeholder="大頭照即將登場"
                        style={{ width: '140px', height: '140px' }}></image-slot>
          </div>
          <div className="vip-info">
            <div className="vip-name">{PROFILE.name}</div>
            <div className="vip-nick">{PROFILE.nickname}</div>
            <div className="vip-mbti">{PROFILE.mbti}</div>
            <div className="vip-tagline">「{PROFILE.tagline}」</div>
          </div>
        </div>
        <div className="vip-facts">
          {PROFILE.facts.map((f, i) => (
            <div className="vip-fact" key={i}>
              <span className="vf-label">{f.label}</span>
              <span className="vf-value">{f.value}</span>
            </div>
          ))}
        </div>
        <div className="vip-foot">★ LUCKY MEMBER · NO.000777 ★</div>
      </div>
    </div>
  );
}

// ---------- 轉場 ----------
function Transition({ topic }) {
  return (
    <div className="transition">
      <div className="trans-burst" style={{ background: `radial-gradient(circle, ${topic.color}55 0%, transparent 60%)` }}></div>
      <div className="trans-symbol" style={{ color: topic.color, textShadow: `0 0 40px ${topic.color}` }}>{topic.symbol}</div>
      <div className="trans-name" style={{ textShadow: `0 0 30px ${topic.color}` }}>{topic.name}</div>
      <div className="trans-jackpot">★ JACKPOT ★</div>
    </div>
  );
}

// ---------- 橫向相簿 ----------
function Gallery({ topic, onClose }) {
  const scrollRef = useRef(null);
  const drag = useRef(null);
  const [lightbox, setLightbox] = useState(null); // { url, label, caption }

  const onPointerDown = (e) => {
    drag.current = { x: e.clientX, left: scrollRef.current.scrollLeft, moved: false };
  };
  const onPointerMove = (e) => {
    if (!drag.current) return;
    const dx = e.clientX - drag.current.x;
    if (Math.abs(dx) > 5) drag.current.moved = true;
    scrollRef.current.scrollLeft = drag.current.left - dx;
  };
  const onPointerUp = () => { setTimeout(() => { drag.current = null; }, 0); };
  const onWheel = (e) => {
    if (Math.abs(e.deltaY) > Math.abs(e.deltaX)) scrollRef.current.scrollLeft += e.deltaY;
  };

  // 燈箱開啟時:Esc 先關燈箱(capture 階段攔下,不讓 App 把整個相簿關掉)
  useEffect(() => {
    if (!lightbox) return;
    const onEsc = (e) => {
      if (e.key !== 'Escape') return;
      e.stopPropagation();
      setLightbox(null);
    };
    window.addEventListener('keydown', onEsc, true);
    return () => window.removeEventListener('keydown', onEsc, true);
  }, [lightbox]);

  const openPhoto = (e, p) => {
    if (drag.current && drag.current.moved) return; // 拖曳結束不要誤觸
    const slot = e.currentTarget.querySelector('image-slot');
    const url = slot && slot.imageUrl;
    if (!url) return; // 空格子(待補圖)不放大
    window.CasinoSound.whoosh();
    setLightbox({ url, label: p.label, caption: p.caption });
  };

  return (
    <div className="gallery" data-screen-label={'相簿:' + topic.name}>
      <div className="gal-head">
        <div className="gal-title">
          <span className="gal-symbol" style={{ color: topic.color, textShadow: `0 0 24px ${topic.color}` }}>{topic.symbol}</span>
          <span className="gal-name">{topic.name}</span>
        </div>
        <div className="gal-intro">{topic.intro}</div>
        <button className="back-btn" onClick={onClose}>← 回到賭場</button>
      </div>
      <div className="gal-strip" ref={scrollRef}
           onPointerDown={onPointerDown} onPointerMove={onPointerMove}
           onPointerUp={onPointerUp} onPointerLeave={onPointerUp} onWheel={onWheel}>
        <div className="gal-row">
          {topic.photos.map((p, i) => (
            <figure className="photo-card" key={i}
                    style={{ transform: `rotate(${(i % 2 === 0 ? -1 : 1) * (0.6 + (i % 3) * 0.4)}deg)` }}
                    onClick={(e) => openPhoto(e, p)}>
              <image-slot id={`slot-${topic.id}-${i}`} shape="rect" readonly=""
                          placeholder={p.label + '(照片即將登場)'}
                          style={{ width: '560px', height: '420px' }}></image-slot>
              <figcaption>
                <span className="pc-label">{p.label}</span>
                {p.caption && <span className="pc-caption">{p.caption}</span>}
              </figcaption>
            </figure>
          ))}
          <div className="gal-end">
            <div className="gal-end-symbol" style={{ color: topic.color }}>{topic.symbol}</div>
            <div>本回合結束</div>
            <button className="back-btn" onClick={onClose}>← 回到賭場再拉一次</button>
          </div>
        </div>
      </div>
      <div className="gal-hint">⟵ 按住拖曳 或 滾輪滑動 ⟶ · 點照片放大 · Esc 返回</div>

      {lightbox && (
        <div className="lightbox" onClick={() => setLightbox(null)}>
          <figure className="lightbox-figure" onClick={(e) => e.stopPropagation()}>
            <img className="lightbox-img" src={lightbox.url} alt={lightbox.label} />
            <figcaption>
              <span className="pc-label">{lightbox.label}</span>
              {lightbox.caption && <span className="pc-caption">{lightbox.caption}</span>}
            </figcaption>
          </figure>
          <button className="lightbox-x" onClick={() => setLightbox(null)}>✕</button>
        </div>
      )}
    </div>
  );
}

// ---------- 全部完成 ----------
function Finale({ onClose, onReset }) {
  return (
    <div className="overlay" onClick={onClose}>
      <div className="finale" onClick={(e) => e.stopPropagation()}>
        <div className="finale-stars">★ ★ ★</div>
        <div className="finale-title">JACKPOT!</div>
        <div className="finale-sub">六個主題全部分享完畢</div>
        <div className="finale-thanks">謝謝聆聽,歡迎提問!</div>
        <div className="finale-actions">
          <button className="enter-btn show" onClick={onReset}>↺ 重新開始</button>
          <button className="back-btn" onClick={onClose}>繼續留在賭場</button>
        </div>
      </div>
    </div>
  );
}

ReactDOM.createRoot(document.getElementById('ui')).render(<App />);
