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

// ── Global State ──────────────────────────────────────────────────────────────

let currentGuildId = null;
let sessionId = null;

// ── Session Management ────────────────────────────────────────────────────────

function getSessionId() {
  if (sessionId) return sessionId;
  
  // Check URL params
  const params = new URLSearchParams(window.location.search);
  const urlSessionId = params.get('session_id');
  if (urlSessionId) {
    sessionId = urlSessionId;
    localStorage.setItem('dashboard_session_id', urlSessionId);
    // Clean URL
    window.history.replaceState({}, document.title, window.location.pathname);
    return urlSessionId;
  }
  
  // Check localStorage
  const storedSessionId = localStorage.getItem('dashboard_session_id');
  if (storedSessionId) {
    sessionId = storedSessionId;
    return storedSessionId;
  }
  
  return null;
}

function clearSession() {
  sessionId = null;
  localStorage.removeItem('dashboard_session_id');
}

// ── API Cache ─────────────────────────────────────────────────────────────────

const apiCache = new Map();
const CACHE_DURATION = 3 * 60 * 1000; // 3 minutes in milliseconds

function getCacheKey(path, guildId) {
  return `${guildId || 'default'}:${path}`;
}

function getCachedData(key) {
  const cached = apiCache.get(key);
  if (!cached) return null;
  
  const now = Date.now();
  if (now - cached.timestamp > CACHE_DURATION) {
    apiCache.delete(key);
    return null;
  }
  
  return cached.data;
}

function setCachedData(key, data) {
  apiCache.set(key, {
    data,
    timestamp: Date.now()
  });
}

// Clear cache when guild changes
function clearCache() {
  apiCache.clear();
}

// ── API ───────────────────────────────────────────────────────────────────────

async function api(path, skipCache = false) {
  // Add guild_id to query params if set
  const separator = path.includes('?') ? '&' : '?';
  let fullPath = currentGuildId ? `/api${path}${separator}guild_id=${currentGuildId}` : `/api${path}`;
  
  // Add session_id if available
  const sid = getSessionId();
  if (sid) {
    const sep2 = fullPath.includes('?') ? '&' : '?';
    fullPath += `${sep2}session_id=${sid}`;
  }
  
  // Check cache first (unless skipCache is true)
  if (!skipCache) {
    const cacheKey = getCacheKey(path, currentGuildId);
    const cached = getCachedData(cacheKey);
    if (cached) {
      return cached;
    }
  }
  
  // Fetch from server
  const headers = {};
  if (sid) {
    headers['X-Session-ID'] = sid;
  }
  
  const r = await fetch(fullPath, { headers });
  
  // Handle auth errors
  if (r.status === 401 || r.status === 403) {
    const data = await r.json();
    if (data.requiresAuth) {
      clearSession();
      window.location.reload();
      throw new Error('Authentication required');
    }
  }
  
  if (!r.ok) throw new Error(await r.text());
  const data = await r.json();
  
  // Cache the result
  const cacheKey = getCacheKey(path, currentGuildId);
  setCachedData(cacheKey, data);
  
  return data;
}

// ── Utils ─────────────────────────────────────────────────────────────────────

const fmt   = n  => Number(n ?? 0).toLocaleString('en-US');
const fmtD  = s  => s ? s.slice(0, 16) : '—';
const trunc = (s, n) => s && s.length > n ? s.slice(0, n - 1) + '…' : (s ?? '');


// ── Shared components ─────────────────────────────────────────────────────────

function Spinner() {
  return (
    <div className="flex justify-center items-center py-16">
      <div className="w-8 h-8 border-4 border-violet-500 border-t-transparent rounded-full animate-spin" />
    </div>
  );
}

function StatCard({ label, value, sub, color = 'violet' }) {
  const accent = color === 'teal' ? 'text-teal-400' : 'text-violet-400';
  return (
    <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
      <p className="text-gray-400 text-xs uppercase tracking-wide">{label}</p>
      <p className={`text-2xl font-bold mt-1 ${accent}`}>{value}</p>
      {sub && <p className="text-gray-500 text-xs mt-1">{sub}</p>}
    </div>
  );
}

function Pagination({ page, total, pageSize, onChange }) {
  const pages = Math.max(1, Math.ceil(total / pageSize));
  return (
    <div className="flex items-center justify-between text-sm text-gray-400 mt-2">
      <button onClick={() => onChange(page - 1)} disabled={page <= 1}
        className="px-4 py-2 bg-gray-900 rounded-lg border border-gray-800 disabled:opacity-30 hover:border-gray-600 transition-colors">
        ← Prev
      </button>
      <span className="text-gray-500">Page {page} of {pages} &nbsp;·&nbsp; {fmt(total)} total</span>
      <button onClick={() => onChange(page + 1)} disabled={page >= pages}
        className="px-4 py-2 bg-gray-900 rounded-lg border border-gray-800 disabled:opacity-30 hover:border-gray-600 transition-colors">
        Next →
      </button>
    </div>
  );
}

// ── Chart wrappers ────────────────────────────────────────────────────────────

function BarChart({ data, label, color = '#8b5cf6', horizontal = false }) {
  const ref  = useRef(null);
  const inst = useRef(null);

  useEffect(() => {
    if (!data?.length || !ref.current) return;
    inst.current?.destroy();
    inst.current = new Chart(ref.current, {
      type: 'bar',
      data: {
        labels: data.map(d => d.week || d.label),
        datasets: [{ label, data: data.map(d => d.count ?? d.value), backgroundColor: color, borderRadius: 4, borderSkipped: false }],
      },
      options: {
        indexAxis: horizontal ? 'y' : 'x',
        responsive: true,
        plugins: { legend: { display: false } },
        scales: {
          x: { ticks: { color: '#6b7280', maxRotation: 45 }, grid: { color: '#1f2937' } },
          y: { ticks: { color: '#6b7280' },                  grid: { color: '#1f2937' } },
        },
      },
    });
    return () => inst.current?.destroy();
  }, [data]);

  return <canvas ref={ref} />;
}

// ── Overview ──────────────────────────────────────────────────────────────────

