/* usage.jsx — owner-only "Usage" tab: how the platform is being consumed.
   Daily active users + activity volume (tape_usage: one tick per user per
   ~5 minutes), events ingested per day / analyst / server, config-change
   volume, per-user activity table, headline totals. All data from
   GET /api/usage (owner-gated server-side too).
*/

// Minimal hand-rolled SVG bar chart, consistent with the app's design tokens.
// data: [{ label, value, value2? }] — value2 renders as a dimmer stacked bar.
function UsageBars({ data, height = 150, color = "var(--accent)", color2, fmt = (v) => v, title }) {
  const [hover, setHover] = useState(null);
  if (!data || !data.length) return <div className="usage-empty">No data yet — this fills in as the platform gets used.</div>;
  const W = 720, H = height, padB = 22, padT = 8;
  const max = Math.max(...data.map(d => Math.max(d.value, d.value2 || 0)), 1);
  const bw = W / data.length;
  const innerH = H - padB - padT;
  const labelEvery = Math.max(1, Math.ceil(data.length / 8));
  return (
    <div className="usage-chart">
      <svg viewBox={`0 0 ${W} ${H}`} preserveAspectRatio="none" className="usage-svg" onMouseLeave={() => setHover(null)}>
        {data.map((d, i) => {
          const h1 = Math.max(1.5, (d.value / max) * innerH);
          const h2 = d.value2 != null ? Math.max(0, (d.value2 / max) * innerH) : 0;
          const x = i * bw + bw * 0.15, w = bw * 0.7;
          return (
            <g key={i} onMouseEnter={() => setHover(i)}>
              <rect x={i * bw} y={0} width={bw} height={H} fill="transparent" />
              {h2 > 0 && <rect x={x} y={padT + innerH - h2} width={w} height={h2} rx="1.5" fill={color2 || "var(--bg-3)"} />}
              <rect x={x} y={padT + innerH - h1} width={w} height={h1} rx="1.5" fill={color} opacity={hover === i ? 1 : 0.82} />
            </g>
          );
        })}
        {data.map((d, i) => (i % labelEvery === 0
          ? <text key={"l" + i} x={i * bw + bw / 2} y={H - 6} textAnchor="middle" fontSize="9.5" fontFamily="var(--f-mono)" fill="var(--fg-3)">{d.label}</text>
          : null))}
      </svg>
      <div className="usage-chart-meta mono">
        {hover != null
          ? <>{data[hover].label} · <strong>{fmt(data[hover].value)}</strong>{data[hover].value2 != null && <span className="usage-dim"> · {fmt(data[hover].value2)}</span>}</>
          : title}
      </div>
    </div>
  );
}

// Horizontal ranked bars (events by analyst / server).
function UsageRank({ data, color = "var(--accent)", unit = "events" }) {
  if (!data || !data.length) return <div className="usage-empty">Nothing in this window.</div>;
  const max = Math.max(...data.map(d => d.value), 1);
  return (
    <div className="usage-rank">
      {data.map((d, i) => (
        <div key={i} className="usage-rank-row">
          <span className="usage-rank-name">{d.label}</span>
          <span className="usage-rank-track"><span className="usage-rank-fill" style={{ width: `${(d.value / max) * 100}%`, background: color }} /></span>
          <span className="usage-rank-val mono">{d.value} {unit}</span>
        </div>
      ))}
    </div>
  );
}

