// ============================================================
// game_hub.jsx  —  마음의 정원 허브 메인 페이지
// 치유 · 자연 · 따뜻한 수채화 컨셉
// ============================================================
const { useState, useEffect, useRef, useCallback } = React;

// ── 팔레트 ──────────────────────────────────────────────────
const C = {
  sage:    '#4A7C59',
  sageL:   '#7BA88A',
  sagePale:'#EAF2EC',
  cream:   '#FDFCF7',
  sand:    '#F5EFE0',
  dusty:   '#6B8FA8',
  dustyL:  '#A8C4D4',
  amber:   '#D4954A',
  amberL:  '#E8C47A',
  muted:   '#8A8A78',
  dark:    '#2C2C20',
  fogGray: '#9BA8B0',
};

// ── 공통 스타일 헬퍼 ────────────────────────────────────────
const btn = (extra='') => ({
  fontFamily: "'Noto Sans KR', sans-serif",
  cursor: 'pointer', border: 'none', outline: 'none', ...{}
});

// ──────────────────────────────────────────────────────────
// GardenSVG — 정원 상태별 SVG 일러스트
// ──────────────────────────────────────────────────────────
function GardenSVG({ status = 'clearing', level = 1, style = {} }) {
  const theme = {
    foggy: {
      skyTop:'#7A8E9A', skyBot:'#B0BFC8',
      ground:'#6A7A6A', groundDark:'#4A5A4A',
      treeTrunk:'#5A4A3A', treeLeaf:'#556655',
      fogOpacity: 0.55, flowersVisible: false,
      sunVisible: false, birdsVisible: false,
    },
    clearing: {
      skyTop:'#5A8AC0', skyBot:'#A0C8E0',
      ground:'#5A8A4A', groundDark:'#3E6A32',
      treeTrunk:'#6B4F3A', treeLeaf:'#4A8A3A',
      fogOpacity: 0.2, flowersVisible: true,
      sunVisible: true, birdsVisible: false,
    },
    blooming: {
      skyTop:'#3A7AC0', skyBot:'#80C0E0',
      ground:'#4A8A3A', groundDark:'#2E6A22',
      treeTrunk:'#7B5F4A', treeLeaf:'#3A9A2A',
      fogOpacity: 0, flowersVisible: true,
      sunVisible: true, birdsVisible: true,
    },
  }[status] || {};

  const leafCount = Math.min(1 + Math.floor(level * 0.8), 6);

  return (
    <svg viewBox="0 0 320 200" xmlns="http://www.w3.org/2000/svg" style={{ width:'100%', height:'100%', ...style }}>
      {/* 하늘 그라데이션 */}
      <defs>
        <linearGradient id="skyGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={theme.skyTop}/>
          <stop offset="100%" stopColor={theme.skyBot}/>
        </linearGradient>
        <linearGradient id="groundGrad" x1="0" y1="0" x2="0" y2="1">
          <stop offset="0%" stopColor={theme.ground}/>
          <stop offset="100%" stopColor={theme.groundDark}/>
        </linearGradient>
        <filter id="softBlur"><feGaussianBlur stdDeviation="2"/></filter>
        <filter id="fogBlur"><feGaussianBlur stdDeviation="4"/></filter>
      </defs>

      {/* 하늘 배경 */}
      <rect width="320" height="200" fill="url(#skyGrad)"/>

      {/* 태양 */}
      {theme.sunVisible && (
        <g>
          <circle cx="260" cy="38" r="22" fill={C.amberL} opacity="0.9"/>
          <circle cx="260" cy="38" r="17" fill="#FFE08A"/>
          {[0,45,90,135,180,225,270,315].map(a=>(
            <line key={a} x1={260+Math.cos(a*Math.PI/180)*20} y1={38+Math.sin(a*Math.PI/180)*20}
              x2={260+Math.cos(a*Math.PI/180)*27} y2={38+Math.sin(a*Math.PI/180)*27}
              stroke="#FFE08A" strokeWidth="2" strokeLinecap="round"/>
          ))}
        </g>
      )}

      {/* 구름 */}
      {status !== 'foggy' && (
        <g opacity="0.85">
          <ellipse cx="80" cy="55" rx="28" ry="14" fill="white" opacity="0.9"/>
          <ellipse cx="95" cy="48" rx="18" ry="12" fill="white" opacity="0.9"/>
          <ellipse cx="65" cy="52" rx="16" ry="10" fill="white" opacity="0.9"/>
          <ellipse cx="195" cy="40" rx="22" ry="11" fill="white" opacity="0.75"/>
          <ellipse cx="208" cy="34" rx="14" ry="9" fill="white" opacity="0.75"/>
        </g>
      )}

      {/* 새 */}
      {theme.birdsVisible && (
        <g fill="none" stroke={C.dusty} strokeWidth="1.5" strokeLinecap="round">
          <path d="M 150 50 Q 154 46 158 50"/>
          <path d="M 162 44 Q 166 40 170 44"/>
          <path d="M 130 62 Q 133 58 136 62"/>
        </g>
      )}

      {/* 지면 */}
      <ellipse cx="160" cy="185" rx="190" ry="30" fill="url(#groundGrad)"/>
      <rect x="0" y="172" width="320" height="28" fill={theme.groundDark}/>

      {/* 풀 */}
      {status !== 'foggy' && (
        <g fill={theme.ground} opacity="0.8">
          {[30,55,90,130,190,230,265,290].map((x,i)=>(
            <g key={x}>
              <line x1={x} y1="172" x2={x-4} y2={162-i%3*4} stroke={theme.treeLeaf} strokeWidth="2" strokeLinecap="round"/>
              <line x1={x} y1="172" x2={x+3} y2={163-i%2*5} stroke={theme.treeLeaf} strokeWidth="2" strokeLinecap="round"/>
            </g>
          ))}
        </g>
      )}

      {/* 나무 몸통 */}
      <rect x="152" y="110" width="16" height="62" rx="5" fill={theme.treeTrunk}/>
      <rect x="155" y="128" width="10" height="44" rx="3" fill={theme.treeTrunk} opacity="0.6"/>

      {/* 나무 잎 (레벨에 따라 점점 풍성) */}
      {leafCount >= 1 && <ellipse cx="160" cy="105" rx="30" ry="26" fill={theme.treeLeaf} opacity="0.95"/>}
      {leafCount >= 2 && <ellipse cx="142" cy="115" rx="22" ry="18" fill={theme.treeLeaf} opacity="0.9"/>}
      {leafCount >= 3 && <ellipse cx="178" cy="113" rx="22" ry="19" fill={theme.treeLeaf} opacity="0.9"/>}
      {leafCount >= 4 && <ellipse cx="160" cy="88" rx="22" ry="18" fill={theme.treeLeaf} opacity="0.85"/>}
      {leafCount >= 5 && <ellipse cx="145" cy="97" rx="16" ry="14" fill={theme.treeLeaf} opacity="0.8"/>}
      {leafCount >= 6 && <ellipse cx="175" cy="96" rx="16" ry="13" fill={theme.treeLeaf} opacity="0.8"/>}

      {/* 꽃 */}
      {theme.flowersVisible && (
        <g>
          {[{x:60,c:'#F9A8D4'},{x:100,c:'#FCD34D'},{x:200,c:'#86EFAC'},{x:240,c:'#F9A8D4'},{x:280,c:'#FCD34D'}].map(({x,c},i)=>(
            level >= i ? (
              <g key={x}>
                <circle cx={x} cy="170" r="5" fill={c} opacity="0.95"/>
                <circle cx={x-5} cy="167" r="3.5" fill={c} opacity="0.8"/>
                <circle cx={x+5} cy="167" r="3.5" fill={c} opacity="0.8"/>
                <circle cx={x} cy="163" r="3.5" fill={c} opacity="0.8"/>
                <circle cx={x} cy="170" r="3" fill="#FFF" opacity="0.7"/>
              </g>
            ) : null
          ))}
        </g>
      )}

      {/* 안개 오버레이 */}
      {theme.fogOpacity > 0 && (
        <g>
          <rect width="320" height="200" fill={C.fogGray} opacity={theme.fogOpacity} filter="url(#fogBlur)"/>
          <ellipse cx="80" cy="170" rx="120" ry="40" fill={C.fogGray} opacity={theme.fogOpacity * 0.8} filter="url(#fogBlur)"/>
          <ellipse cx="240" cy="165" rx="100" ry="35" fill={C.fogGray} opacity={theme.fogOpacity * 0.7} filter="url(#fogBlur)"/>
        </g>
      )}
    </svg>
  );
}