function Overview({ onNavigate }) {
  const [data,  setData]  = useState(null);
  const [chart, setChart] = useState(null);

  useEffect(() => {
    Promise.all([api('/overview'), api('/activity/chart')])
      .then(([o, c]) => { setData(o); setChart(c); });
  }, []);

  if (!data) return <Spinner />;

  const pvpTotal  = data.reportWins + data.reportDraws + data.reportLosses;
  const winRate   = pvpTotal > 0 ? ((data.reportWins / pvpTotal) * 100).toFixed(1) : 0;
  const topAP     = data.topPlayers.length > 0 ? data.topPlayers[0].total_ap : 0;

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Overview</h1>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <StatCard label="Active Players"     value={fmt(data.activePlayersCurrentSession)} sub="current session" />
        <StatCard label="Berries Consumed"   value={fmt(data.totalBerriesConsumed)}     sub={`${fmt(data.berriesConsumedThisWeek)} this week`} />
        <StatCard label="Total Paid Out"     value={`${fmt(Math.round(data.totalCrystalsPaid))} 💎`} sub={`${fmt(Math.round(data.crystalsPaidBerries))} berries · ${fmt(Math.round(data.crystalsPaidShares))} shares`} />
        <StatCard label="Total Shares"       value={fmt(data.totalShares)}          sub="non-reverted" />
        <StatCard label="PvP Reports"        value={fmt(data.reportCount)}          sub={`${winRate}% win rate (excl. Tribulation)`} color="teal" />
        <StatCard label="PvP Record"         value={`${data.reportWins}W · ${data.reportDraws}D · ${data.reportLosses}L`} sub="all time" color="teal" />
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
          <h2 className="text-white font-semibold mb-4 text-sm">Berry Submissions · Last 4 Weeks</h2>
          {chart && <BarChart data={chart} label="Submissions" />}
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800">
          <h2 className="text-white font-semibold text-sm px-5 py-4 border-b border-gray-800">Top 10 Players by AP</h2>
          {data.topPlayers.length === 0 ? (
            <p className="px-5 py-4 text-gray-600 text-sm">No report data yet.</p>
          ) : (
            <div className="divide-y divide-gray-800">
              {data.topPlayers.map((p, i) => {
                const pct = topAP > 0 ? (p.total_ap / topAP) * 100 : 0;
                return (
                  <div key={p.user_id} className="px-5 py-3 flex items-center gap-3">
                    <span className="text-gray-600 text-xs font-mono w-5 shrink-0">{i + 1}</span>
                    <span className="text-white text-sm flex-1 truncate">{p.username}</span>
                    <div className="w-24 bg-gray-800 rounded-full h-1.5 shrink-0">
                      <div className="bg-violet-500 h-1.5 rounded-full" style={{ width: `${pct}%` }} />
                    </div>
                    <span className="text-violet-300 text-xs font-mono w-16 text-right shrink-0">{fmt(Math.round(p.total_ap))} AP</span>
                  </div>
                );
              })}
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// ── Currency Owed ─────────────────────────────────────────────────────────────

function CurrencyOwed({ onNavigate }) {
  const [data, setData] = useState(null);
  const [search, setSearch] = useState('');
  const [owedOnly, setOwedOnly] = useState(true);

  useEffect(() => { api('/currency-owed').then(setData); }, []);
  if (!data) return <Spinner />;
  if (!data.available) return <div className="text-gray-500 text-center py-16">Currency tracking not available</div>;

  const owedCount = data.users.filter(u => u.totalCrystals > 0 || Object.values(u.balances).some(b => b > 0)).length;
  const rows = data.users.filter(u => {
    const matchesSearch = u.username.toLowerCase().includes(search.toLowerCase());
    const hasBalance = u.totalCrystals > 0 || Object.values(u.balances).some(b => b > 0);
    return matchesSearch && (!owedOnly || hasBalance);
  });

  // Get all unique currencies (excluding crystals which we show separately)
  const otherCurrencies = data.currencies.filter(c => c.toLowerCase() !== 'crystals');

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold text-white">💎 Currency Owed</h1>
        <p className="text-gray-500 text-sm mt-1">Track all currency balances owed to players</p>
      </div>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <StatCard label="Members with Balance" value={fmt(owedCount)} sub="have unpaid currency" />
        <StatCard label="Berry Crystals Owed" value={`${fmt(Math.round(data.totals.berryCrystals || 0))} 💎`} sub="from submissions" />
        {data.totals.crystals > 0 && (
          <StatCard label="Share Crystals Owed" value={`${fmt(Math.round(data.totals.crystals || 0))} 💎`} sub="from share payouts" />
        )}
        {otherCurrencies.map(curr => (
          data.totals[curr] > 0 && (
            <StatCard key={curr} label={`${curr} Owed`} value={fmt(Math.round(data.totals[curr]))} sub={`total ${curr}`} color="teal" />
          )
        ))}
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 flex flex-col">
        <div className="p-4 border-b border-gray-800 flex gap-3 items-center">
          <input
            className="flex-1 bg-gray-950 text-white rounded-lg px-4 py-2 text-sm placeholder-gray-600 border border-gray-700 focus:outline-none focus:border-violet-500"
            placeholder="Search members…"
            value={search}
            onChange={e => setSearch(e.target.value)}
          />
          <label className="flex items-center gap-2 text-sm text-gray-400 cursor-pointer whitespace-nowrap select-none">
            <input type="checkbox" checked={owedOnly} onChange={e => setOwedOnly(e.target.checked)} className="accent-violet-500" />
            Owed only
          </label>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">Member</th>
                <th className="px-4 py-3 text-right">💎 Crystals from Berries</th>
                {data.totals.crystals > 0 && <th className="px-4 py-3 text-right">💰 Crystals from Share</th>}
                {otherCurrencies.map(curr => (
                  <th key={curr} className="px-4 py-3 text-right">{curr}</th>
                ))}
                <th className="px-4 py-3 text-right text-violet-400">Total Crystals</th>
              </tr>
            </thead>
            <tbody>
              {rows.map(u => (
                <tr key={u.user_id}
                  className="border-b border-gray-800/60 hover:bg-gray-800/40 cursor-pointer transition-colors"
                  onClick={() => onNavigate('user', { userId: u.user_id, username: u.username })}>
                  <td className="px-4 py-2.5 text-white font-medium">{u.username}</td>
                  <td className={`px-4 py-2.5 text-right font-semibold ${u.berryCrystals > 0 ? 'text-violet-300' : 'text-gray-600'}`}>
                    {fmt(Math.round(u.berryCrystals))}
                  </td>
                  {data.totals.crystals > 0 && (
                    <td className={`px-4 py-2.5 text-right ${(u.balances.crystals || 0) > 0 ? 'text-yellow-300' : 'text-gray-600'}`}>
                      {fmt(Math.round(u.balances.crystals || 0))}
                    </td>
                  )}
                  {otherCurrencies.map(curr => (
                    <td key={curr} className={`px-4 py-2.5 text-right ${(u.balances[curr] || 0) > 0 ? 'text-teal-300' : 'text-gray-600'}`}>
                      {fmt(Math.round(u.balances[curr] || 0))}
                    </td>
                  ))}
                  <td className={`px-4 py-2.5 text-right font-bold ${u.totalCrystals > 0 ? 'text-white' : 'text-gray-600'}`}>
                    {fmt(Math.round(u.totalCrystals))}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="px-4 py-3 border-t border-gray-800 text-gray-600 text-xs">
          {rows.length} member{rows.length !== 1 ? 's' : ''}
        </div>
      </div>
    </div>
  );
}

// ── Crystals Owed (Legacy - redirects to Currency Owed) ──────────────────────

function CrystalsOwed({ onNavigate }) {
  return <CurrencyOwed onNavigate={onNavigate} />;
}

// ── User Profile ──────────────────────────────────────────────────────────────

function UserProfile({ userId, onBack }) {
  const [data, setData] = useState(null);
  useEffect(() => { api(`/users/${userId}`).then(setData); }, [userId]);
  if (!data) return <Spinner />;

  const { aggregate, berryTypes: bts, crystals, totalPaid, recentHistory, payments, mazeFavorite, weeklyActivity } = data;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <button onClick={onBack} className="text-gray-500 hover:text-white transition-colors text-sm">← Back</button>
        <h1 className="text-2xl font-bold text-white">{data.username}</h1>
      </div>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <StatCard label="Berry Crystals Owed" value={fmt(Math.round(crystals))}                sub="from submissions" />
        {data.shareBalance > 0 && <StatCard label="Share Balance Owed" value={`${fmt(Math.round(data.shareBalance))} 💎`} sub="unpaid share payout" />}
        <StatCard label="Crystals Paid"       value={fmt(Math.round(totalPaid))}              sub="all time" />
        <StatCard label="Submissions"         value={fmt(aggregate.submission_count)}          sub={`first: ${(aggregate.first_submission ?? '—').slice(0,10)}`} />
        <StatCard label="Favourite Maze"      value={trunc(mazeFavorite?.maze_name ?? '—', 20)} sub="most played" />
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
          <h2 className="text-white font-semibold text-sm mb-4">Monthly Activity · Last 4 Weeks</h2>
          <BarChart data={weeklyActivity} label="Submissions" />
        </div>
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
          <h2 className="text-white font-semibold text-sm mb-4">All-Time Berry Totals</h2>
          <div className="space-y-3">
            {bts.map(bt => {
              const ever = aggregate.totalsEver[bt.id] ?? 0;
              const curr = data.totals[bt.id] ?? 0;
              return (
                <div key={bt.id}>
                  <div className="flex justify-between text-sm mb-1">
                    <span className="text-gray-400">{bt.name} <span className="text-gray-600">({bt.abbr})</span></span>
                    <span className="text-white">{fmt(ever)} <span className="text-gray-600 text-xs">ever</span> · {fmt(curr)} <span className="text-gray-600 text-xs">owed</span></span>
                  </div>
                </div>
              );
            })}
            <div className="pt-2 border-t border-gray-800 flex justify-between text-sm">
              <span className="text-gray-400">Total crystals ever</span>
              <span className="text-violet-400 font-semibold">{fmt(aggregate.crystalsEver)} 💎</span>
            </div>
          </div>
        </div>
      </div>

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <div className="bg-gray-900 rounded-xl border border-gray-800">
          <h2 className="text-white font-semibold text-sm px-5 py-4 border-b border-gray-800">Recent Submissions</h2>
          <div className="divide-y divide-gray-800">
            {recentHistory.length === 0 && <p className="px-5 py-4 text-gray-600 text-sm">No submissions yet.</p>}
            {recentHistory.map(h => (
              <div key={h.id} className="px-5 py-3">
                <div className="flex justify-between items-center">
                  <span className="text-gray-500 font-mono text-xs">{fmtD(h.timestamp)}</span>
                  {h.maze_name && <span className="text-gray-600 text-xs">{h.maze_name}</span>}
                </div>
                <div className="text-white text-sm mt-0.5">
                  {h.amounts.filter(a => a.amount > 0).map(a => `+${a.amount} ${a.abbr}`).join(' · ') || '—'}
                </div>
              </div>
            ))}
          </div>
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800">
          <h2 className="text-white font-semibold text-sm px-5 py-4 border-b border-gray-800">Payment History</h2>
          <div className="divide-y divide-gray-800">
            {payments.length === 0 && <p className="px-5 py-4 text-gray-600 text-sm">No payments yet.</p>}
            {payments.map(p => (
              <div key={p.id} className="px-5 py-3">
                <div className="flex justify-between items-center">
                  <span className="text-violet-300 font-semibold text-sm">{fmt(p.crystals_paid)} 💎</span>
                  <span className="text-gray-500 font-mono text-xs">{fmtD(p.timestamp)}</span>
                </div>
                <div className="text-gray-500 text-xs mt-0.5">paid by {p.paid_by_username}</div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

// ── Activity ──────────────────────────────────────────────────────────────────

function Activity() {
  const [data,  setData]  = useState(null);
  const [page,  setPage]  = useState(1);
  const [from,  setFrom]  = useState('');
  const [to,    setTo]    = useState('');
  const [maze,  setMaze]  = useState('');

  const load = useCallback(() => {
    const p = new URLSearchParams({ page });
    if (from) p.set('from', from);
    if (to)   p.set('to',   to);
    if (maze) p.set('maze', maze);
    api(`/activity?${p}`).then(setData);
  }, [page, from, to, maze]);

  useEffect(() => { load(); }, [load]);

  const reset = () => { setFrom(''); setTo(''); setMaze(''); setPage(1); };

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Berry Submissions Feed</h1>

      <div className="bg-gray-900 rounded-xl border border-gray-800 p-4 flex flex-wrap gap-3 items-end">
        <div>
          <label className="text-gray-500 text-xs block mb-1">From</label>
          <input type="date" value={from} onChange={e => { setFrom(e.target.value); setPage(1); }}
            className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
        </div>
        <div>
          <label className="text-gray-500 text-xs block mb-1">To</label>
          <input type="date" value={to} onChange={e => { setTo(e.target.value); setPage(1); }}
            className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
        </div>
        <div>
          <label className="text-gray-500 text-xs block mb-1">Maze</label>
          <input value={maze} onChange={e => { setMaze(e.target.value); setPage(1); }}
            placeholder="Filter maze…"
            className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
        </div>
        <button onClick={reset} className="px-3 py-2 text-sm text-gray-500 hover:text-white bg-gray-800 rounded-lg border border-gray-700 hover:border-gray-500 transition-colors">
          Clear
        </button>
      </div>

      {!data ? <Spinner /> : (
        <>
          <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                    <th className="px-4 py-3 text-left">Time</th>
                    <th className="px-4 py-3 text-left">Member</th>
                    <th className="px-4 py-3 text-left">Berries</th>
                    <th className="px-4 py-3 text-left">Maze</th>
                  </tr>
                </thead>
                <tbody>
                  {data.rows.map(r => (
                    <tr key={r.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                      <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(r.timestamp)}</td>
                      <td className="px-4 py-2.5 text-white">{r.username}</td>
                      <td className="px-4 py-2.5 text-gray-300">
                        {r.amounts.filter(a => a.amount > 0).map(a => `+${a.amount} ${a.abbr}`).join(' · ') || '—'}
                      </td>
                      <td className="px-4 py-2.5 text-gray-500">{r.maze_name ?? '—'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          <Pagination page={data.page} total={data.total} pageSize={data.pageSize} onChange={setPage} />
        </>
      )}
    </div>
  );
}

// ── Maze Stats ────────────────────────────────────────────────────────────────

function WinRateBar({ wins, draws, losses }) {
  const total = wins + draws + losses;
  if (total === 0) return <span className="text-gray-600 text-xs">no data</span>;
  const wp = (wins  / total) * 100;
  const dp = (draws / total) * 100;
  const lp = (losses / total) * 100;
  return (
    <div className="flex items-center gap-2">
      <div className="flex-1 flex rounded-full overflow-hidden h-2">
        {wp > 0 && <div style={{ width: `${wp}%` }} className="bg-green-500" />}
        {dp > 0 && <div style={{ width: `${dp}%` }} className="bg-yellow-500" />}
        {lp > 0 && <div style={{ width: `${lp}%` }} className="bg-red-500" />}
      </div>
      <span className="text-green-400 text-xs font-mono w-10 text-right">{wp.toFixed(0)}%</span>
    </div>
  );
}

function MazeStats() {
  const [data, setData] = useState(null);
  useEffect(() => { api('/maze-stats').then(setData); }, []);
  if (!data) return <Spinner />;

  if (!data.available) {
    return (
      <div className="space-y-6">
        <h1 className="text-2xl font-bold text-white">Maze Stats</h1>
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-8 text-center text-gray-500">
          Report data not available in this database yet.
        </div>
      </div>
    );
  }

  const totalWins   = data.mazes.reduce((s, m) => s + m.wins,   0);
  const totalDraws  = data.mazes.reduce((s, m) => s + m.draws,  0);
  const totalLosses = data.mazes.reduce((s, m) => s + m.losses, 0);
  const totalReports = totalWins + totalDraws + totalLosses;
  const overallWR   = totalReports > 0 ? ((totalWins / totalReports) * 100).toFixed(1) : 0;

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Maze Stats</h1>

      <div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
        <StatCard label="Overall Win Rate" value={`${overallWR}%`} sub={`${fmt(totalWins)}W · ${fmt(totalDraws)}D · ${fmt(totalLosses)}L`} />
        <StatCard label="Mazes Tracked"   value={fmt(data.mazes.length)} sub="unique PvP mazes" />
        <StatCard label="Unique Players"  value={fmt(data.mazes.reduce((s, m) => Math.max(s, m.unique_players), 0))} sub="peak per maze" />
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
        <h2 className="text-white font-semibold text-sm mb-4">Win Rate by Maze</h2>
        <BarChart
          data={data.mazes.map(m => ({ label: trunc(m.maze_name, 16), value: m.win_rate }))}
          label="Win Rate %"
          color="#22c55e"
        />
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">Maze</th>
                <th className="px-4 py-3 text-right">Players</th>
                <th className="px-4 py-3 text-right text-green-600">W</th>
                <th className="px-4 py-3 text-right text-yellow-600">D</th>
                <th className="px-4 py-3 text-right text-red-600">L</th>
                <th className="px-4 py-3 text-left" style={{ minWidth: '160px' }}>Win Rate</th>
              </tr>
            </thead>
            <tbody>
              {data.mazes.map(m => (
                <tr key={m.maze_name} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-white font-medium">{m.maze_name}</td>
                  <td className="px-4 py-2.5 text-right text-gray-400">{fmt(m.unique_players)}</td>
                  <td className="px-4 py-2.5 text-right text-green-400">{m.wins}</td>
                  <td className="px-4 py-2.5 text-right text-yellow-400">{m.draws}</td>
                  <td className="px-4 py-2.5 text-right text-red-400">{m.losses}</td>
                  <td className="px-4 py-2.5"><WinRateBar wins={m.wins} draws={m.draws} losses={m.losses} /></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ── Player Stats ──────────────────────────────────────────────────────────────

function PlayerProfile({ userId, username, onBack }) {
  const [report, setReport] = useState(null);
  const [berry,  setBerry]  = useState(null);

  useEffect(() => {
    api(`/player-stats/${userId}`).then(setReport);
    api(`/users/${userId}`).then(setBerry).catch(() => setBerry(null));
  }, [userId]);

  if (!report) return <Spinner />;

  const s = report.summary;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <button onClick={onBack} className="text-gray-500 hover:text-white transition-colors text-sm">← Back</button>
        <h1 className="text-2xl font-bold text-white">{username}</h1>
      </div>

      <div className="grid grid-cols-2 lg:grid-cols-4 gap-4">
        <StatCard label="Win Rate"     value={`${s?.win_rate ?? 0}%`}   sub={`${s?.wins ?? 0}W · ${s?.draws ?? 0}D · ${s?.losses ?? 0}L`} />
        <StatCard label="Total AP"     value={fmt(s?.total_ap ?? 0)}    sub="from reports" />
        {berry && <StatCard label="Crystals Owed" value={fmt(berry.crystals)} sub="berry balance" />}
      </div>

      {s && (s.wins + s.draws + s.losses) > 0 && (
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
          <h2 className="text-white font-semibold text-sm mb-3">Overall Record</h2>
          <WinRateBar wins={s.wins} draws={s.draws} losses={s.losses} />
          <div className="flex gap-6 mt-3 text-sm">
            <span className="text-green-400"><span className="font-bold">{s.wins}</span> <span className="text-gray-500">wins</span></span>
            <span className="text-yellow-400"><span className="font-bold">{s.draws}</span> <span className="text-gray-500">draws</span></span>
            <span className="text-red-400"><span className="font-bold">{s.losses}</span> <span className="text-gray-500">losses</span></span>
          </div>
        </div>
      )}

      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        <div className="bg-gray-900 rounded-xl border border-gray-800">
          <h2 className="text-white font-semibold text-sm px-5 py-4 border-b border-gray-800">Record by Maze</h2>
          <div className="divide-y divide-gray-800">
            {report.byMaze.length === 0 && <p className="px-5 py-4 text-gray-600 text-sm">No maze data.</p>}
            {report.byMaze.map(m => (
              <div key={m.maze_name} className="px-5 py-3">
                <div className="mb-1.5">
                  <span className="text-white text-sm">{m.maze_name}</span>
                  <span className="text-gray-600 text-xs ml-2">{m.wins}W · {m.draws}D · {m.losses}L</span>
                </div>
                <WinRateBar wins={m.wins} draws={m.draws} losses={m.losses} />
              </div>
            ))}
          </div>
        </div>

        <div className="bg-gray-900 rounded-xl border border-gray-800">
          <h2 className="text-white font-semibold text-sm px-5 py-4 border-b border-gray-800">Recent Reports</h2>
          <div className="divide-y divide-gray-800">
            {report.recentRuns.length === 0 && <p className="px-5 py-4 text-gray-600 text-sm">No reports yet.</p>}
            {report.recentRuns.map((r, i) => (
              <div key={i} className="px-5 py-3 flex justify-between items-center">
                <div>
                  <div className="text-white text-sm">{r.maze_name}</div>
                  <div className="text-gray-500 text-xs font-mono">{fmtD(r.timestamp)}</div>
                </div>
                <div className="flex items-center gap-3">
                  {r.ap_earned > 0 && <span className="text-gray-400 text-xs">+{r.ap_earned} AP</span>}
                  <span className={`text-xs px-2 py-0.5 rounded-full ${
                    r.result === 'win'  ? 'bg-green-900/30 text-green-400' :
                    r.result === 'draw' ? 'bg-yellow-900/30 text-yellow-400' :
                                          'bg-red-900/30 text-red-400'}`}>
                    {r.result}
                  </span>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>
    </div>
  );
}

function PlayerStats({ onNavigate }) {
  const [data,   setData]   = useState(null);
  const [search, setSearch] = useState('');
  const [sort,   setSort]   = useState('win_rate');
  const [dir,    setDir]    = useState('desc');

  useEffect(() => { api('/player-stats').then(setData); }, []);
  if (!data) return <Spinner />;

  if (!data.available) {
    return (
      <div className="space-y-6">
        <h1 className="text-2xl font-bold text-white">Players</h1>
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-8 text-center text-gray-500">
          Report data not available in this database yet.
        </div>
      </div>
    );
  }

  const toggleSort = col => {
    if (sort === col) setDir(d => d === 'desc' ? 'asc' : 'desc');
    else { setSort(col); setDir('desc'); }
  };
  const SortIcon = ({ col }) => sort === col ? (dir === 'asc' ? ' ↑' : ' ↓') : '';

  const rows = data.players
    .filter(p => p.username.toLowerCase().includes(search.toLowerCase()))
    .sort((a, b) => {
      const av = a[sort] ?? 0, bv = b[sort] ?? 0;
      if (typeof av === 'string') return dir === 'asc' ? av.localeCompare(bv) : bv.localeCompare(av);
      return dir === 'asc' ? av - bv : bv - av;
    });

  const topPlayer = data.players.length > 0
    ? [...data.players].sort((a, b) => b.elo - a.elo)[0]
    : null;
  
  // Use guild-level report stats (actual reports, not player participations)
  const guildWins   = data.guildStats?.wins ?? 0;
  const guildDraws  = data.guildStats?.draws ?? 0;
  const guildLosses = data.guildStats?.losses ?? 0;
  const guildReports = guildWins + guildDraws + guildLosses;

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Players</h1>

      <div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
        <StatCard label="Total Players"    value={fmt(data.players.length)} sub="in PvP reports" />
        <StatCard label="Guild Win Rate"   value={guildReports > 0 ? `${((guildWins / guildReports) * 100).toFixed(1)}%` : '—'} sub={`${fmt(guildWins)}W · ${fmt(guildDraws)}D · ${fmt(guildLosses)}L (excl. Tribulation)`} />
        <StatCard label="Top ELO"          value={topPlayer ? fmt(topPlayer.elo) : '—'} sub={topPlayer?.username ?? ''} />
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 flex flex-col">
        <div className="p-4 border-b border-gray-800">
          <input
            className="w-full bg-gray-950 text-white rounded-lg px-4 py-2 text-sm placeholder-gray-600 border border-gray-700 focus:outline-none focus:border-violet-500"
            placeholder="Search players…"
            value={search}
            onChange={e => setSearch(e.target.value)}
          />
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left w-8">#</th>
                <th className="px-4 py-3 text-left cursor-pointer hover:text-gray-300 select-none" onClick={() => toggleSort('username')}>
                  Player<SortIcon col="username" />
                </th>
                <th className="px-4 py-3 text-right text-green-600">W</th>
                <th className="px-4 py-3 text-right text-yellow-600">D</th>
                <th className="px-4 py-3 text-right text-red-600">L</th>
                <th className="px-4 py-3 text-left cursor-pointer hover:text-gray-300 select-none" onClick={() => toggleSort('win_rate')} style={{ minWidth: '180px' }}>
                  Win Rate<SortIcon col="win_rate" />
                </th>
                <th className="px-4 py-3 text-right cursor-pointer hover:text-gray-300 select-none" onClick={() => toggleSort('elo')}>
                  ELO<SortIcon col="elo" />
                </th>
                <th className="px-4 py-3 text-right cursor-pointer hover:text-gray-300 select-none" onClick={() => toggleSort('total_ap')}>
                  AP<SortIcon col="total_ap" />
                </th>
                <th className="px-4 py-3 text-left text-gray-600">Last Report</th>
              </tr>
            </thead>
            <tbody>
              {rows.map((p, i) => (
                <tr key={p.user_id}
                  className="border-b border-gray-800/60 hover:bg-gray-800/40 cursor-pointer transition-colors"
                  onClick={() => onNavigate('player', { userId: p.user_id, username: p.username })}>
                  <td className="px-4 py-2.5 text-gray-600 text-xs font-mono">{i + 1}</td>
                  <td className="px-4 py-2.5 text-white font-medium">{p.username}</td>
                  <td className="px-4 py-2.5 text-right text-green-400">{p.wins}</td>
                  <td className="px-4 py-2.5 text-right text-yellow-400">{p.draws}</td>
                  <td className="px-4 py-2.5 text-right text-red-400">{p.losses}</td>
                  <td className="px-4 py-2.5"><WinRateBar wins={p.wins} draws={p.draws} losses={p.losses} /></td>
                  <td className="px-4 py-2.5 text-right text-cyan-400 font-semibold">{fmt(p.elo)}</td>
                  <td className="px-4 py-2.5 text-right text-violet-300">{fmt(p.total_ap)}</td>
                  <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(p.last_run)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="px-4 py-3 border-t border-gray-800 text-gray-600 text-xs">
          {rows.length} of {data.players.length} players
        </div>
      </div>
    </div>
  );
}

// ── Reports ───────────────────────────────────────────────────────────────────

function Reports() {
  const [data,   setData]   = useState(null);
  const [page,   setPage]   = useState(1);
  const [maze,   setMaze]   = useState('');
  const [result, setResult] = useState('');

  const load = useCallback(() => {
    const p = new URLSearchParams({ page });
    if (maze)   p.set('maze',   maze);
    if (result) p.set('result', result);
    api(`/reports?${p}`).then(setData);
  }, [page, maze, result]);

  useEffect(() => { load(); }, [load]);

  const resultStyle = r => ({
    win:  'bg-green-900/30 text-green-400',
    draw: 'bg-yellow-900/30 text-yellow-400',
    loss: 'bg-red-900/30 text-red-400',
  }[r] ?? 'text-gray-400');

  const resultLabel = r => ({ win: '✅ Win', draw: '🤝 Draw', loss: '❌ Loss' }[r] ?? r);

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Maze Reports</h1>

      <div className="bg-gray-900 rounded-xl border border-gray-800 p-4 flex flex-wrap gap-3">
        <input value={maze} onChange={e => { setMaze(e.target.value); setPage(1); }}
          placeholder="Filter maze…"
          className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
        <select value={result} onChange={e => { setResult(e.target.value); setPage(1); }}
          className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500">
          <option value="">All results</option>
          <option value="win">Win</option>
          <option value="draw">Draw</option>
          <option value="loss">Loss</option>
        </select>
      </div>

      {!data ? <Spinner /> : (
        <>
          <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                    <th className="px-4 py-3 text-left">#</th>
                    <th className="px-4 py-3 text-left">Maze</th>
                    <th className="px-4 py-3 text-left">Result</th>
                    <th className="px-4 py-3 text-left">Status</th>
                    <th className="px-4 py-3 text-right">Players</th>
                    <th className="px-4 py-3 text-left">Created by</th>
                    <th className="px-4 py-3 text-left">Date</th>
                  </tr>
                </thead>
                <tbody>
                  {data.reports.map(r => (
                    <tr key={r.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                      <td className="px-4 py-2.5 text-gray-600 text-xs">#{r.guild_seq ?? '?'}</td>
                      <td className="px-4 py-2.5 text-white">{r.maze_name}</td>
                      <td className="px-4 py-2.5">
                        <span className={`text-xs px-2 py-0.5 rounded-full ${resultStyle(r.result)}`}>{resultLabel(r.result)}</span>
                      </td>
                      <td className="px-4 py-2.5">
                        <span className={`text-xs px-2 py-0.5 rounded-full ${r.status === 'cancelled' ? 'bg-red-900/30 text-red-400' : 'bg-green-900/30 text-green-400'}`}>
                          {r.status}
                        </span>
                      </td>
                      <td className="px-4 py-2.5 text-right text-gray-300">{r.players.length}</td>
                      <td className="px-4 py-2.5 text-gray-400">{r.created_by_name}</td>
                      <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(r.timestamp)}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>
          <Pagination page={data.page} total={data.total} pageSize={data.pageSize} onChange={setPage} />
        </>
      )}
    </div>
  );
}

// ── Bank ──────────────────────────────────────────────────────────────────────

function Bank() {
  const [data,     setData]     = useState(null);
  const [page,     setPage]     = useState(1);
  const [account,  setAccount]  = useState('');
  const [currency, setCurrency] = useState('');
  const [type,     setType]     = useState('');
  const [from,     setFrom]     = useState('');
  const [to,       setTo]       = useState('');

  const load = useCallback(() => {
    const p = new URLSearchParams({ page });
    if (account)  p.set('account', account);
    if (currency) p.set('currency', currency);
    if (type)     p.set('type',     type);
    if (from)     p.set('from',     from);
    if (to)       p.set('to',       to);
    api(`/bank?${p}`).then(setData);
  }, [page, account, currency, type, from, to]);

  useEffect(() => { load(); }, [load]);

  const reset = () => { setAccount(''); setCurrency(''); setType(''); setFrom(''); setTo(''); setPage(1); };

  const txnStyle = t => t.type === 'in' ? 'text-green-400' : 'text-red-400';
  const txnSign  = t => t.type === 'in' ? '+' : '-';

  const sections = {};
  for (const c of (data?.currencies ?? [])) {
    if (!sections[c.section]) sections[c.section] = [];
    sections[c.section].push(c);
  }

  const accountOptions = data ? data.currencies.reduce((acc, c) => {
    if (!acc.find(item => item.name === c.name)) {
      acc.push({ name: c.name, abbr: c.abbr });
    }
    return acc;
  }, []) : [];

  const currencyOptions = data ? [...new Set(data.currencies.map(c => c.abbr))] : [];

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Bank</h1>

      {Object.entries(sections).map(([section, currs]) => (
        <div key={section} className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
          <div className="px-4 py-3 border-b border-gray-800 text-gray-300 font-semibold text-sm">{section}</div>
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                  <th className="px-4 py-3 text-left">Account</th>
                  <th className="px-4 py-3 text-left">Currency</th>
                  <th className="px-4 py-3 text-right">Balance</th>
                  <th className="px-4 py-3 text-right">Rate</th>
                  <th className="px-4 py-3 text-left text-gray-600">Description</th>
                </tr>
              </thead>
              <tbody>
                {currs.map(c => (
                  <tr key={c.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                    <td className="px-4 py-2.5 text-white font-medium">{c.name}</td>
                    <td className="px-4 py-2.5 text-gray-400">{c.abbr}</td>
                    <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">{fmt(c.balance)}</td>
                    <td className="px-4 py-2.5 text-right text-gray-400">×{c.rate}</td>
                    <td className="px-4 py-2.5 text-gray-600 text-xs">{c.description ?? '—'}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      ))}

      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="px-4 py-3 border-b border-gray-800 text-gray-300 font-semibold text-sm">Transactions</div>

        <div className="p-4 border-b border-gray-800 flex flex-wrap gap-3 items-end">
          <div>
            <label className="text-gray-500 text-xs block mb-1">Account</label>
            <select value={account} onChange={e => { setAccount(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500">
              <option value="">All Accounts</option>
              {accountOptions.map(c => <option key={c.name} value={c.name}>{c.name}</option>)}
            </select>
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">Currency</label>
            <select value={currency} onChange={e => { setCurrency(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500">
              <option value="">All Currencies</option>
              {currencyOptions.map(abbr => <option key={abbr} value={abbr}>{abbr}</option>)}
            </select>
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">Type</label>
            <select value={type} onChange={e => { setType(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500">
              <option value="">All types</option>
              <option value="in">In</option>
              <option value="out">Out</option>
            </select>
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">From</label>
            <input type="date" value={from} onChange={e => { setFrom(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">To</label>
            <input type="date" value={to} onChange={e => { setTo(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <button onClick={reset} className="px-3 py-2 text-sm text-gray-500 hover:text-white bg-gray-800 rounded-lg border border-gray-700 hover:border-gray-500 transition-colors">
            Clear
          </button>
        </div>

        {!data ? <Spinner /> : (
          <>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                    <th className="px-4 py-3 text-left">Time</th>
                    <th className="px-4 py-3 text-left">Account</th>
                    <th className="px-4 py-3 text-left">Type</th>
                    <th className="px-4 py-3 text-right">Amount</th>
                    <th className="px-4 py-3 text-left">By</th>
                    <th className="px-4 py-3 text-left text-gray-600">Note</th>
                  </tr>
                </thead>
                <tbody>
                  {data.recentTransactions.map(t => (
                    <tr key={t.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                      <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(t.timestamp)}</td>
                      <td className="px-4 py-2.5 text-white">{t.currency_name}</td>
                      <td className="px-4 py-2.5">
                        <span className={`text-xs px-2 py-0.5 rounded-full ${t.type === 'in' ? 'bg-green-900/30 text-green-400' : 'bg-red-900/30 text-red-400'}`}>
                          {t.type}
                        </span>
                      </td>
                      <td className={`px-4 py-2.5 text-right font-semibold ${txnStyle(t)}`}>
                        {txnSign(t)}{fmt(Math.abs(t.amount))}
                      </td>
                      <td className="px-4 py-2.5 text-gray-400">{t.username}</td>
                      <td className="px-4 py-2.5 text-gray-600 text-xs">{t.note ?? '—'}</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
            <div className="px-4 py-3 border-t border-gray-800">
              <Pagination page={data.page} total={data.total} pageSize={data.pageSize} onChange={setPage} />
            </div>
          </>
        )}
      </div>
    </div>
  );
}

// ── Shares ────────────────────────────────────────────────────────────────────

function Shares() {
  const [data,     setData]     = useState(null);
  const [page,     setPage]     = useState(1);
  const [expanded, setExpanded] = useState(null);
  const [payouts,  setPayouts]  = useState({});

  const load = useCallback(() => {
    api(`/shares?page=${page}`).then(setData);
  }, [page]);

  useEffect(() => { load(); }, [load]);

  function toggleExpand(id) {
    if (expanded === id) { setExpanded(null); return; }
    setExpanded(id);
    if (!payouts[id]) {
      api(`/shares/${id}`).then(r => setPayouts(prev => ({ ...prev, [id]: r.payouts })));
    }
  }

  if (!data) return <Spinner />;

  if (!data.available) {
    return (
      <div className="space-y-6">
        <h1 className="text-2xl font-bold text-white">Shares</h1>
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-8 text-center text-gray-500">
          Share data not available in this database yet.
        </div>
      </div>
    );
  }

  const totalDistributed = data.sessions.filter(s => !s.reverted).reduce((s, r) => s + r.net_crystals, 0);

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Shares</h1>

      <div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
        <StatCard label="Total Sessions"    value={fmt(data.total)}                        sub="all time" />
        <StatCard label="Total Distributed" value={`${fmt(Math.round(totalDistributed))} 💎`} sub="net, this page" />
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">#</th>
                <th className="px-4 py-3 text-left">Date</th>
                <th className="px-4 py-3 text-right">Total</th>
                <th className="px-4 py-3 text-right">Tax</th>
                <th className="px-4 py-3 text-right">Net</th>
                <th className="px-4 py-3 text-right">Price/AP</th>
                <th className="px-4 py-3 text-right">Players</th>
                <th className="px-4 py-3 text-left">Created by</th>
                <th className="px-4 py-3 text-left"></th>
              </tr>
            </thead>
            <tbody>
              {data.sessions.map(s => (
                <React.Fragment key={s.id}>
                  <tr
                    className={`border-b border-gray-800/60 hover:bg-gray-800/30 cursor-pointer transition-colors ${s.reverted ? 'opacity-40' : ''}`}
                    onClick={() => toggleExpand(s.id)}>
                    <td className="px-4 py-2.5 text-gray-600 text-xs font-mono">#{s.guild_seq ?? s.id}</td>
                    <td className="px-4 py-2.5 text-gray-400 font-mono text-xs">{fmtD(s.timestamp)}</td>
                    <td className="px-4 py-2.5 text-right text-gray-300">{fmt(Math.round(s.total_crystals))} 💎</td>
                    <td className="px-4 py-2.5 text-right text-gray-500 text-xs">{s.tax_pct > 0 ? `${s.tax_pct}%` : '—'}</td>
                    <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">{fmt(Math.round(s.net_crystals))} 💎</td>
                    <td className="px-4 py-2.5 text-right text-gray-400 text-xs">{s.price_per_eff_ap.toFixed(2)}</td>
                    <td className="px-4 py-2.5 text-right text-gray-300">{s.payout_count}</td>
                    <td className="px-4 py-2.5 text-gray-400">{s.created_by}</td>
                    <td className="px-4 py-2.5 text-gray-600 text-xs flex items-center gap-2">
                      {s.reverted && <span className="text-red-500">reverted</span>}
                      <span>{expanded === s.id ? '▲' : '▼'}</span>
                    </td>
                  </tr>
                  {expanded === s.id && (
                    <tr className="border-b border-gray-700">
                      <td colSpan="9" className="px-6 py-3 bg-gray-950">
                        {!payouts[s.id] ? (
                          <p className="text-gray-500 text-xs py-1">Loading…</p>
                        ) : payouts[s.id].length === 0 ? (
                          <p className="text-gray-600 text-xs py-1">No payouts recorded.</p>
                        ) : (
                          <table className="w-full text-xs">
                            <thead>
                              <tr className="text-gray-600 uppercase tracking-wide">
                                <th className="pr-6 py-1 text-left">Player</th>
                                <th className="pr-6 py-1 text-right">AP</th>
                                <th className="pr-6 py-1 text-right">Bonus</th>
                                <th className="pr-6 py-1 text-right">Eff. AP</th>
                                <th className="py-1 text-right">Crystals</th>
                              </tr>
                            </thead>
                            <tbody>
                              {payouts[s.id].map(p => (
                                <tr key={p.id} className="border-t border-gray-800/40">
                                  <td className="pr-6 py-1 text-white">{p.username}</td>
                                  <td className="pr-6 py-1 text-right text-gray-400">{p.ap}</td>
                                  <td className="pr-6 py-1 text-right text-gray-500">{p.bonus_pct > 0 ? `+${p.bonus_pct}%` : '—'}</td>
                                  <td className="pr-6 py-1 text-right text-gray-300">{(+p.effective_ap).toFixed(1)}</td>
                                  <td className="py-1 text-right text-violet-300 font-semibold">{fmt(Math.round(p.crystals))} 💎</td>
                                </tr>
                              ))}
                            </tbody>
                          </table>
                        )}
                      </td>
                    </tr>
                  )}
                </React.Fragment>
              ))}
            </tbody>
          </table>
        </div>
      </div>
      <Pagination page={data.page} total={data.total} pageSize={data.pageSize} onChange={setPage} />
    </div>
  );
}

// ── Auctions ──────────────────────────────────────────────────────────────────

function AuctionBids({ auctionId, onBack }) {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    api(`/auctions/${auctionId}/bids`).then(setData);
  }, [auctionId]);

  if (!data) return <Spinner />;

  return (
    <div className="space-y-6">
      <div className="flex items-center gap-3">
        <button onClick={onBack} className="text-gray-500 hover:text-white transition-colors text-sm">← Back</button>
        <h1 className="text-2xl font-bold text-white">Auction Bids</h1>
      </div>

      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">Time</th>
                <th className="px-4 py-3 text-left">Bidder</th>
                <th className="px-4 py-3 text-right">Amount</th>
              </tr>
            </thead>
            <tbody>
              {data.bids.map(b => (
                <tr key={b.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(b.timestamp)}</td>
                  <td className="px-4 py-2.5 text-white">{b.username}</td>
                  <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">{fmt(b.amount)} 💎</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

function Auctions({ onNavigate }) {
  const [data,   setData]   = useState(null);
  const [stats,  setStats]  = useState(null);
  const [goldData, setGoldData] = useState(null);
  const [page,   setPage]   = useState(1);
  const [gem,    setGem]    = useState('');
  const [status, setStatus] = useState('');
  const [winner, setWinner] = useState('');
  const [from,   setFrom]   = useState('');
  const [to,     setTo]     = useState('');

  const load = useCallback(() => {
    const p = new URLSearchParams({ page });
    if (gem)    p.set('gem',    gem);
    if (status) p.set('status', status);
    if (winner) p.set('winner', winner);
    if (from)   p.set('from',   from);
    if (to)     p.set('to',     to);
    api(`/auctions?${p}`).then(setData);
  }, [page, gem, status, winner, from, to]);

  useEffect(() => {
    load();
    api('/auctions/stats').then(setStats);
    api('/auctions/gold-accumulation').then(setGoldData);
  }, [load]);

  const reset = () => { setGem(''); setStatus(''); setWinner(''); setFrom(''); setTo(''); setPage(1); };

  const statusStyle = s => ({
    active:    'bg-blue-900/30 text-blue-400',
    ended:     'bg-gray-900/30 text-gray-400',
    cancelled: 'bg-red-900/30 text-red-400',
  }[s] ?? 'text-gray-400');

  if (!data) return <Spinner />;

  if (!data.available) {
    return (
      <div className="space-y-6">
        <h1 className="text-2xl font-bold text-white">Auctions</h1>
        <div className="bg-gray-900 rounded-xl border border-gray-800 p-8 text-center text-gray-500">
          Auction data not available in this database yet.
        </div>
      </div>
    );
  }

  return (
    <div className="space-y-6">
      <h1 className="text-2xl font-bold text-white">Auctions</h1>

      {stats && (
        <>
          <div className="grid grid-cols-2 lg:grid-cols-3 gap-4">
            <StatCard label="Total Auctions"    value={fmt(stats.totalAuctions)}     sub="all time" />
            <StatCard label="Total Revenue"     value={`${fmt(stats.totalRevenue)} 💎`} sub="from completed auctions" />
            <StatCard label="Active Status"     value={stats.statusBreakdown.find(s => s.status === 'active')?.count ?? 0} sub="currently running" />
          </div>

          <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
            <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
              <h2 className="text-white font-semibold text-sm mb-4">Revenue by Share Session</h2>
              <BarChart data={stats.shareSessionRevenue.map(s => ({ week: s.session, count: s.revenue }))} label="Revenue (💎)" color="#8b5cf6" />
            </div>
            
            <div className="bg-gray-900 rounded-xl border border-gray-800 p-5">
              <h2 className="text-white font-semibold text-sm mb-4">Top Gems by Auction Count</h2>
              <div className="space-y-2">
                {stats.topGems.slice(0, 5).map((g, i) => (
                  <div key={g.gem_base || g.gem} className="flex justify-between items-center">
                    <div>
                      <span className="text-white text-sm">{trunc(g.gem_base || g.gem, 25)}</span>
                      <span className="text-gray-600 text-xs ml-2">{g.auction_count} auctions</span>
                    </div>
                    <span className="text-violet-400 text-sm">{fmt(Math.round(g.max_price))} 💎 max</span>
                  </div>
                ))}
              </div>
            </div>
          </div>

          <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
            <div className="px-4 py-3 border-b border-gray-800 text-gray-300 font-semibold text-sm">Top Contributors</div>
            <div className="overflow-x-auto">
              <table className="w-full text-sm">
                <thead>
                  <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                    <th className="px-4 py-3 text-left w-8">#</th>
                    <th className="px-4 py-3 text-left">Contributor</th>
                    <th className="px-4 py-3 text-right">Wins</th>
                    <th className="px-4 py-3 text-right">Total Spent</th>
                  </tr>
                </thead>
                <tbody>
                  {stats.topWinners.map((w, i) => (
                    <tr key={w.winner} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                      <td className="px-4 py-2.5 text-gray-600 text-xs font-mono">{i + 1}</td>
                      <td className="px-4 py-2.5 text-white font-medium">{w.winner}</td>
                      <td className="px-4 py-2.5 text-right text-green-400">{w.wins}</td>
                      <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">{fmt(Math.round(w.total_spent))} 💎</td>
                    </tr>
                  ))}
                </tbody>
              </table>
            </div>
          </div>

          {goldData && goldData.available && (
            <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
              <div className="px-4 py-3 border-b border-gray-800 text-gray-300 font-semibold text-sm">Crystal Accumulation by Share Session</div>
              <div className="overflow-x-auto">
                <table className="w-full text-sm">
                  <thead>
                    <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                      <th className="px-4 py-3 text-left">Session</th>
                      <th className="px-4 py-3 text-left">Date</th>
                      <th className="px-4 py-3 text-right">Crystals Distributed</th>
                      <th className="px-4 py-3 text-right">Auction Revenue</th>
                      <th className="px-4 py-3 text-right">Auctions</th>
                      <th className="px-4 py-3 text-right">Contribution</th>
                      <th className="px-4 py-3 text-left">Top Contributor</th>
                    </tr>
                  </thead>
                  <tbody>
                    {goldData.sessions.map(s => (
                      <tr key={s.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                        <td className="px-4 py-2.5 text-white font-medium">
                          #{s.guild_seq ?? s.id}
                          {s.reverted && <span className="text-red-400 text-xs ml-1">(reverted)</span>}
                        </td>
                        <td className="px-4 py-2.5 text-gray-400 text-xs">
                          <div>{fmtD(s.timestamp)}</div>
                          <div className="text-gray-600">by {s.created_by}</div>
                        </td>
                        <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">
                          {fmt(Math.round(s.net_crystals))} 💎
                          {s.tax_pct > 0 && <div className="text-gray-600 text-xs">{s.tax_pct}% tax</div>}
                        </td>
                        <td className="px-4 py-2.5 text-right text-yellow-300 font-semibold">
                          {s.auction_revenue > 0 ? `${fmt(s.auction_revenue)} 💎` : '—'}
                        </td>
                        <td className="px-4 py-2.5 text-right text-gray-300">{s.auction_count}</td>
                        <td className="px-4 py-2.5 text-right text-green-400">
                          {s.auction_revenue > 0 ? `${s.auction_contribution.toFixed(1)}%` : '—'}
                        </td>
                        <td className="px-4 py-2.5 text-gray-300">
                          {s.top_winners.length > 0 ? 
                            `${s.top_winners[0].winner} (${fmt(s.top_winners[0].spent)} 💎)` : 
                            '—'
                          }
                        </td>
                      </tr>
                    ))}
                  </tbody>
                </table>
              </div>
              <div className="px-4 py-3 border-t border-gray-800 text-gray-600 text-xs">
                Contribution = (Auction Revenue / Crystals Distributed) × 100% • Shows how much auction revenue contributed to the share pool
              </div>
            </div>
          )}
        </>
      )}

      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="px-4 py-3 border-b border-gray-800 text-gray-300 font-semibold text-sm">All Auctions</div>
        
        <div className="p-4 border-b border-gray-800 flex flex-wrap gap-3 items-end">
          <div>
            <label className="text-gray-500 text-xs block mb-1">Gem</label>
            <input value={gem} onChange={e => { setGem(e.target.value); setPage(1); }}
              placeholder="Filter gem…"
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">Status</label>
            <select value={status} onChange={e => { setStatus(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500">
              <option value="">All statuses</option>
              <option value="active">Active</option>
              <option value="ended">Ended</option>
              <option value="cancelled">Cancelled</option>
            </select>
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">Winner</label>
            <input value={winner} onChange={e => { setWinner(e.target.value); setPage(1); }}
              placeholder="Filter winner…"
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">From</label>
            <input type="date" value={from} onChange={e => { setFrom(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <div>
            <label className="text-gray-500 text-xs block mb-1">To</label>
            <input type="date" value={to} onChange={e => { setTo(e.target.value); setPage(1); }}
              className="bg-gray-950 text-white rounded-lg px-3 py-2 text-sm border border-gray-700 focus:outline-none focus:border-violet-500" />
          </div>
          <button onClick={reset} className="px-3 py-2 text-sm text-gray-500 hover:text-white bg-gray-800 rounded-lg border border-gray-700 hover:border-gray-500 transition-colors">
            Clear
          </button>
        </div>

        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">#</th>
                <th className="px-4 py-3 text-left">Gem</th>
                <th className="px-4 py-3 text-left">Status</th>
                <th className="px-4 py-3 text-right">Starting Price</th>
                <th className="px-4 py-3 text-right">Final Bid</th>
                <th className="px-4 py-3 text-left">Winner</th>
                <th className="px-4 py-3 text-right">Bids</th>
                <th className="px-4 py-3 text-left">Created</th>
                <th className="px-4 py-3 text-left">Actions</th>
              </tr>
            </thead>
            <tbody>
              {data.auctions.map(a => (
                <tr key={a.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-gray-600 text-xs">#{a.guild_seq ?? a.id}</td>
                  <td className="px-4 py-2.5 text-white font-medium">{trunc(a.gem, 30)}</td>
                  <td className="px-4 py-2.5">
                    <span className={`text-xs px-2 py-0.5 rounded-full ${statusStyle(a.status)}`}>
                      {a.status}
                    </span>
                  </td>
                  <td className="px-4 py-2.5 text-right text-gray-400">{fmt(a.starting_price)} 💎</td>
                  <td className="px-4 py-2.5 text-right text-violet-300 font-semibold">
                    {a.current_bid > 0 ? `${fmt(a.current_bid)} 💎` : '—'}
                  </td>
                  <td className="px-4 py-2.5 text-gray-300">{a.current_bidder_name ?? '—'}</td>
                  <td className="px-4 py-2.5 text-right text-gray-400">{a.bid_count}</td>
                  <td className="px-4 py-2.5 text-gray-500 font-mono text-xs">{fmtD(a.timestamp)}</td>
                  <td className="px-4 py-2.5">
                    {a.bid_count > 0 && (
                      <button 
                        onClick={() => onNavigate('auction-bids', { auctionId: a.id })}
                        className="text-violet-400 hover:text-violet-300 text-xs">
                        View Bids
                      </button>
                    )}
                  </td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        
        <div className="px-4 py-3 border-t border-gray-800">
          <Pagination page={data.page} total={data.total} pageSize={data.pageSize} onChange={setPage} />
        </div>
      </div>
    </div>
  );
}

// ── Bless Tracker ─────────────────────────────────────────────────────────────

function BlessTracker() {
  const [data, setData] = useState(null);
  const [filters, setFilters] = useState({ username: '', maze: '', page: 1 });

  useEffect(() => {
    const params = new URLSearchParams();
    if (filters.username) params.append('username', filters.username);
    if (filters.maze) params.append('maze', filters.maze);
    params.append('page', filters.page);
    
    api(`/bless-tracker?${params}`).then(setData);
  }, [filters]);

  if (!data) return <Spinner />;
  if (!data.available) return <div className="text-gray-500 text-center py-16">Bless tracking not available</div>;

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold text-white">🧪 Bless Tracker</h1>
        <p className="text-gray-500 text-sm mt-1">Track blessed potion usage across mazes</p>
      </div>

      {/* Stats Cards */}
      <div className="grid grid-cols-1 md:grid-cols-4 gap-4">
        <StatCard label="Total Potions Used" value={fmt(data.stats.totalPotionsUsed)} color="violet" />
        <StatCard label="Total Users" value={fmt(data.stats.totalUsers)} color="teal" />
        <StatCard label="Recent Activity (7d)" value={fmt(data.stats.recentActivity)} color="violet" />
        <StatCard label="Total Records" value={fmt(data.total)} color="teal" />
      </div>

      {/* Top Stats */}
      <div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
        {/* Top Users */}
        <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
          <h3 className="text-white font-semibold mb-4">Top Users by Potions Used</h3>
          <div className="space-y-2">
            {data.stats.topUsers.map((u, i) => (
              <div key={u.user_id} className="flex items-center justify-between text-sm">
                <div className="flex items-center gap-2">
                  <span className="text-gray-600 w-6">#{i + 1}</span>
                  <span className="text-white">{u.username}</span>
                </div>
                <div className="flex items-center gap-4">
                  <span className="text-violet-400">{fmt(u.total_potions)} potions</span>
                  <span className="text-gray-500">{fmt(u.usage_count)} uses</span>
                </div>
              </div>
            ))}
          </div>
        </div>

        {/* Top Mazes */}
        <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
          <h3 className="text-white font-semibold mb-4">Top Mazes by Usage</h3>
          <div className="space-y-2">
            {data.stats.topMazes.map((m, i) => (
              <div key={m.maze_name} className="flex items-center justify-between text-sm">
                <div className="flex items-center gap-2">
                  <span className="text-gray-600 w-6">#{i + 1}</span>
                  <span className="text-white">{trunc(m.maze_name, 25)}</span>
                </div>
                <div className="flex items-center gap-4">
                  <span className="text-violet-400">{fmt(m.total_potions)} potions</span>
                  <span className="text-gray-500">{fmt(m.usage_count)} uses</span>
                </div>
              </div>
            ))}
          </div>
        </div>
      </div>

      {/* Filters */}
      <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
        <div className="flex flex-wrap gap-3">
          <input
            type="text"
            placeholder="Filter by username..."
            value={filters.username}
            onChange={e => setFilters({ ...filters, username: e.target.value, page: 1 })}
            className="px-4 py-2 bg-gray-800 text-white rounded-lg border border-gray-700 focus:border-violet-500 focus:outline-none text-sm"
          />
          <input
            type="text"
            placeholder="Filter by maze name..."
            value={filters.maze}
            onChange={e => setFilters({ ...filters, maze: e.target.value, page: 1 })}
            className="px-4 py-2 bg-gray-800 text-white rounded-lg border border-gray-700 focus:border-violet-500 focus:outline-none text-sm"
          />
          <button
            onClick={() => setFilters({ username: '', maze: '', page: 1 })}
            className="px-4 py-2 bg-gray-800 text-gray-400 rounded-lg border border-gray-700 hover:border-gray-600 text-sm"
          >
            Clear
          </button>
        </div>
      </div>

      {/* History Table */}
      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">User</th>
                <th className="px-4 py-3 text-left">Maze</th>
                <th className="px-4 py-3 text-right">Potions Used</th>
                <th className="px-4 py-3 text-left">Timestamp</th>
              </tr>
            </thead>
            <tbody>
              {data.history.map(h => (
                <tr key={h.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-white">{h.username}</td>
                  <td className="px-4 py-2.5 text-gray-300">{h.maze_name || '—'}</td>
                  <td className="px-4 py-2.5 text-right text-violet-400 font-medium">{h.potions_used}</td>
                  <td className="px-4 py-2.5 text-gray-500">{fmtD(h.timestamp)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
        <div className="p-4 border-t border-gray-800">
          <Pagination
            page={filters.page}
            total={data.total}
            pageSize={data.pageSize}
            onChange={p => setFilters({ ...filters, page: p })}
          />
        </div>
      </div>
    </div>
  );
}

// ── Wallet Tracker ────────────────────────────────────────────────────────────

function WalletTracker() {
  const [data, setData] = useState(null);

  useEffect(() => {
    api('/gold-owed').then(setData);
  }, []);

  if (!data) return <Spinner />;
  if (!data.available) return <div className="text-gray-500 text-center py-16">Wallet tracking not available</div>;

  return (
    <div className="space-y-6">
      <div>
        <h1 className="text-2xl font-bold text-white">🪙 Wallet Tracker</h1>
        <p className="text-gray-500 text-sm mt-1">Track wallet sessions and gold balances</p>
      </div>

      {/* Current Session */}
      {data.currentSession && (
        <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
          <div className="flex items-center justify-between mb-4">
            <h3 className="text-white font-semibold">Current Session</h3>
            <span className="px-3 py-1 bg-green-500/20 text-green-400 rounded-full text-xs font-medium">
              {data.currentSession.status}
            </span>
          </div>
          <div className="grid grid-cols-1 md:grid-cols-3 gap-4">
            <StatCard label="Current Balance" value={`${data.currentBalance.toFixed(2)}g`} color="violet" />
            <StatCard label="Session ID" value={`#${data.currentSession.id}`} color="teal" />
            <StatCard label="Created" value={fmtD(data.currentSession.created_at)} color="violet" />
          </div>
        </div>
      )}

      {/* User Balances */}
      {data.userBalances.length > 0 && (
        <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
          <h3 className="text-white font-semibold mb-4">User Balances (Current Session)</h3>
          <div className="overflow-x-auto">
            <table className="w-full text-sm">
              <thead>
                <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                  <th className="px-4 py-3 text-left">User</th>
                  <th className="px-4 py-3 text-right">Balance</th>
                  <th className="px-4 py-3 text-right">Transactions</th>
                </tr>
              </thead>
              <tbody>
                {data.userBalances.map(u => (
                  <tr key={u.user_id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                    <td className="px-4 py-2.5 text-white">{u.username}</td>
                    <td className={`px-4 py-2.5 text-right font-medium ${u.balance >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                      {u.balance >= 0 ? '+' : ''}{u.balance.toFixed(2)}g
                    </td>
                    <td className="px-4 py-2.5 text-right text-gray-400">{u.transaction_count}</td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
        </div>
      )}

      {/* Category Breakdown */}
      {data.categoryBreakdown.length > 0 && (
        <div className="bg-gray-900 rounded-xl p-5 border border-gray-800">
          <h3 className="text-white font-semibold mb-4">Category Breakdown (Current Session)</h3>
          <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
            {data.categoryBreakdown.map(c => (
              <div key={`${c.category}-${c.type}`} className="flex items-center justify-between p-3 bg-gray-800/50 rounded-lg">
                <div>
                  <div className="text-white font-medium">{c.category}</div>
                  <div className="text-gray-500 text-xs">{c.type === 'in' ? 'Income' : 'Expense'} · {c.count} transactions</div>
                </div>
                <div className={`text-lg font-bold ${c.type === 'in' ? 'text-green-400' : 'text-red-400'}`}>
                  {c.type === 'in' ? '+' : '-'}{c.total.toFixed(2)}g
                </div>
              </div>
            ))}
          </div>
        </div>
      )}

      {/* Sessions History */}
      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="px-5 py-4 border-b border-gray-800">
          <h3 className="text-white font-semibold">Session History</h3>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">ID</th>
                <th className="px-4 py-3 text-right">Balance</th>
                <th className="px-4 py-3 text-right">Total In</th>
                <th className="px-4 py-3 text-right">Total Out</th>
                <th className="px-4 py-3 text-right">Participants</th>
                <th className="px-4 py-3 text-left">Status</th>
                <th className="px-4 py-3 text-left">Created</th>
                <th className="px-4 py-3 text-left">Closed</th>
              </tr>
            </thead>
            <tbody>
              {data.sessions.map(s => (
                <tr key={s.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-gray-400">#{s.id}</td>
                  <td className={`px-4 py-2.5 text-right font-medium ${s.balance >= 0 ? 'text-green-400' : 'text-red-400'}`}>
                    {s.balance.toFixed(2)}g
                  </td>
                  <td className="px-4 py-2.5 text-right text-green-400">+{s.total_in.toFixed(2)}g</td>
                  <td className="px-4 py-2.5 text-right text-red-400">-{s.total_out.toFixed(2)}g</td>
                  <td className="px-4 py-2.5 text-right text-gray-400">{s.participant_count}</td>
                  <td className="px-4 py-2.5">
                    <span className={`px-2 py-1 rounded-full text-xs font-medium ${
                      s.status === 'open' ? 'bg-green-500/20 text-green-400' : 'bg-gray-700 text-gray-400'
                    }`}>
                      {s.status}
                    </span>
                  </td>
                  <td className="px-4 py-2.5 text-gray-500">{fmtD(s.created_at)}</td>
                  <td className="px-4 py-2.5 text-gray-500">{s.closed_at ? fmtD(s.closed_at) : '—'}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>

      {/* Recent Transactions */}
      <div className="bg-gray-900 rounded-xl border border-gray-800 overflow-hidden">
        <div className="px-5 py-4 border-b border-gray-800">
          <h3 className="text-white font-semibold">Recent Transactions</h3>
        </div>
        <div className="overflow-x-auto">
          <table className="w-full text-sm">
            <thead>
              <tr className="text-gray-500 text-xs uppercase tracking-wide border-b border-gray-800">
                <th className="px-4 py-3 text-left">User</th>
                <th className="px-4 py-3 text-left">Type</th>
                <th className="px-4 py-3 text-left">Category</th>
                <th className="px-4 py-3 text-left">Item</th>
                <th className="px-4 py-3 text-right">Amount</th>
                <th className="px-4 py-3 text-left">Note</th>
                <th className="px-4 py-3 text-left">Timestamp</th>
              </tr>
            </thead>
            <tbody>
              {data.recentTransactions.map(t => (
                <tr key={t.id} className="border-b border-gray-800/60 hover:bg-gray-800/30">
                  <td className="px-4 py-2.5 text-white">{t.username}</td>
                  <td className="px-4 py-2.5">
                    <span className={`px-2 py-1 rounded-full text-xs font-medium ${
                      t.type === 'in' ? 'bg-green-500/20 text-green-400' : 'bg-red-500/20 text-red-400'
                    }`}>
                      {t.type}
                    </span>
                  </td>
                  <td className="px-4 py-2.5 text-gray-300">{t.category || '—'}</td>
                  <td className="px-4 py-2.5 text-gray-300">{t.item ? `${t.item} ${t.quantity ? `(${t.quantity})` : ''}` : '—'}</td>
                  <td className={`px-4 py-2.5 text-right font-medium ${t.type === 'in' ? 'text-green-400' : 'text-red-400'}`}>
                    {t.type === 'in' ? '+' : '-'}{t.amount.toFixed(2)}g
                  </td>
                  <td className="px-4 py-2.5 text-gray-500">{trunc(t.note || '—', 30)}</td>
                  <td className="px-4 py-2.5 text-gray-500">{fmtD(t.timestamp)}</td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
}

// ── Gold Owed (Legacy - redirects to Wallet Tracker) ─────────────────────────

function GoldOwed() {
  return <WalletTracker />;
}

const NAV = [
  { id: 'overview',      icon: '🏠', label: 'Overview'       },
  { id: 'currency-owed', icon: '💎', label: 'Currency Owed'  },
  { id: 'activity',      icon: '📋', label: 'Berry Submissions' },
  { id: 'maze-stats',    icon: '🗺️', label: 'Maze Stats'     },
  { id: 'players',       icon: '⚔️', label: 'Players'         },
  { id: 'reports',       icon: '📊', label: 'Reports'         },
  { id: 'bless-tracker', icon: '🧪', label: 'Bless Tracker'   },
  { id: 'wallet-tracker', icon: '🪙', label: 'Wallet Tracker' },
  { id: 'auctions',      icon: '💍', label: 'Auctions'        },
  { id: 'shares',        icon: '💰', label: 'Shares'          },
  { id: 'bank',          icon: '🏦', label: 'Bank'            },
];

// ── Login Page ────────────────────────────────────────────────────────────────

function LoginPage({ error }) {
  const errorMessages = {
    no_code: 'Authorization code not received',
    oauth_failed: 'OAuth authentication failed',
    no_access: 'You do not have access to any guilds. Please contact your server administrator.',
    auth_failed: 'Authentication failed. Please try again.',
  };

  return (
    <div className="min-h-screen bg-gray-950 flex items-center justify-center p-6">
      <div className="max-w-md w-full">
        <div className="text-center mb-8">
          <div className="text-6xl mb-4">🫐</div>
          <h1 className="text-3xl font-bold text-white mb-2">Guild Dashboard</h1>
          <p className="text-gray-400">Sign in with Discord to continue</p>
        </div>

        {error && (
          <div className="bg-red-500/20 border border-red-500/50 rounded-lg p-4 mb-6">
            <p className="text-red-400 text-sm">{errorMessages[error] || 'An error occurred'}</p>
          </div>
        )}

        <div className="bg-gray-900 rounded-xl border border-gray-800 p-8">
          <a
            href="/auth/login"
            className="w-full flex items-center justify-center gap-3 bg-indigo-600 hover:bg-indigo-700 text-white font-semibold py-3 px-6 rounded-lg transition-colors"
          >
            <svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24">
              <path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515a.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0a12.64 12.64 0 0 0-.617-1.25a.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057a19.9 19.9 0 0 0 5.993 3.03a.078.078 0 0 0 .084-.028a14.09 14.09 0 0 0 1.226-1.994a.076.076 0 0 0-.041-.106a13.107 13.107 0 0 1-1.872-.892a.077.077 0 0 1-.008-.128a10.2 10.2 0 0 0 .372-.292a.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127a12.299 12.299 0 0 1-1.873.892a.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028a19.839 19.839 0 0 0 6.002-3.03a.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.956-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419c0-1.333.955-2.419 2.157-2.419c1.21 0 2.176 1.096 2.157 2.42c0 1.333-.946 2.418-2.157 2.418z"/>
            </svg>
            Sign in with Discord
          </a>

          <div className="mt-6 text-center text-gray-500 text-sm">
            <p>You need to be a member of a guild with the appropriate role to access this dashboard.</p>
          </div>
        </div>

        <div className="mt-6 text-center text-gray-600 text-xs">
          <p>By signing in, you agree to share your Discord user info and guild memberships.</p>
        </div>
      </div>
    </div>
  );
}

function App() {
  const [page,    setPage]    = useState('overview');
  const [userCtx, setUserCtx] = useState(null);
  const [sidebar, setSidebar] = useState(false);
  const [guilds,  setGuilds]  = useState([]);
  const [selectedGuild, setSelectedGuild] = useState(null);
  const [refreshKey, setRefreshKey] = useState(0); // Force re-render on guild change
  const [authState, setAuthState] = useState({ loading: true, requiresAuth: false, user: null });

  // Check authentication on mount
  useEffect(() => {
    fetch('/auth/me', {
      headers: getSessionId() ? { 'X-Session-ID': getSessionId() } : {}
    })
      .then(r => r.json())
      .then(data => {
        setAuthState({
          loading: false,
          requiresAuth: data.requiresAuth,
          user: data.user
        });
      })
      .catch(err => {
        console.error('Auth check failed:', err);
        setAuthState({ loading: false, requiresAuth: true, user: null });
      });
  }, []);

  // Load available guilds on mount (after auth check)
  useEffect(() => {
    if (authState.loading) return;
    if (authState.requiresAuth && !authState.user) return;
    
    api('/guilds').then(data => {
      setGuilds(data.guilds || []);
      // Set default guild
      const defaultGuild = data.guilds?.find(g => g.is_default) || data.guilds?.[0];
      if (defaultGuild) {
        setSelectedGuild(defaultGuild.guild_id);
        currentGuildId = defaultGuild.guild_id;
      }
    }).catch(err => console.error('Failed to load guilds:', err));
  }, [authState]);

  // Show loading state
  if (authState.loading) {
    return (
      <div className="min-h-screen bg-gray-950 flex items-center justify-center">
        <div className="text-center">
          <div className="w-16 h-16 border-4 border-violet-500 border-t-transparent rounded-full animate-spin mx-auto mb-4" />
          <p className="text-gray-400">Loading...</p>
        </div>
      </div>
    );
  }

  // Show login page if auth required and not logged in
  if (authState.requiresAuth && !authState.user) {
    const params = new URLSearchParams(window.location.search);
    const error = params.get('error');
    return <LoginPage error={error} />;
  }

  // Update global guild_id when selection changes
  function handleGuildChange(guildId) {
    setSelectedGuild(guildId);
    currentGuildId = guildId;
    // Clear cache when switching guilds
    clearCache();
    // Force refresh by incrementing key
    setRefreshKey(prev => prev + 1);
  }

  function navigate(p, ctx = null) {
    setPage(p);
    setUserCtx(ctx);
    setSidebar(false);
    window.scrollTo(0, 0);
  }

  function renderContent() {
    if (page === 'user' && userCtx) {
      return <UserProfile key={refreshKey} userId={userCtx.userId} onBack={() => navigate('currency-owed')} />;
    }
    if (page === 'player' && userCtx) {
      return <PlayerProfile key={refreshKey} userId={userCtx.userId} username={userCtx.username} onBack={() => navigate('players')} />;
    }
    if (page === 'auction-bids' && userCtx) {
      return <AuctionBids key={refreshKey} auctionId={userCtx.auctionId} onBack={() => navigate('auctions')} />;
    }
    switch (page) {
      case 'overview':        return <Overview        key={refreshKey} onNavigate={navigate} />;
      case 'currency-owed':   return <CurrencyOwed    key={refreshKey} onNavigate={navigate} />;
      case 'crystals-owed':   return <CurrencyOwed    key={refreshKey} onNavigate={navigate} />; // Redirect old route
      case 'activity':        return <Activity        key={refreshKey} />;
      case 'maze-stats':      return <MazeStats       key={refreshKey} />;
      case 'players':         return <PlayerStats     key={refreshKey} onNavigate={navigate} />;
      case 'reports':         return <Reports         key={refreshKey} />;
      case 'bless-tracker':   return <BlessTracker    key={refreshKey} />;
      case 'wallet-tracker':  return <WalletTracker   key={refreshKey} />;
      case 'gold-owed':       return <WalletTracker   key={refreshKey} />; // Redirect old route
      case 'auctions':        return <Auctions        key={refreshKey} onNavigate={navigate} />;
      case 'shares':          return <Shares          key={refreshKey} />;
      case 'bank':            return <Bank            key={refreshKey} />;
      default:                return <Overview        key={refreshKey} onNavigate={navigate} />;
    }
  }

  const activeId = page === 'user' ? 'currency-owed' : (page === 'player' ? 'players' : (page === 'auction-bids' ? 'auctions' : page));

  return (
    <div className="flex h-screen bg-gray-950 overflow-hidden">
      {sidebar && (
        <div className="fixed inset-0 bg-black/60 z-20 lg:hidden" onClick={() => setSidebar(false)} />
      )}

      {/* Sidebar */}
      <aside className={`fixed lg:static inset-y-0 left-0 z-30 w-52 bg-gray-900 border-r border-gray-800 flex flex-col transition-transform duration-200 ${sidebar ? 'translate-x-0' : '-translate-x-full lg:translate-x-0'}`}>
        <div className="px-5 py-5 border-b border-gray-800">
          <div className="text-white font-bold text-base leading-snug">
            🫐 Guild
            <span className="text-violet-400"> Dashboard</span>
          </div>
          <div className="text-gray-600 text-xs mt-0.5">read-only · live data</div>
        </div>

        {/* Guild Selector */}
        {guilds.length > 1 && (
          <div className="px-3 py-3 border-b border-gray-800">
            <label className="text-gray-500 text-xs uppercase tracking-wide mb-1.5 block">Guild</label>
            <select 
              value={selectedGuild || ''} 
              onChange={(e) => handleGuildChange(e.target.value)}
              className="w-full bg-gray-800 text-white text-sm px-3 py-2 rounded-lg border border-gray-700 focus:border-violet-500 focus:outline-none"
            >
              {guilds.map(g => (
                <option key={g.guild_id} value={g.guild_id}>
                  {g.name}
                </option>
              ))}
            </select>
          </div>
        )}

        <nav className="flex-1 p-2 space-y-0.5 overflow-y-auto">
          {NAV.map(n => (
            <button key={n.id} onClick={() => navigate(n.id)}
              className={`w-full flex items-center gap-2.5 px-3 py-2 text-sm rounded-lg transition-colors text-left ${
                activeId === n.id
                  ? 'bg-violet-600/20 text-violet-300 border border-violet-700/40'
                  : 'text-gray-400 hover:text-white hover:bg-gray-800'
              }`}>
              <span>{n.icon}</span>
              <span>{n.label}</span>
            </button>
          ))}
        </nav>

        {/* User Info & Logout */}
        {authState.user && (
          <div className="p-3 border-t border-gray-800">
            <div className="flex items-center gap-2 mb-2">
              {authState.user.avatar ? (
                <img 
                  src={`https://cdn.discordapp.com/avatars/${authState.user.userId}/${authState.user.avatar}.png?size=32`}
                  alt="Avatar"
                  className="w-8 h-8 rounded-full"
                />
              ) : (
                <div className="w-8 h-8 rounded-full bg-violet-600 flex items-center justify-center text-white text-xs font-bold">
                  {authState.user.username[0].toUpperCase()}
                </div>
              )}
              <div className="flex-1 min-w-0">
                <div className="text-white text-sm font-medium truncate">{authState.user.username}</div>
                <div className="text-gray-500 text-xs">{authState.user.accessibleGuilds.length} guild{authState.user.accessibleGuilds.length !== 1 ? 's' : ''}</div>
              </div>
            </div>
            <button
              onClick={async () => {
                await fetch(`/auth/logout?session_id=${getSessionId()}`);
                clearSession();
                window.location.reload();
              }}
              className="w-full px-3 py-2 text-sm text-gray-400 hover:text-white hover:bg-gray-800 rounded-lg transition-colors text-center"
            >
              Sign Out
            </button>
          </div>
        )}
      </aside>

      {/* Main */}
      <div className="flex-1 flex flex-col min-w-0 overflow-hidden">
        {/* Mobile header */}
        <div className="lg:hidden flex items-center gap-3 px-4 py-3 border-b border-gray-800 bg-gray-900 flex-shrink-0">
          <button onClick={() => setSidebar(true)} className="text-gray-400 hover:text-white text-lg">☰</button>
          <span className="text-white font-semibold text-sm">Guild Dashboard</span>
        </div>

        <main className="flex-1 overflow-y-auto p-6">
          {renderContent()}
        </main>
      </div>
    </div>
  );
}

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