// Reusable hooks for live data:
//   useLiveStatus()    → BattleMetrics-backed server status (players, name,
//                         map, version, rank, ping, online).
//   useDiscordWidget() → public Discord widget JSON (online count + voice
//                         channel count). 60s poll. null until fetched.

function useLiveStatus(fallbackInitial) {
  const [state, setState] = React.useState({
    players: fallbackInitial ?? 47,
    max:     SERVER.slots,
    queue:   0,
    online:  true,
    name:    null,
    map:     null,
    version: null,
    rank:    null,
    country: null,
    source:  "demo",
    queueSource: "demo",
    lastFetch: null,
  });

  React.useEffect(() => {
    let stopped = false;
    let timer;

    async function tick() {
      const live = await ShovelheadLive.fetchBattleMetrics();
      if (stopped) return;
      if (live) {
        // Persist this sample so the 24h sparkline becomes real data.
        if (typeof live.players === "number") {
          ShovelheadLive.appendHistorySample(live.players);
        }
        setState(s => ({
          ...s,
          players: live.players ?? s.players,
          max:     live.maxPlayers ?? s.max,
          queue:   typeof live.queue === "number" ? live.queue : s.queue,
          online:  live.online,
          name:    live.name ?? null,
          map:     live.details?.map ?? null,
          version: live.details?.version ?? null,
          rank:    live.rank ?? null,
          country: live.country ?? null,
          source:  "battlemetrics",
          queueSource: typeof live.queue === "number" ? "battlemetrics" : "unavailable",
          lastFetch: Date.now(),
        }));
      } else {
        // demo drift so the prototype still looks alive
        setState(s => {
          const nextPlayers = Math.max(20, Math.min(s.max, s.players + (Math.random() < 0.5 ? -1 : 1)));
          // Demo queue: only nonzero when we're at/near cap
          const demoQueue = nextPlayers >= s.max
            ? Math.max(1, s.queue + (Math.random() < 0.5 ? -1 : 1))
            : nextPlayers >= s.max - 2
              ? Math.max(0, s.queue + (Math.random() < 0.6 ? -1 : 1))
              : 0;
          return {
            ...s,
            players: nextPlayers,
            queue:   demoQueue,
            source:  "demo",
            queueSource: "demo",
            lastFetch: Date.now(),
          };
        });
      }
      timer = setTimeout(tick, window.SHOVELHEAD_CONFIG.refreshMs);
    }
    tick();
    return () => { stopped = true; clearTimeout(timer); };
  }, []);

  return state;
}

function useDiscordWidget() {
  const [state, setState] = React.useState({
    presenceCount: null,
    channels:      null,
    name:          null,
    source:        "demo",
    lastFetch:     null,
  });

  React.useEffect(() => {
    let stopped = false;
    let timer;

    async function tick() {
      const w = await ShovelheadLive.fetchDiscordWidget();
      if (stopped) return;
      if (w) {
        setState({
          presenceCount: w.presenceCount,
          channels:      w.channels,
          name:          w.name,
          source:        "widget",
          lastFetch:     Date.now(),
        });
      } else {
        setState(s => ({ ...s, source: "demo", lastFetch: Date.now() }));
      }
      // 60s is plenty — the widget itself caches on Discord's side.
      timer = setTimeout(tick, 60_000);
    }
    tick();
    return () => { stopped = true; clearTimeout(timer); };
  }, []);

  return state;
}

window.useLiveStatus = useLiveStatus;
window.useDiscordWidget = useDiscordWidget;

function useLeaderboard() {
  const [state, setState] = React.useState({
    rows: null,
    source: "demo",
    generatedAt: null,
  });
  React.useEffect(() => {
    let stopped = false;
    let timer;
    async function tick() {
      const res = await ShovelheadLive.fetchLeaderboard();
      if (stopped) return;
      if (res && Array.isArray(res.rows)) {
        setState({ rows: res.rows, source: "live", generatedAt: res.generatedAt });
      } else {
        setState(s => ({ ...s, source: "demo" }));
      }
      // 5 min — matches the scraper's republish cadence.
      timer = setTimeout(tick, 5 * 60_000);
    }
    tick();
    return () => { stopped = true; clearTimeout(timer); };
  }, []);
  return state;
}

window.useLeaderboard = useLeaderboard;
