/* ── Crate Unboxer ──────────────────────────────────────────────────────────── */

const RARITY = {
  grand:     { color: '#4db34d', label: 'Grand'     },
  rare:      { color: '#4a9edd', label: 'Rare'      },
  arcane:    { color: '#9b6bc8', label: 'Arcane'    },
  heroic:    { color: '#d4b832', label: 'Heroic'    },
  unique:    { color: '#e07c2e', label: 'Unique'    },
  celestial: { color: '#d47878', label: 'Celestial' },
  divine:    { color: '#c8b87a', label: 'Divine',    glow: true },
  epic:      { color: '#f0f0f0', label: 'Epic',      glow: true },
  legendary: { color: '#c8960a', label: 'Legendary', glow: true },
  mythic:    { color: '#ff2020', label: 'Mythic',    glow: true },
};

function rarityGlow(color, strong = false) {
  const a = strong ? 'cc' : '70';
  const b = strong ? '55' : '28';
  return `0 0 10px 2px ${color}${a}, 0 0 28px 6px ${color}${b}`;
}

const CRATE_DEFS = {
  supply:    { name: 'Jesters Crate',   price: 100,  desc: 'Common adventuring goods',    img: 'images/Jester.png'    },
  war:       { name: 'Queens Crate',    price: 250,  desc: 'Battlefield-grade equipment', img: 'images/Queen.png'     },
  delphinad: { name: 'Ancestral Crate', price: 750,  desc: 'Ancient Delphinad relics',    img: 'images/Ancestral.png' },
};

const CRATE_ITEMS = {
  supply: [
    { name: 'Bait Worm',               rarity: 'grand',  value: 30,   icon: '◉',  weight: 32 },
    { name: 'Iron Ore',                rarity: 'grand',  value: 50,   icon: '◈',  weight: 26 },
    { name: 'Lumber',                  rarity: 'grand',  value: 40,   icon: '⬡',  weight: 20 },
    { name: 'Silver Ingot',            rarity: 'rare',   value: 120,  icon: '◆',  weight: 12 },
    { name: 'Mysterious Garden Powder',rarity: 'arcane', value: 300,  icon: '✦',  weight: 6  },
    { name: 'Thunderstruck Log',       rarity: 'heroic', value: 600,  icon: '⚡', weight: 3  },
    { name: 'Thunderstruck Tree',      rarity: 'unique', value: 1600, icon: '⚡', weight: 1  },
  ],
  war: [
    { name: 'Bait Worm',               rarity: 'grand',     value: 65,   icon: '◉',  weight: 30 },
    { name: 'Silver Ingot',            rarity: 'rare',      value: 120,  icon: '◆',  weight: 24 },
    { name: 'Mysterious Garden Powder',rarity: 'arcane',    value: 200,  icon: '✦',  weight: 20 },
    { name: 'Thunderstruck Log',       rarity: 'heroic',    value: 375,  icon: '⚡', weight: 13 },
    { name: 'Thunderstruck Tree',      rarity: 'unique',    value: 560,  icon: '⚡', weight: 8  },
    { name: 'Lucky Sunpoint',                   rarity: 'celestial', value: 1000, icon: '★',  weight: 4  },
    { name: 'Resplendent Weapon Regrade Scroll', rarity: 'divine',   value: 1500, icon: '☀', weight: 1  },
  ],
  delphinad: [
    { name: 'Mysterious Garden Powder',rarity: 'arcane',    value: 190,  icon: '✦',  weight: 28 },
    { name: 'Thunderstruck Log',       rarity: 'heroic',    value: 325,  icon: '⚡', weight: 22 },
    { name: 'Thunderstruck Tree',      rarity: 'unique',    value: 560,  icon: '⚡', weight: 18 },
    { name: 'Lucky Sunpoint',                   rarity: 'celestial', value: 940,  icon: '★',  weight: 14 },
    { name: 'Resplendent Weapon Regrade Scroll', rarity: 'divine',   value: 1690, icon: '☀', weight: 10 },
    { name: 'Merchant Schooner',   rarity: 'legendary', value: 2340, icon: '☀', weight: 6  },
    { name: 'S200 Rampage',        rarity: 'mythic',    value: 3750, icon: '⚔', weight: 2  },
  ],
};

const ITEM_W    = 112;
const ITEM_GAP  = 8;
const STRIDE    = ITEM_W + ITEM_GAP;
const WINNER_IDX = 52;
const STRIP_PAD  = 8;
const SPIN_MS    = 9000;

