/**
 * CoinRush Slice 'n Dice V2 - React App
 * Premium dice battle arena matching Coinflip design
 */

const { useState, useEffect, useRef, useCallback, useMemo } = React;

// ============================================
// CONFIGURATION
// ============================================
const CONFIG = {
  minBet: 100, // 1.00 coins in hundredths
  maxBet: 10000000,
  rollDuration: 3000,
  wsReconnectDelay: 3000,
  battleTimeout: 300 // 5 minutes in seconds
};

// ============================================
// SVG ICONS
// ============================================
const Icons = {
  dice: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <rect x="3" y="3" width="18" height="18" rx="2"/>
      <circle cx="8.5" cy="8.5" r="1.5" fill="currentColor"/>
      <circle cx="15.5" cy="8.5" r="1.5" fill="currentColor"/>
      <circle cx="8.5" cy="15.5" r="1.5" fill="currentColor"/>
      <circle cx="15.5" cy="15.5" r="1.5" fill="currentColor"/>
      <circle cx="12" cy="12" r="1.5" fill="currentColor"/>
    </svg>
  ),
  swords: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
      <polyline points="14.5 17.5 3 6 3 3 6 3 17.5 14.5"/>
      <line x1="13" y1="19" x2="19" y2="13"/>
      <line x1="16" y1="16" x2="20" y2="20"/>
      <line x1="19" y1="21" x2="21" y2="19"/>
    </svg>
  ),
  trophy: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M6 9V2h12v7a6 6 0 01-12 0z"/>
      <path d="M6 4H4a2 2 0 000 4h2M18 4h2a2 2 0 010 4h-2"/>
      <path d="M9 22h6M12 15v7"/>
    </svg>
  ),
  clock: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="10"/>
      <polyline points="12 6 12 12 16 14"/>
    </svg>
  ),
  bolt: (
    <svg viewBox="0 0 24 24" fill="currentColor">
      <polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"/>
    </svg>
  ),
  crown: (
    <svg viewBox="0 0 24 24" fill="currentColor">
      <path d="M5 16L3 5l5.5 5L12 4l3.5 6L21 5l-2 11H5zm14 3H5v2h14v-2z"/>
    </svg>
  ),
  close: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <line x1="18" y1="6" x2="6" y2="18"/>
      <line x1="6" y1="6" x2="18" y2="18"/>
    </svg>
  ),
  eye: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/>
      <circle cx="12" cy="12" r="3"/>
    </svg>
  ),
  refresh: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <polyline points="23 4 23 10 17 10"/>
      <path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/>
    </svg>
  ),
  info: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="10"/>
      <line x1="12" y1="16" x2="12" y2="12"/>
      <line x1="12" y1="8" x2="12.01" y2="8"/>
    </svg>
  ),
  gift: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <rect x="3" y="8" width="18" height="4" rx="1"/>
      <rect x="5" y="12" width="14" height="10" rx="1"/>
      <line x1="12" y1="8" x2="12" y2="22"/>
      <path d="M12 8c-2-4-6-4-6 0s4 4 6 0"/>
      <path d="M12 8c2-4 6-4 6 0s-4 4-6 0"/>
    </svg>
  ),
  users: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M17 21v-2a4 4 0 00-4-4H5a4 4 0 00-4 4v2"/>
      <circle cx="9" cy="7" r="4"/>
    </svg>
  ),
  shield: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
      <polyline points="9 12 11 14 15 10"/>
    </svg>
  ),
  check: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <polyline points="20 6 9 17 4 12"/>
    </svg>
  ),
  target: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="10"/>
      <circle cx="12" cy="12" r="6"/>
      <circle cx="12" cy="12" r="2"/>
    </svg>
  ),
  sparkle: (
    <svg viewBox="0 0 24 24" fill="currentColor">
      <path d="M12 0L14.59 9.41L24 12L14.59 14.59L12 24L9.41 14.59L0 12L9.41 9.41L12 0Z"/>
    </svg>
  ),
  hourglass: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <path d="M6.5 7h11M6.5 17h11"/>
      <path d="M6 20v-2a4 4 0 014-4h4a4 4 0 014 4v2H6zM18 4v2a4 4 0 01-4 4h-4a4 4 0 01-4-4V4h16z"/>
    </svg>
  ),
  crossX: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5">
      <circle cx="12" cy="12" r="10" fill="#ef4444" stroke="none"/>
      <line x1="15" y1="9" x2="9" y2="15" stroke="white"/>
      <line x1="9" y1="9" x2="15" y2="15" stroke="white"/>
    </svg>
  ),
  checkCircle: (
    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
      <circle cx="12" cy="12" r="10" fill="#22c55e" stroke="none"/>
      <polyline points="8 12 11 15 16 9" stroke="white" strokeWidth="2.5"/>
    </svg>
  )
};