// ──────────────────────────────────────────────────────────
// LevelBar — 경험치 바
// ──────────────────────────────────────────────────────────
function LevelBar({ levelInfo }) {
  const { level, name, emoji, progress, currentExp, maxExp } = levelInfo || {};
  return (
    <div style={{ padding:'16px 20px', background:'rgba(255,255,255,0.7)', borderRadius:16, backdropFilter:'blur(8px)' }}>
      <div style={{ display:'flex', alignItems:'center', justifyContent:'space-between', marginBottom:10 }}>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <span style={{ fontSize:22 }}>{emoji}</span>
          <div>
            <div style={{ fontSize:15, fontWeight:700, color:C.dark }}>Lv.{level} {name}</div>
            <div style={{ fontSize:11, color:C.muted }}>다음 레벨까지 {maxExp - currentExp} EXP</div>
          </div>
        </div>
        <div style={{ fontSize:13, fontWeight:600, color:C.sage }}>{currentExp} EXP</div>
      </div>
      <div style={{ height:10, background:'rgba(0,0,0,0.08)', borderRadius:100, overflow:'hidden' }}>
        <div style={{
          height:'100%', width:`${progress}%`,
          background:`linear-gradient(90deg, ${C.sage}, ${C.sageL})`,
          borderRadius:100, transition:'width 1s ease',
          boxShadow:`0 0 8px ${C.sage}60`,
        }}/>
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// TestBadge — 연결된 검사 표시
// ──────────────────────────────────────────────────────────
const TEST_META_HUB = {
  PHQ9:    { label:'PHQ-9',   emoji:'🌱', desc:'우울 선별' },
  GAD7:    { label:'GAD-7',   emoji:'💙', desc:'불안 선별' },
  DASS21:  { label:'DASS-21', emoji:'🌊', desc:'스트레스' },
  BIG5:    { label:'Big5',    emoji:'🧠', desc:'성격 분석' },
  SCT:     { label:'SCT',     emoji:'✍️', desc:'문장 완성' },
  DSI:     { label:'DSI',     emoji:'🪞', desc:'자아 분화' },
  BURNOUT: { label:'K-MBI+',  emoji:'🔥', desc:'번아웃' },
  LOST:    { label:'LOST',    emoji:'🧭', desc:'행동 양식' },
};

function TestBadgeRow({ completedTests = [] }) {
  const allTests = Object.keys(TEST_META_HUB);
  return (
    <div>
      <div style={{ fontSize:12, fontWeight:600, color:C.muted, marginBottom:10, letterSpacing:'0.5px' }}>연결된 심리검사</div>
      <div style={{ display:'flex', flexWrap:'wrap', gap:7 }}>
        {allTests.map(t => {
          const meta = TEST_META_HUB[t];
          const done = completedTests.includes(t);
          return (
            <div key={t} style={{
              display:'flex', alignItems:'center', gap:5,
              padding:'5px 10px', borderRadius:100,
              background: done ? C.sagePale : 'rgba(0,0,0,0.05)',
              border: `1px solid ${done ? C.sage+'44' : 'transparent'}`,
              opacity: done ? 1 : 0.5,
            }}>
              <span style={{ fontSize:13 }}>{meta.emoji}</span>
              <span style={{ fontSize:11, fontWeight: done ? 600 : 400, color: done ? C.sage : C.muted }}>
                {meta.label}
              </span>
              {done && <span style={{ fontSize:10, color:C.sage }}>✓</span>}
            </div>
          );
        })}
      </div>
      {completedTests.length === 0 && (
        <div style={{ marginTop:10, fontSize:12, color:C.muted, lineHeight:1.6 }}>
          심리검사를 완료하면 게임이 더 풍성해져요.{' '}
          <a href={PHYWEB_URL} style={{ color:C.sage, fontWeight:600, textDecoration:'none' }}>
            마음풀에서 검사하기 →
          </a>
        </div>
      )}
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// GameCard — 개별 게임 카드
// ──────────────────────────────────────────────────────────
function GameCard({ game, onPlay }) {
  const [hovered, setHovered] = useState(false);
  const locked = !game.canPlay;
  const comingSoon = !game.isAvailable;

  const cardBg = locked
    ? 'rgba(255,255,255,0.5)'
    : hovered
      ? 'rgba(255,255,255,0.95)'
      : 'rgba(255,255,255,0.8)';

  return (
    <div
      onClick={() => !locked && onPlay(game.id)}
      onMouseEnter={() => setHovered(true)}
      onMouseLeave={() => setHovered(false)}
      style={{
        background: cardBg,
        borderRadius: 20,
        padding: '24px 20px 20px',
        cursor: locked ? 'not-allowed' : 'pointer',
        transition: 'all 0.25s ease',
        transform: !locked && hovered ? 'translateY(-4px)' : 'none',
        boxShadow: !locked && hovered ? `0 12px 32px ${C.sage}22` : '0 2px 12px rgba(0,0,0,0.06)',
        border: `1px solid ${!locked && hovered ? C.sage+'44' : 'rgba(255,255,255,0.6)'}`,
        backdropFilter: 'blur(8px)',
        position: 'relative',
        overflow: 'hidden',
        opacity: comingSoon ? 0.7 : 1,
      }}
    >
      {/* 준비 중 배지 */}
      {comingSoon && (
        <div style={{
          position:'absolute', top:12, right:12,
          background:'rgba(0,0,0,0.08)', color:C.muted,
          fontSize:10, fontWeight:700, padding:'3px 9px', borderRadius:100,
          letterSpacing:'0.5px',
        }}>준비 중</div>
      )}

      {/* 레벨 잠금 표시 */}
      {!comingSoon && !game.isUnlocked && (
        <div style={{
          position:'absolute', top:12, right:12,
          background:C.sand, color:C.amber,
          fontSize:10, fontWeight:700, padding:'3px 9px', borderRadius:100,
        }}>Lv.{game.unlockLevel} 해금</div>
      )}

      {/* 이모지 */}
      <div style={{
        fontSize:42, marginBottom:12, lineHeight:1,
        filter: locked ? 'grayscale(0.5)' : 'none',
        animation: !locked && hovered ? 'float 2s ease-in-out infinite' : 'none',
      }}>
        {game.emoji}
      </div>

      {/* 이름 */}
      <div style={{ fontSize:16, fontWeight:700, color:C.dark, marginBottom:4 }}>
        {game.name}
      </div>
      <div style={{ fontSize:12, color:C.muted, marginBottom:12, lineHeight:1.5 }}>
        {game.tagline}
      </div>

      {/* 태그 */}
      <div style={{ display:'flex', flexWrap:'wrap', gap:5, marginBottom:14 }}>
        {game.tags.slice(0,3).map(tag => (
          <span key={tag} style={{
            fontSize:10, padding:'2px 8px', borderRadius:100,
            background:C.sagePale, color:C.sage, fontWeight:500,
          }}>{tag}</span>
        ))}
      </div>

      {/* 크레딧 비용 */}
      <div style={{ fontSize:11, fontWeight:600, marginBottom:4,
        color: game.creditCost > 0 ? '#D4954A' : '#4A7C59' }}>
        {game.creditCost > 0 ? `🌿 ${game.creditCost} 크레딧` : '무료'}
      </div>

      {/* 필요 검사 */}
      {game.requiredTests.length > 0 && (
        <div style={{ fontSize:11, color:C.dusty, marginBottom:12 }}>
          {game.requiredTests.map(t => TEST_META_HUB[t]?.label || t).join(' · ')} 연동
        </div>
      )}

      {/* 모듈 미리보기 */}
      {game.modules?.length > 0 && !comingSoon && (
        <div style={{ display:'flex', flexDirection:'column', gap:5, marginBottom:14 }}>
          {game.modules.map(m => (
            <div key={m.id} style={{ display:'flex', alignItems:'center', gap:7, fontSize:12, color:C.muted }}>
              <span style={{ fontSize:14 }}>{m.emoji}</span>
              <span>{m.name}</span>
            </div>
          ))}
        </div>
      )}

      {/* 버튼 */}
      <button
        disabled={locked}
        style={{
          ...btn(), width:'100%', padding:'10px 0',
          borderRadius:12, fontSize:13, fontWeight:700,
          background: locked ? 'rgba(0,0,0,0.07)' : `linear-gradient(135deg, ${C.sage}, ${C.sageL})`,
          color: locked ? C.muted : 'white',
          transition:'all 0.2s',
          boxShadow: !locked ? `0 4px 12px ${C.sage}40` : 'none',
        }}
      >
        {comingSoon ? '곧 출시됩니다' : locked ? '🔒 잠금 해제 필요' : '시작하기 →'}
      </button>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// RecentActivity — 최근 플레이 기록
// ──────────────────────────────────────────────────────────
function RecentActivity({ sessions = [] }) {
  if (sessions.length === 0) return null;

  const MODULE_LABEL = {
    breathing: { emoji:'💧', name:'호흡 훈련' },
    cbt:       { emoji:'🌱', name:'생각 교정' },
    efmt:      { emoji:'🌸', name:'감정 훈련' },
    relax:     { emoji:'🏞️', name:'이완 훈련' },
  };

  return (
    <div style={{ marginTop:32 }}>
      <div style={{ fontSize:14, fontWeight:700, color:C.dark, marginBottom:14, display:'flex', alignItems:'center', gap:6 }}>
        <span style={{ fontSize:16 }}>📜</span> 최근 플레이 기록
      </div>
      <div style={{ display:'flex', flexDirection:'column', gap:8 }}>
        {sessions.map((s, i) => {
          const m = MODULE_LABEL[s.module_type] || { emoji:'🎮', name:s.module_type };
          return (
            <div key={i} style={{
              display:'flex', alignItems:'center', gap:12,
              padding:'12px 16px', borderRadius:12,
              background:'rgba(255,255,255,0.6)', backdropFilter:'blur(6px)',
              border:'1px solid rgba(255,255,255,0.5)',
            }}>
              <span style={{ fontSize:20 }}>{m.emoji}</span>
              <div style={{ flex:1, minWidth:0 }}>
                <div style={{ fontSize:13, fontWeight:600, color:C.dark }}>{m.name}</div>
                <div style={{ fontSize:11, color:C.muted }}>{GameEngine.formatRelativeTime(s.created_at)}</div>
              </div>
              <div style={{ textAlign:'right' }}>
                <div style={{ fontSize:13, fontWeight:600, color:C.sage }}>+{s.exp_gained} EXP</div>
                <div style={{ fontSize:11, color:C.muted }}>점수 {s.score}</div>
              </div>
            </div>
          );
        })}
      </div>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// LoginGate — 미로그인 상태 안내
// ──────────────────────────────────────────────────────────
function LoginGate() {
  return (
    <div style={{
      minHeight:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:`linear-gradient(160deg, ${C.sagePale}, ${C.cream}, #EBF4FA)`,
      padding:24, textAlign:'center',
    }}>
      <div style={{ fontSize:72, marginBottom:20, animation:'float 3s ease-in-out infinite' }}>🌿</div>
      <h1 style={{ fontSize:28, fontWeight:700, color:C.dark, marginBottom:10, fontFamily:"'Noto Serif KR', serif" }}>
        마음의 정원
      </h1>
      <p style={{ fontSize:15, color:C.muted, lineHeight:1.8, marginBottom:32, maxWidth:300 }}>
        마음풀에서 로그인하면<br/>
        별도 로그인 없이 바로 이용할 수 있어요.<br/>
        심리검사 결과와 연결하여<br/>
        나만의 정원을 가꾸세요 🌿
      </p>
      <a href={PHYWEB_URL} style={{
        display:'inline-block', padding:'14px 36px',
        background:`linear-gradient(135deg, ${C.sage}, ${C.sageL})`,
        color:'white', borderRadius:14, fontWeight:700,
        fontSize:15, textDecoration:'none',
        boxShadow:`0 8px 24px ${C.sage}44`,
        fontFamily:"'Noto Sans KR', sans-serif",
      }}>
        마음풀 로그인하고 시작하기 →
      </a>
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// AchievementToast — 업적 달성 알림
// ──────────────────────────────────────────────────────────
function AchievementToast({ achievements = [], onDismiss }) {
  const [visible, setVisible] = useState(true);

  useEffect(() => {
    const timer = setTimeout(() => { setVisible(false); onDismiss?.(); }, 4000);
    return () => clearTimeout(timer);
  }, []);

  if (!visible || achievements.length === 0) return null;

  return (
    <div style={{
      position:'fixed', bottom:24, right:24, zIndex:1000,
      display:'flex', flexDirection:'column', gap:8,
      animation:'fadeUp 0.4s ease',
    }}>
      {achievements.map(id => {
        const a = GameEngine.getAchievementInfo(id);
        return (
          <div key={id} style={{
            display:'flex', alignItems:'center', gap:10,
            background:'white', borderRadius:14, padding:'12px 16px',
            boxShadow:'0 8px 24px rgba(0,0,0,0.12)',
            border:`1px solid ${C.sage}33`,
          }}>
            <span style={{ fontSize:24 }}>{a.emoji}</span>
            <div>
              <div style={{ fontSize:13, fontWeight:700, color:C.dark }}>업적 달성!</div>
              <div style={{ fontSize:12, color:C.sage, fontWeight:600 }}>{a.name}</div>
            </div>
          </div>
        );
      })}
    </div>
  );
}

// ──────────────────────────────────────────────────────────
// GameHubApp — 메인 앱
// ──────────────────────────────────────────────────────────
function GameHubApp() {
  const [loading, setLoading] = useState(true);
  const [data, setData]       = useState(null);
  const [error, setError]     = useState('');
  const [newAchievements, setNewAchievements] = useState([]);
  const [activeGame, setActiveGame] = useState(null);
  const [creditModal, setCreditModal] = useState(null); // { gameId, cost, balance }
  const [spendLoading, setSpendLoading] = useState(false); // 게임 진행 시 사용

  const isLoggedIn = !!localStorage.getItem('game_token');

  useEffect(() => {
    if (!isLoggedIn) { setLoading(false); return; }
    GameEngine.getMe()
      .then(res => {
        if (res.success) setData(res.data);
        else setError(res.error || '데이터 조회 실패');
      })
      .catch(() => setError('서버 연결 실패'))
      .finally(() => setLoading(false));
  }, []);

  const handlePlay = useCallback(async (gameId) => {
    const game = getGameById(gameId);
    if (!game) return;

    // 무료 게임은 바로 시작
    if (!game.creditCost || game.creditCost <= 0) {
      setActiveGame(gameId);
      return;
    }

    // 유료 게임: 실시간 잔액 확인 후 모달 표시
    try {
      const res = await GameEngine.getCredits();
      const balance = res.success ? res.data.balance : (data?.user?.credits || 0);
      setCreditModal({ gameId, cost: game.creditCost, balance, gameName: game.name, gameEmoji: game.emoji });
    } catch {
      // 네트워크 오류 시 캐시 잔액 사용
      const balance = data?.user?.credits || 0;
      setCreditModal({ gameId, cost: game.creditCost, balance, gameName: game.name, gameEmoji: game.emoji });
    }
  }, [data]);

  const handleGameExit = useCallback((result) => {
    setActiveGame(null);
    setCreditModal(null);
    // 허브 데이터 새로고침 (경험치 + 크레딧 잔액 반영)
    GameEngine.getMe().then(res => {
      if (res.success) setData(res.data);
      if (result?.newAchievements?.length) setNewAchievements(result.newAchievements);
    });
  }, []);

  // 크레딧 차감 확인 후 게임 시작
  const handleCreditConfirm = useCallback(async () => {
    if (!creditModal) return;
    const { gameId, cost, balance } = creditModal;
    if (balance < cost) return; // 잔액 부족 — 버튼이 비활성이므로 여기 안 옴

    setSpendLoading(true);
    try {
      const res = await GameEngine.spendCredit(gameId, cost);
      if (res.success) {
        // 잔액 즉시 반영
        setData(prev => prev ? { ...prev, user: { ...prev.user, credits: res.data.balance } } : prev);
        setCreditModal(null);
        setActiveGame(gameId);
      } else if (res.errorCode === 'insufficient_credits') {
        setCreditModal(prev => ({ ...prev, balance: res.balance, insufficient: true }));
      } else {
        alert(res.error || '크레딧 차감 실패. 다시 시도해주세요.');
      }
    } catch {
      alert('네트워크 오류. 다시 시도해주세요.');
    }
    setSpendLoading(false);
  }, [creditModal]);

  if (!isLoggedIn) return <LoginGate />;

  if (loading) return (
    <div style={{
      minHeight:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:`linear-gradient(160deg, ${C.sagePale}, ${C.cream})`,
    }}>
      <div style={{ fontSize:56, marginBottom:16, animation:'float 2s ease-in-out infinite' }}>🌿</div>
      <div style={{ fontSize:14, color:C.muted, animation:'pulse 1.5s infinite' }}>정원을 불러오는 중...</div>
    </div>
  );

  // 게임 실행 중
  if (activeGame === 'garden') return (
    <div style={{ display:'flex', flexDirection:'column', height:'100vh', overflow:'hidden' }}>
      <GardenGame onExit={handleGameExit}/>
    </div>
  );

  if (activeGame === 'efmt') return (
    <div style={{ display:'flex', flexDirection:'column', height:'100vh', overflow:'hidden' }}>
      <EFMTGame onExit={handleGameExit}/>
    </div>
  );

  if (activeGame === 'gratitude') return (
    <div style={{ display:'flex', flexDirection:'column', height:'100vh', overflow:'hidden' }}>
      <GratitudeGame onExit={handleGameExit}/>
    </div>
  );

  if (activeGame === 'tree') return (
    <div style={{ display:'flex', flexDirection:'column', height:'100vh', overflow:'hidden' }}>
      <TreeGame onExit={handleGameExit}/>
    </div>
  );

  if (error) return (
    <div style={{
      minHeight:'100vh', display:'flex', flexDirection:'column',
      alignItems:'center', justifyContent:'center',
      background:C.cream, padding:24, textAlign:'center',
    }}>
      <div style={{ fontSize:40, marginBottom:12 }}>🌧️</div>
      <div style={{ fontSize:15, color:C.muted, marginBottom:20 }}>{error}</div>
      <a href={PHYWEB_URL} style={{
        padding:'10px 24px', background:C.sage, color:'white',
        borderRadius:10, fontSize:14, fontWeight:600,
        textDecoration:'none', fontFamily:"'Noto Sans KR', sans-serif",
      }}>마음풀으로 돌아가기</a>
    </div>
  );

  const { user, gameStatus, recentSessions, completedTests, achievements } = data || {};
  const levelInfo    = GameEngine.getLevelInfo(gameStatus?.total_exp || 0);
  const gardenTheme  = GameEngine.getGardenTheme(gameStatus?.visual_status || 'clearing');
  const games        = getPlayableGames(completedTests, gameStatus?.garden_level || 1);

  return (
    <div style={{ minHeight:'100vh', background:`linear-gradient(160deg, ${C.sagePale} 0%, ${C.cream} 40%, #EBF4FA 100%)` }}>

      {/* ── 네비게이션 ── */}
      <nav style={{
        position:'sticky', top:0, zIndex:100,
        background:'rgba(253,252,247,0.88)', backdropFilter:'blur(16px)',
        borderBottom:'1px solid rgba(74,124,89,0.12)',
        padding:'0 20px', height:56,
        display:'flex', alignItems:'center', justifyContent:'space-between',
      }}>
        <div style={{ display:'flex', alignItems:'center', gap:8 }}>
          <span style={{ fontSize:20 }}>🌿</span>
          <span style={{ fontSize:16, fontWeight:700, color:C.dark, fontFamily:"'Noto Serif KR', serif" }}>
            마음의 정원
          </span>
        </div>
        <div style={{ display:'flex', alignItems:'center', gap:10 }}>
          <div style={{
            fontSize:12, fontWeight:600, color:C.sage,
            background:C.sagePale, padding:'4px 12px', borderRadius:100,
          }}>
            Lv.{levelInfo.level} {levelInfo.emoji}
          </div>
          <a href={PHYWEB_URL} style={{
            fontSize:12, color:C.muted, textDecoration:'none',
            padding:'5px 12px', borderRadius:8,
            border:`1px solid rgba(0,0,0,0.08)`,
            background:'rgba(255,255,255,0.6)',
          }}>← 마음풀</a>
        </div>
      </nav>

      <div style={{ maxWidth:680, margin:'0 auto', padding:'24px 20px 40px' }}>

        {/* ── 정원 히어로 섹션 ── */}
        <div style={{
          borderRadius:24, overflow:'hidden',
          boxShadow:'0 8px 32px rgba(0,0,0,0.08)',
          marginBottom:24, background:'white',
        }}>
          {/* 정원 SVG */}
          <div style={{ height:200, position:'relative' }}>
            <GardenSVG status={gameStatus?.visual_status || 'clearing'} level={levelInfo.level}/>
            {/* 정원 상태 라벨 */}
            <div style={{
              position:'absolute', bottom:12, left:16,
              background:'rgba(255,255,255,0.85)', backdropFilter:'blur(8px)',
              padding:'6px 14px', borderRadius:100,
              fontSize:12, fontWeight:600, color:C.dark,
              boxShadow:'0 2px 8px rgba(0,0,0,0.08)',
            }}>
              {gardenTheme.label}
            </div>
            {/* 연속 출석 */}
            {(gameStatus?.streak_days || 0) > 1 && (
              <div style={{
                position:'absolute', top:12, right:12,
                background:'rgba(255,255,255,0.9)', backdropFilter:'blur(8px)',
                padding:'5px 12px', borderRadius:100,
                fontSize:11, fontWeight:700, color:C.amber,
                display:'flex', alignItems:'center', gap:5,
              }}>
                🔥 {gameStatus.streak_days}일 연속
              </div>
            )}
          </div>

          {/* 인사 + 레벨바 */}
          <div style={{ padding:'16px 20px 20px' }}>
            <div style={{ marginBottom:12 }}>
              <div style={{ fontSize:18, fontWeight:700, color:C.dark, marginBottom:4 }}>
                안녕하세요, {user?.nickname || user?.email?.split('@')[0]}님 👋
              </div>
              <div style={{ fontSize:13, color:C.muted }}>{gardenTheme.desc}</div>
            </div>
            <LevelBar levelInfo={levelInfo} />
          </div>
        </div>

        {/* ── 연결된 검사 ── */}
        <div style={{
          background:'rgba(255,255,255,0.7)', backdropFilter:'blur(8px)',
          borderRadius:20, padding:'18px 20px', marginBottom:24,
          border:'1px solid rgba(255,255,255,0.6)',
        }}>
          <TestBadgeRow completedTests={completedTests || []} />
        </div>

        {/* ── 게임 목록 ── */}
        <div style={{ marginBottom:24 }}>
          <div style={{ fontSize:15, fontWeight:700, color:C.dark, marginBottom:16, display:'flex', alignItems:'center', gap:6 }}>
            <span style={{ fontSize:18 }}>🎮</span> 치유 게임
          </div>
          <div style={{ display:'grid', gridTemplateColumns:'repeat(2, 1fr)', gap:14 }} className="game-grid">
            {games.map(game => (
              <GameCard key={game.id} game={game} onPlay={handlePlay} />
            ))}
          </div>
        </div>

        {/* ── 업적 ── */}
        {achievements?.length > 0 && (
          <div style={{
            background:'rgba(255,255,255,0.7)', backdropFilter:'blur(8px)',
            borderRadius:20, padding:'18px 20px', marginBottom:24,
            border:'1px solid rgba(255,255,255,0.6)',
          }}>
            <div style={{ fontSize:13, fontWeight:700, color:C.dark, marginBottom:12, display:'flex', alignItems:'center', gap:6 }}>
              <span>🏅</span> 획득한 업적
            </div>
            <div style={{ display:'flex', flexWrap:'wrap', gap:8 }}>
              {achievements.map(({ achievement_id }) => {
                const a = GameEngine.getAchievementInfo(achievement_id);
                return (
                  <div key={achievement_id} style={{
                    display:'flex', alignItems:'center', gap:6,
                    padding:'5px 12px', borderRadius:100,
                    background:C.sagePale, border:`1px solid ${C.sage}33`,
                  }}>
                    <span style={{ fontSize:14 }}>{a.emoji}</span>
                    <span style={{ fontSize:11, fontWeight:600, color:C.sage }}>{a.name}</span>
                  </div>
                );
              })}
            </div>
          </div>
        )}

        {/* ── 최근 활동 ── */}
        <RecentActivity sessions={recentSessions || []} />

      </div>

      {/* 크레딧 차감 확인 모달 */}
      {creditModal && (
        <div style={{
          position:'fixed', inset:0, background:'rgba(0,0,0,0.55)',
          display:'flex', alignItems:'center', justifyContent:'center',
          zIndex:1000, padding:20,
        }} onClick={e => { if(e.target===e.currentTarget) setCreditModal(null); }}>
          <div style={{
            background:'white', borderRadius:22, padding:'28px 24px',
            width:'100%', maxWidth:360,
            boxShadow:'0 16px 48px rgba(0,0,0,0.18)',
            animation:'fadeUp 0.3s ease',
          }}>
            <div style={{ textAlign:'center', marginBottom:20 }}>
              <div style={{ fontSize:48, marginBottom:10 }}>{creditModal.gameEmoji}</div>
              <h3 style={{
                fontSize:18, fontWeight:700, color:'#2C2C20', marginBottom:6,
                fontFamily:"'Noto Serif KR', sans-serif",
              }}>{creditModal.gameName}</h3>
              <p style={{ fontSize:13, color:'#8A8A78', lineHeight:1.6 }}>
                이 게임은 플레이 시 크레딧이 차감됩니다
              </p>
            </div>

            {/* 잔액 vs 비용 */}
            <div style={{
              background:'#F5EFE0', borderRadius:14, padding:'14px 16px', marginBottom:18,
            }}>
              <div style={{ display:'flex', justifyContent:'space-between', marginBottom:6, fontSize:13 }}>
                <span style={{ color:'#8A8A78' }}>현재 크레딧</span>
                <span style={{ fontWeight:700, color:'#2C2C20' }}>{creditModal.balance} 크레딧</span>
              </div>
              <div style={{ display:'flex', justifyContent:'space-between', fontSize:13 }}>
                <span style={{ color:'#8A8A78' }}>차감 예정</span>
                <span style={{ fontWeight:700, color:'#D4954A' }}>- {creditModal.cost} 크레딧</span>
              </div>
              <div style={{ height:1, background:'rgba(0,0,0,0.08)', margin:'10px 0' }}/>
              <div style={{ display:'flex', justifyContent:'space-between', fontSize:14 }}>
                <span style={{ fontWeight:700, color:'#2C2C20' }}>차감 후 잔액</span>
                <span style={{
                  fontWeight:700,
                  color: creditModal.balance >= creditModal.cost ? '#4A7C59' : '#C05050',
                }}>
                  {Math.max(0, creditModal.balance - creditModal.cost)} 크레딧
                </span>
              </div>
            </div>

            {/* 잔액 부족 경고 */}
            {(creditModal.insufficient || creditModal.balance < creditModal.cost) && (
              <div style={{
                background:'#FEF2F2', border:'1px solid rgba(192,80,80,0.2)',
                borderRadius:10, padding:'10px 14px', marginBottom:14,
                fontSize:12, color:'#C05050', lineHeight:1.6,
              }}>
                크레딧이 부족해요. 마음풀에서 크레딧을 충전한 후 다시 시도해주세요.
              </div>
            )}

            <div style={{ display:'flex', gap:10 }}>
              <button onClick={() => setCreditModal(null)} style={{
                fontFamily:"'Noto Sans KR',sans-serif",
                flex:1, padding:'12px', background:'rgba(0,0,0,0.07)',
                color:'#8A8A78', border:'none', borderRadius:12, fontSize:13,
                fontWeight:600, cursor:'pointer',
              }}>취소</button>

              {creditModal.balance < creditModal.cost ? (
                <a href={PHYWEB_URL} style={{
                  flex:2, padding:'12px', textAlign:'center',
                  background:`linear-gradient(135deg, #D4954A, #E8C47A)`,
                  color:'white', border:'none', borderRadius:12, fontSize:13,
                  fontWeight:700, cursor:'pointer', textDecoration:'none',
                  display:'flex', alignItems:'center', justifyContent:'center',
                  fontFamily:"'Noto Sans KR',sans-serif",
                }}>크레딧 충전하기 →</a>
              ) : (
                <button
                  onClick={handleCreditConfirm}
                  disabled={spendLoading}
                  style={{
                    fontFamily:"'Noto Sans KR',sans-serif",
                    flex:2, padding:'12px',
                    background: spendLoading
                      ? 'rgba(0,0,0,0.1)'
                      : 'linear-gradient(135deg, #4A7C59, #7BA88A)',
                    color: spendLoading ? '#8A8A78' : 'white',
                    border:'none', borderRadius:12, fontSize:13,
                    fontWeight:700, cursor: spendLoading ? 'not-allowed' : 'pointer',
                  }}>
                  {spendLoading ? '처리 중...' : `${creditModal.cost} 크레딧으로 시작`}
                </button>
              )}
            </div>
          </div>
        </div>
      )}

      {/* 업적 토스트 */}
      {newAchievements.length > 0 && (
        <AchievementToast achievements={newAchievements} onDismiss={() => setNewAchievements([])} />
      )}

      {/* 반응형 CSS */}
      <style>{`
        @media (max-width: 480px) {
          .game-grid { grid-template-columns: 1fr !important; }
        }
      `}</style>
    </div>
  );
}

// ── 앱 마운트 ───────────────────────────────────────────────
const rootEl = document.getElementById('root');
if (rootEl) {
  ReactDOM.createRoot(rootEl).render(React.createElement(GameHubApp));
}