function Crate({ balance, apiFetch, onBack, onBalanceChange }) {
  const { useState, useRef, useEffect } = React;

  const [selected,  setSelected]  = useState('supply');
  const [phase,     setPhase]     = useState('idle');   // idle | spinning | done
  const [strip,     setStrip]     = useState([]);
  const [result,    setResult]    = useState(null);     // { item, net }
  const [history,   setHistory]   = useState([]);
  const [showInfo,  setShowInfo]  = useState(false);
  const [err,       setErr]       = useState('');

  const viewportRef = useRef(null);
  const stripRef    = useRef(null);

  // RAF loop with quintic ease-out — same feel as the roulette wheel
  useEffect(() => {
    if (phase !== 'spinning' || !stripRef.current || !viewportRef.current) return;
    const el    = stripRef.current;
    const viewW = viewportRef.current.offsetWidth;
    const finalX = STRIP_PAD + WINNER_IDX * STRIDE + ITEM_W / 2 - viewW / 2;

    el.style.transition = 'none';
    el.style.transform  = 'translateX(0)';

    const t0 = performance.now();
    let rafId;
    let prevItemIdx = -1;
    function frame(now) {
      const raw    = Math.min((now - t0) / SPIN_MS, 1);
      const eased  = 1 - Math.pow(1 - raw, 5);
      const currentX = finalX * eased;
      el.style.transform = `translateX(-${currentX}px)`;

      const itemIdx = Math.floor(currentX / STRIDE);
      if (itemIdx !== prevItemIdx) {
        window.SoundFX?.tick();
        prevItemIdx = itemIdx;
      }

      if (raw < 1) rafId = requestAnimationFrame(frame);
    }
    rafId = requestAnimationFrame(frame);
    return () => cancelAnimationFrame(rafId);
  }, [phase, strip]);

  async function openCrate() {
    setErr('');
    const def = CRATE_DEFS[selected];
    if (balance < def.price) { setErr('Insufficient balance'); return; }

    let data;
    try {
      data = await apiFetch('/api/game/crate/open', { crateId: selected });
    } catch (e) { setErr(e.message); return; }

    setResult(null);
    setStrip(data.strip);
    setPhase('spinning');

    setTimeout(() => {
      setPhase('done');
      setResult({ item: data.item, net: data.net });
      setHistory(h => [{ crate: selected, item: data.item, net: data.net }, ...h.slice(0, 19)]);
      onBalanceChange(data.balance);
      if (data.net >= 0) window.SoundFX?.win(); else window.SoundFX?.bust();
    }, SPIN_MS + 200);
  }

  function playAgain() {
    setPhase('idle');
    setResult(null);
    setStrip([]);
    if (stripRef.current) stripRef.current.style.transform = 'translateX(0)';
  }

  const def   = CRATE_DEFS[selected];
  const busy  = phase === 'spinning';
  const rInfo = result ? (RARITY[result.item.rarity] || RARITY.grand) : null;

  return (
    <div className="game-panel game-panel--wide" data-game-view="crate">
      <div className="game-panel-header">
        <button className="btn-back" onClick={onBack}>Lobby</button>
        <div>
          <h1 className="game-panel-title">Crate Unboxer</h1>
          <div className="game-panel-subtitle">·❦· The Sealed Vault ·❦·</div>
        </div>
        <div className="game-panel-meta"><span>10 Rarities</span></div>
      </div>

      {/* Crate selector */}
      <div className="crate-selector">
        {Object.entries(CRATE_DEFS).map(([id, c]) => (
          <button
            key={id}
            className={`crate-btn${selected === id ? ' active' : ''}`}
            onClick={() => { if (!busy && phase !== 'done') { window.SoundFX?.chip(); setSelected(id); } }}
            disabled={busy || phase === 'done'}
          >
            <img src={c.img} alt={c.name} className="crate-btn-img" />
            <div className="crate-btn-name">{c.name}</div>
            <div className="crate-btn-price">{c.price.toLocaleString()} G</div>
            <div className="crate-btn-desc">{c.desc}</div>
          </button>
        ))}
      </div>

      {/* Info toggle */}
      <button className="crate-info-toggle" onClick={() => setShowInfo(v => !v)}>
        Crate Contents {showInfo ? '▴' : '▾'}
      </button>

      {showInfo && (() => {
        const items = CRATE_ITEMS[selected];
        const total = items.reduce((s, i) => s + i.weight, 0);
        return (
          <div className="crate-info-panel">
            <div className="crate-info-header">
              <span>Item</span>
              <span>Rarity</span>
              <span>Chance</span>
              <span>Value</span>
            </div>
            {items.map((item, i) => {
              const r = RARITY[item.rarity] || RARITY.grand;
              const chance = (item.weight / total * 100).toFixed(1);
              return (
                <div key={i} className="crate-info-row" style={{ borderLeftColor: r.color, boxShadow: r.glow ? `inset 3px 0 8px -2px ${r.color}55` : undefined }}>
                  <span className="crate-info-item">
                    <span className="crate-info-icon">{item.icon}</span>
                    {item.name}
                  </span>
                  <span className="crate-info-rarity" style={{ color: r.color, textShadow: r.glow ? `0 0 8px ${r.color}` : undefined }}>{r.label}</span>
                  <span className="crate-info-chance">{chance}%</span>
                  <span className="crate-info-value">{item.value.toLocaleString()} G</span>
                </div>
              );
            })}
          </div>
        );
      })()}

      {/* Strip viewport — always mounted so ref is valid */}
      <div className="crate-viewport" ref={viewportRef}>
        <div className="crate-tick" />
        <div className="crate-strip-inner" ref={stripRef}>
          {strip.map((item, i) => {
            const r = RARITY[item.rarity] || RARITY.normal;
            const isWinner = phase === 'done' && i === WINNER_IDX;
            return (
              <div
                key={i}
                className={`crate-item${r.glow ? ' crate-item--glow' : ''}${isWinner ? ' crate-item-winner' : ''}`}
                style={{ '--item-color': r.color, boxShadow: r.glow ? rarityGlow(r.color) : undefined }}
              >
                <div className="crate-item-icon">{item.icon}</div>
                <div className="crate-item-name" style={{ color: r.color }}>{item.name}</div>
                <div className="crate-item-rarity" style={{ color: r.color }}>{r.label}</div>
              </div>
            );
          })}
          {strip.length === 0 && (
            <div className="crate-strip-placeholder">Select a crate and open it</div>
          )}
        </div>
      </div>

      {/* Result card */}
      {phase === 'done' && result && (
        <div className="crate-result" style={{ borderColor: rInfo.color, boxShadow: rInfo.glow ? rarityGlow(rInfo.color, true) : undefined }}>
          <div className="crate-result-rarity" style={{ color: rInfo.color }}>{rInfo.label}</div>
          <div className="crate-result-icon">{result.item.icon}</div>
          <div className="crate-result-name" style={{ color: rInfo.color }}>{result.item.name}</div>
          <div className="crate-result-value">{result.item.value.toLocaleString()} G</div>
          <div className={`crate-result-net ${result.net >= 0 ? 'pos' : 'neg'}`}>
            {result.net >= 0 ? '+' : ''}{result.net.toLocaleString()} G net
          </div>
        </div>
      )}

      {/* Controls */}
      <div className="bet-controls">
        {phase === 'idle' && (
          <button className="btn btn-primary btn-lg" onClick={() => { window.SoundFX?.chip(); openCrate(); }}>
            Open — {def.price.toLocaleString()} G
          </button>
        )}
        {phase === 'spinning' && (
          <button className="btn btn-lg" disabled>Opening…</button>
        )}
        {phase === 'done' && (
          <button className="btn btn-primary btn-lg" onClick={() => { window.SoundFX?.chip(); playAgain(); }}>Open Another</button>
        )}
      </div>
      {err && <p style={{ color: 'var(--garnet)', fontSize: 12, marginTop: 10 }}>{err}</p>}

      {/* History */}
      {history.length > 0 && (
        <div style={{ marginTop: 20 }}>
          <div className="section-header">
            <span className="section-title">Recent Crates</span>
            <div className="section-line" />
          </div>
          <div className="history-feed">
            {history.map((h, i) => {
              const r = RARITY[h.item.rarity] || RARITY.normal;
              return (
                <div key={i} className="history-item">
                  <span className="history-game">{CRATE_DEFS[h.crate].name}</span>
                  <span className="history-bet" style={{ color: r.color }}>{h.item.name}</span>
                  <span className={`history-result ${h.net > 0 ? 'pos' : h.net < 0 ? 'neg' : 'zero'}`}>
                    {h.net > 0 ? '+' : ''}{h.net.toLocaleString()} G
                  </span>
                </div>
              );
            })}
          </div>
        </div>
      )}
    </div>
  );
}