// ============================================
// UTILITIES
// ============================================
// For Slice 'n Dice, amounts are stored in COINS (not hundredths)
// So we format directly without dividing by 100
const formatCoins = (coins) => {
  const amount = coins || 0;
  return amount.toLocaleString('da-DK', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};

// For user balance (which IS in hundredths)
const formatBalance = (cents) => {
  const coins = (cents || 0) / 100;
  return coins.toLocaleString('da-DK', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
};

const parseCoinsInput = (input) => {
  if (typeof input === 'number') return Math.round(input * 100);
  const normalized = String(input).trim().replace(/\./g, '').replace(',', '.');
  const parsed = parseFloat(normalized);
  if (!isFinite(parsed)) return 0;
  return Math.round(parsed * 100);
};

const timeAgo = (dateStr) => {
  const date = new Date(dateStr);
  const now = new Date();
  const seconds = Math.floor((now - date) / 1000);
  if (seconds < 60) return 'Just now';
  if (seconds < 3600) return `${Math.floor(seconds / 60)}m ago`;
  if (seconds < 86400) return `${Math.floor(seconds / 3600)}h ago`;
  return `${Math.floor(seconds / 86400)}d ago`;
};

const formatTime = (seconds) => {
  const mins = Math.floor(seconds / 60);
  const secs = Math.floor(seconds % 60);
  return `${mins}:${secs.toString().padStart(2, '0')}`;
};

const clsx = (...classes) => classes.filter(Boolean).join(' ');

// API helper
const api = async (endpoint, options = {}) => {
  const res = await fetch(endpoint, {
    method: options.method || 'GET',
    headers: {
      'Content-Type': 'application/json',
      ...options.headers
    },
    credentials: 'include',
    body: options.body ? JSON.stringify(options.body) : undefined
  });
  const data = await res.json();
  if (!res.ok) throw new Error(data.detail || data.error || 'Request failed');
  return data;
};

// ============================================
// AVATAR COMPONENT - With Level Borders (matching Coinflip)
// ============================================
function Avatar({ username, size = 'md', showBorder = true, level = 1, showLevel = false }) {
  const sizeClasses = {
    xs: 'sd-avatar--xs',
    sm: 'sd-avatar--sm',
    md: 'sd-avatar--md',
    lg: 'sd-avatar--lg',
    xl: 'sd-avatar--xl'
  };

  const frameSizes = {
    xs: 44,
    sm: 72,
    md: 86,
    lg: 100,
    xl: 120
  };

  const getBackground = () => {
    if (typeof window.colorFrom === 'function') {
      return window.colorFrom(username || 'X');
    }
    const hue = [...(username || 'X')].reduce((a, c) => a + c.charCodeAt(0), 0) % 360;
    return `linear-gradient(135deg, hsl(${hue} 70% 50%), hsl(${hue} 70% 35%))`;
  };

  const getBorderFrame = () => {
    if (level >= 40) return '/static/img/borders/Challengerborder.png';
    if (level >= 30) return '/static/img/borders/Diamondborder.png';
    if (level >= 20) return '/static/img/borders/Rubyborder.png';
    if (level >= 15) return '/static/img/borders/Goldborder.png';
    if (level >= 10) return '/static/img/borders/Silverborder.png';
    if (level >= 5) return '/static/img/borders/Bronzeborder.png';
    return null;
  };

  const getBorderClass = () => {
    if (typeof window.getAvatarBorderClass === 'function') {
      return window.getAvatarBorderClass(level);
    }
    return '';
  };

  const borderClass = showBorder ? getBorderClass() : '';
  const frameUrl = showBorder ? getBorderFrame() : null;
  const frameSize = frameSizes[size] || 86;

  return (
    <div
      className={clsx('sd-avatar', sizeClasses[size], borderClass)}
      style={{ background: getBackground() }}
    >
      <span className="sd-avatar__initials">
        {(username || 'X').slice(0, 2).toUpperCase()}
      </span>
      {showLevel && level > 0 && (
        <span className="sd-avatar__level">{level}</span>
      )}
      {frameUrl && (
        <img
          src={frameUrl}
          alt=""
          className="sd-avatar__frame"
          style={{
            position: 'absolute',
            top: '50%',
            left: '50%',
            transform: 'translate(-50%, -50%)',
            width: frameSize,
            height: frameSize,
            pointerEvents: 'none',
            zIndex: 10
          }}
        />
      )}
    </div>
  );
}

// ============================================
// ANIMATED DICE ROLL COMPONENT
// ============================================
function AnimatedRoll({ value, isRolling, maxValue = 1000 }) {
  const [display, setDisplay] = useState(value || '---');
  
  useEffect(() => {
    if (isRolling) {
      const interval = setInterval(() => {
        setDisplay(Math.floor(Math.random() * maxValue));
      }, 50);
      return () => clearInterval(interval);
    } else if (value !== null && value !== undefined) {
      setDisplay(value);
    }
  }, [isRolling, value, maxValue]);
  
  return <span>{display}</span>;
}

// ============================================
// BATTLE CARD COMPONENT
// ============================================
function BattleCard({ battle, user, onJoin, onView, isJoining }) {
  const [timeLeft, setTimeLeft] = useState(CONFIG.battleTimeout);
  const isOwn = user && battle.creator_username === user.username;
  const isWaiting = battle.status === 'waiting' || battle.status === 'open';
  const canJoin = user && isWaiting && !isOwn;
  const isResolved = battle.status === 'resolved' || battle.status === 'completed';
  const isRolling = battle.status === 'rolling';

  useEffect(() => {
    if (isResolved || isRolling) return;

    let createdAtStr = battle.created_at;
    if (createdAtStr && !createdAtStr.endsWith('Z') && !createdAtStr.includes('+')) {
      createdAtStr += 'Z';
    }
    const createdAt = new Date(createdAtStr).getTime();
    if (!Number.isFinite(createdAt)) return;

    const updateTimer = () => {
      const elapsed = (Date.now() - createdAt) / 1000;
      const remaining = Math.max(0, CONFIG.battleTimeout - elapsed);
      setTimeLeft(remaining);
    };

    updateTimer();
    const interval = setInterval(updateTimer, 1000);
    return () => clearInterval(interval);
  }, [battle.created_at, isResolved, isRolling]);

  const isUrgent = timeLeft < 60;
  const isWarning = timeLeft < 120 && timeLeft >= 60;
  const winnerIsCreator = isResolved && battle.winner === battle.creator_username;

  return (
    <div className={clsx(
      'bc',
      isResolved && 'bc--resolved',
      isRolling && 'bc--rolling',
      isOwn && 'bc--own'
    )}>
      {/* Main row */}
      <div className="bc__row">
        {/* Creator */}
        <div className={clsx('bc__player', isResolved && winnerIsCreator && 'bc__player--winner')}>
          <div className="bc__avatar-wrap">
            <Avatar 
              username={battle.creator_username} 
              size="sm" 
              level={battle.creator_level || 1} 
              showLevel={true} 
            />
            <span className="bc__dice-badge">🎲</span>
          </div>
          <div className="bc__info">
            <span className="bc__name">{battle.creator_username}</span>
            <span className="bc__bet">{formatCoins(battle.amount)}</span>
          </div>
          {isResolved && battle.creator_roll !== undefined && (
            <span className={clsx(
              'bc__roll',
              winnerIsCreator ? 'bc__roll--win' : 'bc__roll--lose'
            )}>
              {battle.creator_roll}
            </span>
          )}
          {isResolved && winnerIsCreator && (
            <span className="bc__crown">{Icons.crown}</span>
          )}
        </div>

        {/* VS dice */}
        <div className="bc__vs">🎲</div>

        {/* Joiner or waiting */}
        <div className={clsx('bc__player bc__player--right', isResolved && !winnerIsCreator && 'bc__player--winner')}>
          {battle.joiner_username ? (
            <>
              {isResolved && !winnerIsCreator && (
                <span className="bc__crown">{Icons.crown}</span>
              )}
              {isResolved && battle.joiner_roll !== undefined && (
                <span className={clsx(
                  'bc__roll',
                  !winnerIsCreator ? 'bc__roll--win' : 'bc__roll--lose'
                )}>
                  {battle.joiner_roll}
                </span>
              )}
              <div className="bc__info bc__info--right">
                <span className="bc__name">{battle.joiner_username}</span>
                <span className="bc__bet">{formatCoins(battle.join_amount || battle.amount)}</span>
              </div>
              <div className="bc__avatar-wrap">
                <Avatar 
                  username={battle.joiner_username} 
                  size="sm" 
                  level={battle.joiner_level || 1} 
                  showLevel={true} 
                />
                <span className="bc__dice-badge">🎲</span>
              </div>
            </>
          ) : (
            <div className="bc__waiting">
              <span className="bc__waiting-text">Waiting...</span>
              <div className="bc__waiting-icon">?</div>
            </div>
          )}
        </div>
      </div>

      {/* Footer */}
      <div className="bc__footer">
        <div className="bc__pot">
          <img src="/static/coinrushlogos.png" alt="" className="bc__coin" />
          <span>{formatCoins(battle.amount)}</span>
        </div>

        {battle.min_roll > 1 && (
          <div className="bc__minroll">Min: {battle.min_roll}</div>
        )}

        <div className={clsx(
          'bc__status',
          isResolved ? 'bc__status--resolved' : 
          isRolling ? 'bc__status--rolling' : 
          'bc__status--open',
          !isResolved && !isRolling && isUrgent && 'bc__status--urgent',
          !isResolved && !isRolling && isWarning && 'bc__status--warning'
        )}>
          {isResolved ? (
            <>WINNER: {battle.winner}</>
          ) : isRolling ? (
            <>🎲 ROLLING...</>
          ) : (
            <><span className="bc__timer-icon">{Icons.clock}</span> {formatTime(timeLeft)}</>
          )}
        </div>

        <div className="bc__actions">
          <button className="bc__btn bc__btn--view" onClick={() => onView(battle)}>
            <span className="bc__btn-icon">{isResolved ? Icons.refresh : Icons.eye}</span>
          </button>
          {canJoin && (
            <button 
              className="bc__btn bc__btn--join" 
              onClick={() => onJoin(battle)} 
              disabled={isJoining}
            >
              {isJoining ? '...' : 'Join'}
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

// ============================================
// CREATE BATTLE PANEL
// ============================================
function CreateBattlePanel({ user, onRefresh }) {
  const [amount, setAmount] = useState('10,00');
  const [minRoll, setMinRoll] = useState('1');
  const [loading, setLoading] = useState(false);
  const [error, setError] = useState('');

  const amountCents = parseCoinsInput(amount);

  const handleCreate = async () => {
    if (!user) {
      window.openAuthModal?.('login');
      return;
    }

    if (amountCents < CONFIG.minBet) {
      setError('Minimum bet is 1.00 coins');
      return;
    }

    if (amountCents > (user.balance || 0)) {
      setError('Insufficient balance');
      return;
    }

    setLoading(true);
    setError('');

    try {
      // API expects amount in coins (not hundredths)
      const amountCoins = amountCents / 100;
      await api('/api/slice-dice/create', {
        method: 'POST',
        body: { 
          amount: amountCoins, 
          min_roll: parseInt(minRoll) || 1 
        }
      });
      onRefresh?.();
      setAmount('10,00');
    } catch (err) {
      setError(err.message || 'Failed to create battle');
    } finally {
      setLoading(false);
    }
  };

  return (
    <div className="create-panel">
      <div className="create-panel__header">
        <div className="create-panel__title">
          <span className="create-panel__icon">{Icons.bolt}</span>
          Create Battle
        </div>
      </div>

      <div className="create-panel__content">
        {/* Amount Input */}
        <div className="amount-input">
          <input
            type="text"
            value={amount}
            onChange={(e) => setAmount(e.target.value)}
            placeholder="10,00"
          />
          <img src="/static/coinrushlogos.png" alt="" />
        </div>

        {/* Amount Presets */}
        <div className="amount-presets">
          {['5', '10', '25', '50', '100', '250', '500'].map(p => (
            <button 
              key={p} 
              onClick={() => setAmount(p + ',00')} 
              className="preset-btn"
            >
              {p}
            </button>
          ))}
          {user?.balance > 0 && (
            <button 
              onClick={() => setAmount(formatCoins(user.balance))} 
              className="preset-btn preset-btn--max"
            >
              MAX
            </button>
          )}
        </div>

        {/* Min Roll */}
        <div className="minroll-section">
          <span className="minroll-label">Min Roll (optional)</span>
          <div className="minroll-input">
            <input
              type="number"
              min="1"
              max="999"
              value={minRoll}
              onChange={(e) => setMinRoll(e.target.value)}
              placeholder="1"
            />
            <span className="minroll-hint">Default: 1</span>
          </div>
        </div>

        {/* Error */}
        {error && <div className="create-panel__error">{error}</div>}

        {/* CTA */}
        <div className="create-panel__cta">
          {user ? (
            <button 
              onClick={handleCreate} 
              disabled={loading} 
              className="cta-btn cta-btn--primary cta-btn--full"
            >
              <span className="cta-icon">{Icons.dice}</span>
              {loading ? 'Creating...' : 'Create Battle'}
            </button>
          ) : (
            <button 
              onClick={() => window.openAuthModal?.('login')} 
              className="cta-btn cta-btn--login cta-btn--full"
            >
              <span className="cta-icon">{Icons.users}</span>
              Login to Play
            </button>
          )}
        </div>
      </div>
    </div>
  );
}

// ============================================
// HISTORY TICKER
// ============================================
function HistoryTicker({ history }) {
  if (!history?.length) return null;

  // Duplicate for seamless scroll
  const items = [...history.slice(0, 12), ...history.slice(0, 12)];

  return (
    <div className="sd-ticker">
      <div className="sd-ticker-track">
        {items.map((h, i) => (
          <div key={i} className="sd-ticker-item">
            <span className="sd-ticker-id">#{h.id}</span>
            <span className="sd-ticker-winner">{h.winner}</span>
            <span className="sd-ticker-text">won</span>
            <span className="sd-ticker-amount sd-ticker-amount--win">
              {formatCoins(h.amount)}
            </span>
            <span className="sd-ticker-text">with</span>
            <span className="sd-ticker-roll">{h.winner_roll}</span>
          </div>
        ))}
      </div>
    </div>
  );
}

// ============================================
// RULES MODAL
// ============================================
function RulesModal({ isOpen, onClose }) {
  if (!isOpen) return null;

  const rules = [
    {
      icon: Icons.dice,
      title: 'Roll the Dice',
      desc: 'Both players roll a random number between 1 and 1000. The higher roll wins!'
    },
    {
      icon: Icons.trophy,
      title: 'Winner Takes All',
      desc: 'The winner receives the combined pot minus a small 2% house fee.'
    },
    {
      icon: Icons.target,
      title: 'Min Roll Option',
      desc: 'Set a minimum roll requirement to filter out low-stakes players.'
    },
    {
      icon: Icons.shield,
      title: 'Provably Fair',
      desc: 'All rolls are cryptographically verified. Check any result with the seed!'
    }
  ];

  return (
    <div className="sd-modal-overlay" onClick={onClose}>
      <div className="sd-modal" onClick={(e) => e.stopPropagation()}>
        <div className="sd-modal-header">
          <div className="sd-modal-title">
            <span className="sd-modal-icon">{Icons.info}</span>
            How to Play
          </div>
          <button className="sd-modal-close" onClick={onClose}>
            {Icons.close}
          </button>
        </div>
        <div className="sd-modal-body">
          <ul className="rules-list">
            {rules.map((rule, i) => (
              <li key={i} className="rules-item">
                <span className="rules-icon">{rule.icon}</span>
                <div className="rules-content">
                  <h4>{rule.title}</h4>
                  <p>{rule.desc}</p>
                </div>
              </li>
            ))}
          </ul>
        </div>
        <div className="sd-modal-footer">
          <button className="cta-btn cta-btn--primary" onClick={onClose}>
            Got It!
          </button>
        </div>
      </div>
    </div>
  );
}

// ============================================
// DAILY REWARD MODAL
// ============================================
function DailyRewardModal({ isOpen, onClose, user, onClaim }) {
  const [claiming, setClaiming] = useState(false);

  if (!isOpen) return null;

  const handleClaim = async () => {
    setClaiming(true);
    try {
      await api('/api/daily-reward/claim', { method: 'POST' });
      onClaim?.();
      onClose();
    } catch (err) {
      console.error('Failed to claim:', err);
    } finally {
      setClaiming(false);
    }
  };

  return (
    <div className="sd-modal-overlay" onClick={onClose}>
      <div className="sd-modal" onClick={(e) => e.stopPropagation()}>
        <div className="sd-modal-header">
          <div className="sd-modal-title">
            <span className="sd-modal-icon">{Icons.gift}</span>
            Daily Reward
          </div>
          <button className="sd-modal-close" onClick={onClose}>
            {Icons.close}
          </button>
        </div>
        <div className="sd-modal-body">
          <div className="daily-reward-content">
            <div className="daily-reward-icon">{Icons.gift}</div>
            <h3 className="daily-reward-title">Claim Your Daily Bonus!</h3>
            <p className="daily-reward-subtitle">Come back every day for free coins</p>
            <div className="daily-reward-amount">+50.00</div>
            <button 
              className="daily-reward-claim" 
              onClick={handleClaim}
              disabled={claiming}
            >
              {claiming ? 'Claiming...' : 'Claim Reward'}
            </button>
          </div>
        </div>
      </div>
    </div>
  );
}

// ============================================
// SLOT DIGIT - Smooth Scrolling Number Wheel
// Each slot spins at constant speed, then individually decelerates to land on target
// ============================================
function SlotDigit({ targetValue, isSpinning = false, stopDelay = 0, onStopped }) {
  const [offset, setOffset] = useState(0);
  const [phase, setPhase] = useState('idle'); // 'idle' | 'spinning' | 'stopping' | 'stopped'
  const animationRef = useRef(null);
  const stopTimerRef = useRef(null);
  const hasStoppedRef = useRef(false);
  const targetReceivedRef = useRef(false);
  const currentOffsetRef = useRef(0);
  const phaseRef = useRef('idle');
  
  // Height of each number in pixels
  const DIGIT_HEIGHT = 72;
  const FULL_ROTATION = DIGIT_HEIGHT * 10;
  
  // SLOW spin speed (pixels per millisecond) - nice and readable
  const SPIN_SPEED = 0.12;
  
  // All numbers for the strip (repeated for smooth wrap-around)
  const numbers = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
  
  // Cleanup function
  const cleanup = useCallback(() => {
    if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
      animationRef.current = null;
    }
    if (stopTimerRef.current) {
      clearTimeout(stopTimerRef.current);
      stopTimerRef.current = null;
    }
  }, []);
  
  // Cleanup on unmount
  useEffect(() => {
    return cleanup;
  }, [cleanup]);
  
  // Main animation logic
  useEffect(() => {
    // Start spinning
    if (isSpinning && phaseRef.current === 'idle') {
      phaseRef.current = 'spinning';
      setPhase('spinning');
      currentOffsetRef.current = Math.random() * FULL_ROTATION;
      
      let lastTime = performance.now();
      
      const spin = (timestamp) => {
        if (phaseRef.current !== 'spinning') return;
        
        const delta = timestamp - lastTime;
        lastTime = timestamp;
        
        currentOffsetRef.current = (currentOffsetRef.current + delta * SPIN_SPEED) % FULL_ROTATION;
        setOffset(currentOffsetRef.current);
        
        animationRef.current = requestAnimationFrame(spin);
      };
      
      animationRef.current = requestAnimationFrame(spin);
    }
  }, [isSpinning]);
  
  // Handle stopping when target value arrives
  useEffect(() => {
    if (targetValue === null || targetValue === undefined) return;
    if (targetReceivedRef.current) return;
    if (phaseRef.current !== 'spinning') return;
    
    targetReceivedRef.current = true;
    
    // Schedule the stop
    stopTimerRef.current = setTimeout(() => {
      // Cancel spinning animation
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
        animationRef.current = null;
      }
      
      phaseRef.current = 'stopping';
      setPhase('stopping');
      
      // Where we want to land
      const targetOffset = targetValue * DIGIT_HEIGHT;
      const startOffset = currentOffsetRef.current;
      
      // Calculate distance to target - ensure we travel forward to it
      let distanceToTarget = ((targetOffset - startOffset) % FULL_ROTATION + FULL_ROTATION) % FULL_ROTATION;
      if (distanceToTarget < DIGIT_HEIGHT * 3) {
        distanceToTarget += FULL_ROTATION; // Go around once more if too close
      }
      
      // We want to decelerate smoothly from SPIN_SPEED to 0
      // Using physics: distance = v0 * t - 0.5 * a * t^2, where final velocity = 0
      // For smooth stop: distance = v0 * t / 2 (average velocity over deceleration)
      // So: t = 2 * distance / v0
      const DECEL_DURATION = (2 * distanceToTarget) / SPIN_SPEED;
      
      const decelStartTime = performance.now();
      let lastTime = decelStartTime;
      let currentSpeed = SPIN_SPEED;
      const decelRate = SPIN_SPEED / DECEL_DURATION; // How much to reduce speed per ms
      
      const decelerate = (timestamp) => {
        const delta = timestamp - lastTime;
        lastTime = timestamp;
        
        // Reduce speed linearly
        currentSpeed = Math.max(0, currentSpeed - decelRate * delta);
        
        // Move based on current speed
        currentOffsetRef.current = (currentOffsetRef.current + delta * currentSpeed) % FULL_ROTATION;
        setOffset(currentOffsetRef.current);
        
        if (currentSpeed > 0.001) {
          animationRef.current = requestAnimationFrame(decelerate);
        } else {
          // Done - snap to exact target
          setOffset(targetOffset);
          phaseRef.current = 'stopped';
          setPhase('stopped');
          
          if (onStopped && !hasStoppedRef.current) {
            hasStoppedRef.current = true;
            onStopped();
          }
        }
      };
      
      animationRef.current = requestAnimationFrame(decelerate);
    }, stopDelay);
    
  }, [targetValue, stopDelay, onStopped]);
  
  // Cleanup on unmount
  useEffect(() => {
    return cleanup;
  }, [cleanup]);
  
  // Show placeholder when idle
  if (phase === 'idle') {
    return (
      <div className="dice-popup__digit dice-popup__digit--idle">
        <span className="dice-popup__digit-placeholder">-</span>
      </div>
    );
  }
  
  return (
    <div 
      className={clsx(
        'dice-popup__digit',
        (phase === 'spinning' || phase === 'stopping') && 'dice-popup__digit--spinning',
        phase === 'stopped' && 'dice-popup__digit--revealed'
      )}
    >
      <div 
        className="dice-popup__digit-strip"
        style={{ 
          transform: `translateY(-${offset}px)`,
        }}
      >
        {numbers.map((num, i) => (
          <span key={i} className="dice-popup__digit-num">{num}</span>
        ))}
      </div>
    </div>
  );
}

// ============================================
// DUEL POPUP - Premium Dice Battle Modal
// ============================================
function DuelPopup({ duel, phase, user, onClose, onRefresh }) {
  const [localPhase, setLocalPhase] = useState(phase || 'waiting');
  const [showConfetti, setShowConfetti] = useState(false);
  const [confetti, setConfetti] = useState([]);
  const [countdown, setCountdown] = useState(null);
  const [isSpinning, setIsSpinning] = useState(false); // Controls when dice start spinning
  const [stoppedCount, setStoppedCount] = useState(0);
  const countdownRef = useRef(null);
  const hasStartedRef = useRef(false);
  
  if (!duel) return null;

  const maxRoll = duel.amount || 100;
  const digitCount = String(maxRoll).length;
  const minRoll = duel.min_roll || 1;
  
  const creatorRoll = duel.creator_roll;
  const joinerRoll = duel.joiner_roll;
  const hasRolls = creatorRoll !== undefined && joinerRoll !== undefined && creatorRoll !== null && joinerRoll !== null;
  const winnerIsCreator = hasRolls && creatorRoll > joinerRoll;
  const winnerUsername = hasRolls ? (winnerIsCreator ? duel.creator_username : duel.joiner_username) : null;
  const difference = hasRolls ? Math.abs(creatorRoll - joinerRoll) : 0;
  
  const userIsCreator = user?.username === duel.creator_username;
  const userIsJoiner = user?.username === duel.joiner_username;
  const userInGame = userIsCreator || userIsJoiner;
  const userWon = userInGame && hasRolls && (
    (userIsCreator && winnerIsCreator) || 
    (userIsJoiner && !winnerIsCreator)
  );

  // Pad number to fixed digits
  const padNumber = (num, len) => {
    return String(num).padStart(len, '0').split('').map(Number);
  };
  
  // Target digits - passed to SlotDigit when rolls are available
  const creatorDigits = hasRolls ? padNumber(creatorRoll, digitCount) : null;
  const joinerDigits = hasRolls ? padNumber(joinerRoll, digitCount) : null;

  // Generate confetti
  const generateConfetti = () => {
    const colors = ['#5bffb2', '#3dd492', '#fbbf24', '#22c55e', '#4ade80', '#ffffff'];
    return Array.from({ length: 60 }, (_, i) => ({
      id: i,
      x: Math.random() * 100,
      color: colors[Math.floor(Math.random() * colors.length)],
      size: 6 + Math.random() * 8,
      delay: Math.random() * 0.5,
      duration: 2 + Math.random() * 2
    }));
  };

  // Start countdown when phase becomes 'ready'
  useEffect(() => {
    if (phase === 'ready' && !hasStartedRef.current) {
      hasStartedRef.current = true;
      setLocalPhase('ready');
      setCountdown(3); // Faster countdown
      
      if (countdownRef.current) clearInterval(countdownRef.current);
      
      let count = 3;
      countdownRef.current = setInterval(() => {
        count -= 1;
        if (count <= 0) {
          clearInterval(countdownRef.current);
          countdownRef.current = null;
          setCountdown(null);
          // Start spinning immediately when countdown ends!
          setLocalPhase('rolling');
          setIsSpinning(true);
        } else {
          setCountdown(count);
        }
      }, 800); // Faster tick (0.8s instead of 1s)
    }
    
    return () => {
      if (countdownRef.current) {
        clearInterval(countdownRef.current);
        countdownRef.current = null;
      }
    };
  }, [phase]);

  // FALLBACK: If rolls arrive without countdown (late joiner, spectator, etc)
  useEffect(() => {
    if (hasRolls && !hasStartedRef.current && !isSpinning) {
      // No countdown was started, just start spinning directly
      setLocalPhase('rolling');
      setIsSpinning(true);
    }
  }, [hasRolls, isSpinning]);

  // Track when all digits have stopped rolling
  const handleDigitStopped = useCallback(() => {
    setStoppedCount(prev => {
      const newCount = prev + 1;
      // Each player has digitCount digits, so total is digitCount * 2
      if (newCount >= digitCount * 2) {
        // All digits stopped - show result after a brief pause
        setTimeout(() => {
          setLocalPhase('resolved');
          setConfetti(generateConfetti());
          setShowConfetti(true);
          setTimeout(() => setShowConfetti(false), 4000);
        }, 500);
      }
      return newCount;
    });
  }, [digitCount]);

  // Handle direct resolved phase (for spectators joining late)
  useEffect(() => {
    if (phase === 'resolved' && localPhase !== 'resolved' && !isSpinning) {
      setLocalPhase('resolved');
      setIsSpinning(true);
    }
  }, [phase, localPhase, isSpinning]);

  return (
    <div className="dice-popup" onClick={onClose}>
      {/* Backdrop */}
      <div className="dice-popup__backdrop" />

      {/* Confetti */}
      {showConfetti && (
        <div className="dice-popup__confetti">
          {confetti.map(c => (
            <div key={c.id} className="dice-popup__confetti-piece" style={{
              left: `${c.x}%`,
              backgroundColor: c.color,
              width: c.size,
              height: c.size * 0.4,
              animationDelay: `${c.delay}s`,
              animationDuration: `${c.duration}s`
            }} />
          ))}
        </div>
      )}

      {/* Modal Card */}
      <div className={clsx('dice-popup__card', `dice-popup__card--${localPhase}`)} onClick={e => e.stopPropagation()}>
        
        {/* Close button */}
        <button className="dice-popup__close" onClick={onClose}>
          {Icons.close}
        </button>

        {/* Header - centered amount */}
        <div className="dice-popup__header">
          <div className="dice-popup__pot dice-popup__pot--centered">
            <img src="/static/coinrushlogos.png" alt="" className="dice-popup__pot-icon" />
            <span>{formatCoins(duel.amount)}</span>
          </div>
          <span className="dice-popup__id">Battle #{duel.id}</span>
        </div>

        {/* Status */}
        <div className={clsx('dice-popup__status', `dice-popup__status--${localPhase}`)}>
          {localPhase === 'waiting' && (
            <>
              <span className="dice-popup__status-icon">{Icons.hourglass}</span>
              <span>Waiting for opponent...</span>
            </>
          )}
          {localPhase === 'ready' && (
            <>
              {countdown !== null ? (
                <>
                  <span className="dice-popup__countdown">{countdown}</span>
                  <span>Get ready!</span>
                </>
              ) : (
                <>
                  <span className="dice-popup__status-icon">{Icons.swords}</span>
                  <span>Battle Starting!</span>
                </>
              )}
            </>
          )}
          {localPhase === 'rolling' && (
            <>
              <span className="dice-popup__status-icon dice-popup__dice-spin">{Icons.dice}</span>
              <span>Rolling the dice...</span>
            </>
          )}
          {localPhase === 'revealing' && (
            <>
              <span className="dice-popup__status-icon">{Icons.sparkle}</span>
              <span>Revealing...</span>
            </>
          )}
          {localPhase === 'resolved' && (
            <>
              <span className="dice-popup__winner-icon">{Icons.crown}</span>
              <span>{winnerUsername} wins!</span>
            </>
          )}
        </div>

        {/* Players */}
        <div className="dice-popup__players">
          
          {/* Creator */}
          <div className={clsx(
            'dice-popup__player',
            localPhase === 'resolved' && winnerIsCreator && 'dice-popup__player--winner',
            localPhase === 'resolved' && !winnerIsCreator && 'dice-popup__player--loser'
          )}>
            {localPhase === 'resolved' && winnerIsCreator && (
              <div className="dice-popup__crown">{Icons.crown}</div>
            )}
            <Avatar 
              username={duel.creator_username} 
              size="lg" 
              level={duel.creator_level || 1} 
              showLevel={true} 
            />
            <div className="dice-popup__name">
              {duel.creator_username}
              {userIsCreator && <span className="dice-popup__you">YOU</span>}
            </div>
            <div className="dice-popup__bet">{formatCoins(duel.amount)}</div>
            
            {/* Roll Display */}
            <div className={clsx(
              'dice-popup__roll',
              localPhase === 'rolling' && 'dice-popup__roll--rolling',
              localPhase === 'resolved' && winnerIsCreator && 'dice-popup__roll--win',
              localPhase === 'resolved' && !winnerIsCreator && 'dice-popup__roll--lose'
            )}>
              {Array.from({ length: digitCount }).map((_, i) => (
                <SlotDigit
                  key={`creator-${i}`}
                  isSpinning={isSpinning}
                  targetValue={creatorDigits ? creatorDigits[i] : null}
                  stopDelay={1200 + (i * 350)}
                  onStopped={handleDigitStopped}
                />
              ))}
            </div>
          </div>

          {/* VS Center */}
          <div className="dice-popup__center">
            <div className={clsx(
              'dice-popup__dice',
              localPhase === 'rolling' && 'dice-popup__dice--rolling'
            )}>
              {Icons.dice}
            </div>
            <span className="dice-popup__vs">VS</span>
            <div className="dice-popup__range">{minRoll} - {maxRoll}</div>
          </div>

          {/* Joiner */}
          <div className={clsx(
            'dice-popup__player',
            localPhase === 'resolved' && !winnerIsCreator && 'dice-popup__player--winner',
            localPhase === 'resolved' && winnerIsCreator && 'dice-popup__player--loser'
          )}>
            {localPhase === 'resolved' && !winnerIsCreator && (
              <div className="dice-popup__crown">{Icons.crown}</div>
            )}
            {duel.joiner_username ? (
              <>
                <Avatar 
                  username={duel.joiner_username} 
                  size="lg" 
                  level={duel.joiner_level || 1} 
                  showLevel={true} 
                />
                <div className="dice-popup__name">
                  {duel.joiner_username}
                  {userIsJoiner && <span className="dice-popup__you">YOU</span>}
                </div>
                <div className="dice-popup__bet">{formatCoins(duel.join_amount || duel.amount)}</div>
                
                {/* Roll Display */}
                <div className={clsx(
                  'dice-popup__roll',
                  localPhase === 'rolling' && 'dice-popup__roll--rolling',
                  localPhase === 'resolved' && !winnerIsCreator && 'dice-popup__roll--win',
                  localPhase === 'resolved' && winnerIsCreator && 'dice-popup__roll--lose'
                )}>
                  {Array.from({ length: digitCount }).map((_, i) => (
                    <SlotDigit
                      key={`joiner-${i}`}
                      isSpinning={isSpinning}
                      targetValue={joinerDigits ? joinerDigits[i] : null}
                      stopDelay={1400 + (i * 350)}
                      onStopped={handleDigitStopped}
                    />
                  ))}
                </div>
              </>
            ) : (
              <>
                <div className="dice-popup__avatar-waiting">?</div>
                <div className="dice-popup__name dice-popup__name--waiting">Waiting...</div>
              </>
            )}
          </div>
        </div>

        {/* Result Info */}
        {localPhase === 'resolved' && (
          <div className="dice-popup__result">
            <div className="dice-popup__result-row">
              <span className="dice-popup__result-label">Difference:</span>
              <span className="dice-popup__result-value">{difference}</span>
            </div>
            <div className="dice-popup__result-row">
              <span className="dice-popup__result-label">Winner takes:</span>
              <span className="dice-popup__result-value dice-popup__result-value--gold">
                +{formatCoins(difference)}
              </span>
            </div>
          </div>
        )}

        {/* User Result Banner */}
        {userInGame && localPhase === 'resolved' && (
          <div className={clsx(
            'dice-popup__banner',
            userWon ? 'dice-popup__banner--won' : 'dice-popup__banner--lost'
          )}>
            {userWon ? (
              <>
                <span className="dice-popup__banner-icon">{Icons.checkCircle}</span>
                <span className="dice-popup__banner-text">YOU WON!</span>
                <span className="dice-popup__banner-prize">+{formatCoins(difference)}</span>
              </>
            ) : (
              <>
                <span className="dice-popup__banner-icon">{Icons.crossX}</span>
                <span className="dice-popup__banner-text">YOU LOST</span>
                <span className="dice-popup__banner-loss">-{formatCoins(difference)}</span>
              </>
            )}
          </div>
        )}

        {/* Footer */}
        <div className="dice-popup__footer">
          <span className="dice-popup__fair">
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" width="12" height="12">
              <path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
            </svg>
            Provably Fair
          </span>
          <button className="dice-popup__btn" onClick={onClose}>
            {localPhase === 'resolved' ? (userWon ? 'Collect' : 'Close') : 'Close'}
          </button>
        </div>
      </div>
    </div>
  );
}

// ============================================
// MAIN APP
// ============================================
function SliceDiceApp() {
  // State
  const [user, setUser] = useState(null);
  const [battles, setBattles] = useState([]);
  const [history, setHistory] = useState([]);
  const [wsConnected, setWsConnected] = useState(false);
  const [filter, setFilter] = useState('all');
  const [joiningId, setJoiningId] = useState(null);
  
  // Modals
  const [showRules, setShowRules] = useState(false);
  const [showDailyModal, setShowDailyModal] = useState(false);
  const [showAuthModal, setShowAuthModal] = useState(false);
  const [authModalMode, setAuthModalMode] = useState('login');
  
  // Duel state
  const [activeDuel, setActiveDuel] = useState(null);
  const [duelPhase, setDuelPhase] = useState(null);
  
  const wsRef = useRef(null);
  const activeDuelRef = useRef(null);
  const userRef = useRef(null);
  
  // Keep refs in sync with state
  useEffect(() => { activeDuelRef.current = activeDuel; }, [activeDuel]);
  useEffect(() => { userRef.current = user; }, [user]);

  // Load user
  const loadUser = useCallback(async () => {
    try {
      const data = await api('/me');
      setUser(data);
    } catch {
      setUser(null);
    }
  }, []);

  // Load battles
  const loadBattles = useCallback(async () => {
    try {
      const data = await api('/api/slice-dice/active');
      setBattles(data.games || []);
    } catch (err) {
      console.error('Failed to load battles:', err);
    }
  }, []);

  // Load history
  const loadHistory = useCallback(async () => {
    try {
      const data = await api('/api/slice-dice/history');
      setHistory(data.history || []);
    } catch (err) {
      console.error('Failed to load history:', err);
    }
  }, []);

  // Initial load
  useEffect(() => {
    loadUser();
    loadBattles();
    loadHistory();
  }, [loadUser, loadBattles, loadHistory]);

  // WebSocket connection
  useEffect(() => {
    const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
    const socket = new WebSocket(`${protocol}//${window.location.host}/ws/slice-dice`);
    wsRef.current = socket;

    socket.onopen = () => {
      console.log('[SliceDice WS] Connected');
      setWsConnected(true);
    };

    socket.onclose = () => {
      console.log('[SliceDice WS] Disconnected');
      setWsConnected(false);
      // Reconnect
      setTimeout(() => {
        if (wsRef.current === socket) {
          loadBattles();
        }
      }, CONFIG.wsReconnectDelay);
    };

    socket.onmessage = (event) => {
      try {
        const data = JSON.parse(event.data);
        console.log('[SliceDice WS]', data);
        
        // Use refs to access current values without recreating socket
        const currentDuel = activeDuelRef.current;
        const currentUser = userRef.current;

        if (data.type === 'game_created') {
          // WS sends flat data, not nested game object
          const game = {
            id: data.game_id,
            creator_username: data.creator_username,
            creator_level: data.creator_level || 1,
            amount: data.amount,
            min_roll: data.min_roll,
            status: 'waiting',
            created_at: data.created_at,
            server_seed_hash: data.server_seed_hash
          };
          setBattles(prev => [game, ...prev.filter(g => g.id !== game.id)]);
          
          // If current user created this game, open the popup for them
          if (currentUser && data.creator_username === currentUser.username) {
            setActiveDuel(game);
            setDuelPhase('waiting');
          }
        }

        if (data.type === 'game_joined') {
          // Reload battles to get fresh data (removes the joined game)
          loadBattles();
          
          // If we're watching this game OR we're the creator, update
          if (currentDuel && currentDuel.id === data.game_id) {
            setActiveDuel(prev => ({
              ...prev,
              joiner_username: data.joiner_username,
              joiner_id: data.joiner_id
            }));
            setDuelPhase('ready');
          }
        }

        if (data.type === 'game_countdown') {
          // Countdown started - start the 5 second countdown, but stay in 'ready' phase
          // The countdown visual runs in the DuelPopup component
          if (currentDuel && currentDuel.id === data.game_id) {
            // Phase stays 'ready' - the countdown is shown during 'ready' phase
            // After 5 seconds, set to 'rolling' for the dice animation
            setTimeout(() => {
              setDuelPhase('rolling');
            }, 5000);
          }
        }

        if (data.type === 'game_rolling') {
          // The roll results are in - update activeDuel and trigger reveal
          if (currentDuel && currentDuel.id === data.game_id) {
            setActiveDuel(prev => ({
              ...prev,
              creator_roll: data.creator_roll,
              joiner_roll: data.joiner_roll,
              winner_username: data.winner_username,
              difference: data.difference,
              net_winnings: data.net_winnings,
              house_fee: data.house_fee,
              server_seed: data.server_seed,
              client_seed: data.client_seed,
              nonce: data.nonce,
              ticket: data.ticket
            }));
            setDuelPhase('revealing');
          }
          
          // Update user balance if we're the creator or joiner
          if (currentUser && (currentUser.id === data.creator_id || currentUser.id === data.joiner_id)) {
            const newBalance = currentUser.id === data.creator_id ? data.creator_balance : data.joiner_balance;
            setUser(prev => prev ? { ...prev, balance: newBalance } : prev);
          }
        }

        if (data.type === 'game_complete') {
          // Game is fully complete
          if (currentDuel && currentDuel.id === data.game_id) {
            setDuelPhase('resolved');
          }
          
          // Reload battles and history
          loadBattles();
          loadHistory();
        }

        if (data.type === 'game_resolved') {
          // Reload battles and history
          loadBattles();
          loadHistory();
          
          // Refresh user balance
          loadUser();
        }

        if (data.type === 'game_expired') {
          setBattles(prev => prev.filter(g => g.id !== data.game_id));
        }

      } catch (err) {
        console.error('[SliceDice WS] Parse error:', err);
      }
    };

    return () => socket.close();
  }, [loadBattles, loadUser, loadHistory]);

  // Handle join
  const handleJoin = async (battle) => {
    if (joiningId) return;
    setJoiningId(battle.id);
    
    // Open the popup IMMEDIATELY before API call (API blocks for ~12 seconds)
    const gameData = {
      ...battle,
      joiner_username: user?.username || 'You',
      joiner_level: user?.level || 1,
      creator_level: battle.creator_level || 1,
    };
    setActiveDuel(gameData);
    setDuelPhase('ready');
    
    try {
      const result = await api('/api/slice-dice/join', {
        method: 'POST',
        body: { game_id: battle.id }
      });
      
      // Update user balance after join completes
      if (result.balance !== undefined) {
        setUser(prev => prev ? { ...prev, balance: result.balance } : prev);
      }
    } catch (err) {
      console.error('Failed to join:', err);
      alert(err.message || 'Failed to join battle');
      // Close popup on error
      setActiveDuel(null);
      setDuelPhase(null);
    } finally {
      setJoiningId(null);
    }
  };

  // Handle logout
  const handleLogout = async () => {
    try {
      await api('/auth/logout', { method: 'POST' });
      setUser(null);
    } catch {}
  };

  // Auth success
  const handleAuthSuccess = (userData) => {
    setUser(userData);
    setShowAuthModal(false);
  };

  // Expose functions
  useEffect(() => {
    window.openAuthModal = (mode) => {
      setAuthModalMode(mode);
      setShowAuthModal(true);
    };
    window.showSliceDiceRules = () => setShowRules(true);
    window.dailyRewardsModal = { open: () => setShowDailyModal(true) };
  }, []);

  // Filter battles
  const filteredBattles = battles.filter(b => {
    if (filter === 'all') return true;
    if (filter === 'high') return b.amount >= 10000;
    if (filter === 'open') return b.status === 'waiting';
    return true;
  });

  // Components
  const NavbarComponent = window.CoinRushNavbar;
  const ChatComponent = window.CoinRushChatApp;

  return (
    <div className="sd-app">
      {/* Background effects */}
      <div className="sd-orbs">
        <div className="sd-orb sd-orb--1" />
        <div className="sd-orb sd-orb--2" />
        <div className="sd-orb sd-orb--3" />
      </div>

      <div className="sd-particles">
        {[...Array(25)].map((_, i) => (
          <div 
            key={i} 
            className="sd-particle"
            style={{
              '--x': `${(i * 17 + 5) % 90 + 5}%`,
              '--delay': `${i * 0.3}s`,
              '--duration': `${5 + (i % 4)}s`,
              '--size': `${2 + (i % 3)}px`,
              '--color': i % 2 === 0 ? 'rgba(91, 255, 178, 0.8)' : 'rgba(251, 191, 36, 0.8)'
            }}
          />
        ))}
      </div>

      {/* Navbar */}
      {NavbarComponent && (
        <NavbarComponent
          user={user}
          isConnected={wsConnected}
          activePage="slicedice"
          onLogout={handleLogout}
        />
      )}

      {/* Auth Modal */}
      {window.AuthModal && (
        <window.AuthModal
          isOpen={showAuthModal}
          initialMode={authModalMode}
          onClose={() => setShowAuthModal(false)}
          onSuccess={handleAuthSuccess}
        />
      )}

      {/* Connection warning */}
      {!wsConnected && (
        <div className="sd-connection-warning">
          ⚠️ Connection lost. Reconnecting...
        </div>
      )}

      {/* History ticker */}
      <HistoryTicker history={history} />

      {/* Main layout */}
      <div className="sd-layout">
        {/* Left sidebar: Create panel */}
        <div className="sd-sidebar sd-sidebar--left">
          <CreateBattlePanel user={user} onRefresh={loadBattles} />
        </div>

        {/* Center: Battles */}
        <div className="sd-main">
          {/* Header */}
          <div className="sd-header">
            <div className="sd-header-title">
              <h1>Live Battles</h1>
              <div className="sd-header-status">
                <span className="sd-status-dot" />
                <span>{battles.length} Active</span>
              </div>
            </div>

            <div className="sd-header-actions">
              <div className="sd-filter-tabs">
                {['all', 'open', 'high'].map(f => (
                  <button
                    key={f}
                    onClick={() => setFilter(f)}
                    className={clsx('sd-filter-tab', filter === f && 'sd-filter-tab--active')}
                  >
                    {f === 'all' ? 'All' : f === 'high' ? (
                      <><span className="sd-filter-icon">{Icons.crown}</span> High</>
                    ) : 'Open'}
                  </button>
                ))}
              </div>

              <button 
                className="sd-btn sd-btn--ghost" 
                onClick={() => setShowRules(true)}
              >
                <span className="sd-btn-icon">{Icons.info}</span>
                Rules
              </button>
            </div>
          </div>

          {/* Battle list */}
          <div className="sd-battle-list">
            {filteredBattles.length > 0 ? (
              filteredBattles.map(battle => (
                <BattleCard
                  key={battle.id}
                  battle={battle}
                  user={user}
                  onJoin={handleJoin}
                  onView={(b) => {
                    setActiveDuel(b);
                    setDuelPhase(b.status === 'resolved' || b.status === 'completed' ? 'resolved' : 
                                 b.status === 'rolling' ? 'rolling' : 'waiting');
                  }}
                  isJoining={joiningId === battle.id}
                />
              ))
            ) : (
              <div className="sd-empty-state sd-empty-state--large">
                <span className="sd-empty-icon">{Icons.dice}</span>
                <h3>No Active Battles</h3>
                <p>Create the first battle to get started!</p>
              </div>
            )}
          </div>
        </div>

        {/* Right sidebar: Chat */}
        <div className="sd-sidebar sd-sidebar--right">
          <div className="sd-chat-wrapper">
            {ChatComponent && (
              <ChatComponent currentUser={user} theme="green" />
            )}
          </div>
        </div>
      </div>

      {/* Duel Popup */}
      {activeDuel && (
        <DuelPopup
          duel={activeDuel}
          phase={duelPhase}
          user={user}
          onClose={() => {
            setActiveDuel(null);
            setDuelPhase(null);
          }}
          onRefresh={loadBattles}
        />
      )}

      {/* Modals */}
      <RulesModal isOpen={showRules} onClose={() => setShowRules(false)} />
      <DailyRewardModal 
        isOpen={showDailyModal} 
        onClose={() => setShowDailyModal(false)}
        user={user}
        onClaim={loadUser}
      />
    </div>
  );
}

// ============================================
// RENDER
// ============================================
const rootEl = document.getElementById('slicedice-root');
if (rootEl) {
  const root = ReactDOM.createRoot(rootEl);
  root.render(<SliceDiceApp />);
}