function UsageTab({ servers }) {
  const [days, setDays] = useState(30);
  const [guild, setGuild] = useState("");   // "" = all servers
  const [data, setData] = useState(null);
  const [err, setErr] = useState(null);
  const avatars = useAvatars((data?.users || []).map(u => u.user_id));

  useEffect(() => {
    let alive = true;
    setData(null); setErr(null);
    tapeFetch(apiBase() + "/api/usage?days=" + days + (guild ? "&guild=" + encodeURIComponent(guild) : ""))
      .then(async r => { const j = await r.json(); if (!r.ok) throw new Error(j.error || "HTTP " + r.status); return j; })
      .then(j => { if (alive) setData(j); })
      .catch(e => { if (alive) setErr(e.message); });
    return () => { alive = false; };
  }, [days, guild]);

  const srvName = (gid) => (servers || []).find(s => s.guild_id === gid)?.name || gid;
  const srvList = (servers || []).slice().sort((a, b) => (a.name || "").localeCompare(b.name || ""));
  const dayLabel = (d) => { const [, m, da] = String(d).split("-"); return `${Number(m)}/${Number(da)}`; };

  // Fill missing days with zeros so the bars read as a continuous timeline.
  const fillDays = (rows, key) => {
    const map = new Map((rows || []).map(r => [r.day, r]));
    const out = [];
    for (let i = days - 1; i >= 0; i--) {
      const d = new Date(Date.now() - i * 86400000).toISOString().slice(0, 10);
      const row = map.get(d);
      out.push({ label: dayLabel(d), value: row ? row[key] : 0, _row: row });
    }
    return out;
  };

  if (err) return <div className="empty" style={{ padding: 40 }}>Couldn't load usage — {err}</div>;
  if (!data) return <div className="empty" style={{ padding: 40 }}>Loading usage…</div>;

  const t = data.totals || {};
  const scoped = !!guild;
  const scopedName = scoped ? srvName(guild) : null;
  const dau = fillDays(data.daily, "users");
  const activity = fillDays(data.daily, "hits");
  const eventsDaily = fillDays(data.events_daily, "events");
  const auditDaily = fillDays(data.audit_daily, "actions");
  const peakDau = Math.max(...dau.map(d => d.value), 0);
  const totalEventsWindow = eventsDaily.reduce((s, d) => s + d.value, 0);

  return (
    <div className="usage">
      <div className="usage-head">
        <p className="sub" style={{ margin: 0 }}>
          How Sinux Signals is being consumed. Activity is sampled in ~5-minute blocks, so "active time" is an approximation.
          {scoped && <> Scoped to <strong>{scopedName}</strong> — user activity stays platform-wide.</>}
        </p>
        <div className="usage-controls">
          <select className="select usage-srv" value={guild} onChange={e => setGuild(e.target.value)} aria-label="Filter usage by server">
            <option value="">All servers</option>
            {srvList.map(s => <option key={s.guild_id} value={s.guild_id}>{s.name || s.guild_id}</option>)}
          </select>
          <div className="seg">
            {[7, 30, 90].map(d => (
              <button key={d} className={cx("seg-btn", days === d && "on")} onClick={() => setDays(d)}>{d}d</button>
            ))}
          </div>
        </div>
      </div>

      <div className="statgrid">
        <div className="stat"><div className="lbl">{I("user", { size: 11 })} Users with access</div><div className="val">{t.users ?? 0}</div><div className={cx("delta", !scoped && "up")}>{scoped ? "with access here" : `peak ${peakDau} active/day`}</div></div>
        <div className="stat"><div className="lbl">{I("events", { size: 11 })} Signals captured</div><div className="val">{t.events ?? 0}</div><div className="delta up">+{totalEventsWindow} in {days}d</div></div>
        <div className="stat"><div className="lbl">{I("sources", { size: 11 })} Analysts</div><div className="val">{t.analysts ?? 0}</div><div className="delta">{t.channels ?? 0} channels</div></div>
        <div className="stat"><div className="lbl">{I("server", { size: 11 })} Servers</div><div className="val">{t.servers ?? 0}</div><div className="delta">{t.watchlist ?? 0} watchlist · {t.grants ?? 0} role grants</div></div>
      </div>

      <div className="usage-grid">
        <div className="panel usage-panel">
          <div className="panel-hdr"><div className="panel-title">Daily active users</div><div className={cx("panel-meta", scoped && "usage-pw")}>{scoped ? "platform-wide" : `last ${days}d`}</div></div>
          <UsageBars data={dau} title={`unique signed-in users per day · last ${days} days`} fmt={(v) => `${v} user${v === 1 ? "" : "s"}`} />
        </div>
        <div className="panel usage-panel">
          <div className="panel-hdr"><div className="panel-title">Activity volume</div><div className={cx("panel-meta", scoped && "usage-pw")}>{scoped ? "platform-wide" : "~5-min blocks"}</div></div>
          <UsageBars data={activity} color="var(--c-add)" title={`activity blocks per day (≈ active minutes ÷ 5)`} fmt={(v) => `${v} blocks ≈ ${v * 5}min`} />
        </div>
        <div className="panel usage-panel">
          <div className="panel-hdr"><div className="panel-title">Signals ingested</div><div className="panel-meta">events/day</div></div>
          <UsageBars data={eventsDaily} color="var(--c-trim)" title={`parsed trade events per day · ${totalEventsWindow} total in window`} fmt={(v) => `${v} event${v === 1 ? "" : "s"}`} />
        </div>
        <div className="panel usage-panel">
          <div className="panel-hdr"><div className="panel-title">Config changes</div><div className="panel-meta">audit/day</div></div>
          <UsageBars data={auditDaily} color="var(--c-watch)" title="audited configuration changes per day" fmt={(v) => `${v} action${v === 1 ? "" : "s"}`} />
        </div>
      </div>

      <div className="usage-grid">
        <div className="panel usage-panel">
          <div className="panel-hdr"><div className="panel-title">Signals by analyst</div><div className="panel-meta">last {days}d</div></div>
          <UsageRank data={(data.events_by_analyst || []).map(a => ({ label: scoped ? a.analyst : `${a.analyst}${(data.events_by_analyst || []).filter(x => x.analyst === a.analyst).length > 1 ? " · " + srvName(a.guild_id) : ""}`, value: a.events }))} />
        </div>
        <div className="panel usage-panel">
          {scoped ? (
            <>
              <div className="panel-hdr"><div className="panel-title">Signals by channel</div><div className="panel-meta">last {days}d</div></div>
              <UsageRank data={(data.events_by_channel || []).map(c => ({ label: c.channel, value: c.events }))} color="var(--c-add)" />
            </>
          ) : (
            <>
              <div className="panel-hdr"><div className="panel-title">Signals by server</div><div className="panel-meta">last {days}d</div></div>
              <UsageRank data={(data.events_by_server || []).map(s => ({ label: s.name, value: s.events }))} color="var(--c-add)" />
            </>
          )}
        </div>
      </div>

      <div className="panel usage-panel">
        <div className="panel-hdr"><div className="panel-title">Who's using it</div><div className={cx("panel-meta", scoped && "usage-pw")}>{(data.users || []).length} users · {scoped ? "platform-wide" : `last ${days}d`}</div></div>
        {(data.users || []).length === 0 ? (
          <div className="usage-empty">No tracked activity yet — usage starts recording from this release.</div>
        ) : (
          <table className="tbl usage-tbl">
            <thead>
              <tr><th>User</th><th>Role</th><th>Active days</th><th>Est. active time</th><th>Last seen</th></tr>
            </thead>
            <tbody>
              {(data.users || []).map(u => (
                <tr key={u.user_id}>
                  <td>
                    <span className="usage-user">
                      <DiscordAvatar url={avatars[u.user_id]} size={20} fallback={<span className="hash">{I("user", { size: 13 })}</span>} />
                      <span>{u.name || u.user_id}</span>
                    </span>
                  </td>
                  <td><span className="mono usage-role">{u.role || "—"}</span></td>
                  <td className="mono">{u.active_days} / {days}</td>
                  <td className="mono">≈ {u.hits * 5 >= 60 ? `${Math.round(u.hits * 5 / 60)}h ${(u.hits * 5) % 60}m` : `${u.hits * 5}m`}</td>
                  <td className="mono muted">{fmtTime(new Date(u.last_seen).getTime(), { short: true })}</td>
                </tr>
              ))}
            </tbody>
          </table>
        )}
      </div>
    </div>
  );
}

Object.assign(window, { UsageTab });
