// page-activity.jsx — Activity Analysis

const { useState: useStateA, useMemo: useMemoA, useCallback: useCallbackA } = React;

function ActivityPage({ members, history, settings, distances, onToast, snapshotMeta }) {
  const now = new Date();
  const [filterLevels, setFilterLevels] = useStateA(new Set()); // empty = all
  const [sortKeys, setSortKeys] = useStateA([
    { col: 'activity_level', dir: 'desc' }, // desc = lost first
    { col: 'last_login', dir: 'asc' },
  ]);
  const [selected, setSelected] = useStateA(null);

  const historyByMember = useMemoA(() => groupHistory(history), [history]);

  const augmented = useMemoA(() => {
    return members.map(m => {
      const h = historyByMember[m.id] || [];
      const act = computeActivity(m, h, settings, now);
      const dist = distances[m.id] !== undefined ? distances[m.id] : m.manual_distance;
      return {
        ...m,
        activity_level: act.level,
        _changes: act.changes,
        _loginDays: act.loginDays,
        _history: h,
        manual_distance: dist,
      };
    });
  }, [members, historyByMember, settings, distances]);

  const counts = useMemoA(() => {
    const c = { active: 0, normal: 0, dormant: 0, lost: 0, new: 0 };
    augmented.forEach(m => { c[m.activity_level] = (c[m.activity_level] || 0) + 1; });
    return c;
  }, [augmented]);

  const filtered = useMemoA(() => {
    let r = augmented;
    if (filterLevels.size > 0) r = r.filter(m => filterLevels.has(m.activity_level));
    const sorted = [...r];
    sorted.sort((a, b) => {
      for (const { col, dir } of sortKeys) {
        let av = a[col], bv = b[col];
        if (col === 'last_login') { av = new Date(av).getTime(); bv = new Date(bv).getTime(); }
        if (col === 'activity_level') {
          const order = { lost: 0, dormant: 1, normal: 2, active: 3, new: 4 };
          av = order[av] ?? 5; bv = order[bv] ?? 5;
        }
        if (av == null) av = -Infinity;
        if (bv == null) bv = -Infinity;
        if (av < bv) return dir === 'asc' ? -1 : 1;
        if (av > bv) return dir === 'asc' ?  1 : -1;
      }
      return 0;
    });
    return sorted;
  }, [augmented, filterLevels, sortKeys]);

  const maxPower = useMemoA(() => Math.max(...augmented.map(m => m.power)), [augmented]);

  const toggleLevel = (lvl) => {
    setFilterLevels(prev => {
      const next = new Set(prev);
      if (next.has(lvl)) next.delete(lvl); else next.add(lvl);
      return next;
    });
  };

  const handleSort = (col) => {
    setSortKeys(prev => {
      const existing = prev.find(s => s.col === col);
      if (existing) {
        if (existing.dir === 'desc') return prev.map(s => s.col === col ? { ...s, dir: 'asc' } : s);
        return prev.filter(s => s.col !== col);
      }
      return [{ col, dir: 'desc' }, ...prev].slice(0, 3);
    });
  };

  const sortInd = (col) => {
    const idx = sortKeys.findIndex(s => s.col === col);
    if (idx === -1) return null;
    const arrow = sortKeys[idx].dir === 'desc' ? '↓' : '↑';
    return <span className="sort-ind">{idx + 1}{arrow}</span>;
  };

  // Bulk DM export — exports nicknames + login age for currently-filtered members
  const handleBulkDM = async () => {
    if (filtered.length === 0) {
      onToast('No members in filter');
      return;
    }
    let out = `Check-in list (${filtered.length} members):\n\n`;
    filtered.forEach(m => {
      const loginStr = m.last_login ? formatRelativePast(m.last_login, now) : 'never';
      out += `• ${m.nickname.padEnd(12)} — ${loginStr} · ${formatPower(m.power)}\n`;
    });
    await copyText(out);
    onToast(`Copied ${filtered.length} nicknames`);
  };

  // Stale snapshot
  const snapAgeH = (now.getTime() - new Date(snapshotMeta.last_sync).getTime()) / 3600000;
  const stale = snapAgeH > 36;

  const summaryCards = [
    { lvl: 'active',  label: 'Active',  sub: `≥ ${settings.activeThreshold} growth days` },
    { lvl: 'normal',  label: 'Normal',  sub: `${settings.normalThreshold}–${settings.activeThreshold - 1} growth days` },
    { lvl: 'dormant', label: 'Dormant', sub: `no growth · login ≤${settings.dormantLoginDays}d` },
    { lvl: 'lost',    label: 'Lost',    sub: `no growth · login >${settings.dormantLoginDays}d` },
  ];

  return (
    <div className="page">
      {stale && (
        <div className="banner">
          Snapshot is {Math.round(snapAgeH)}h old. Activity scores may lag reality.
        </div>
      )}

      <div className="section-header">
        <h2>Roster Activity</h2>
        <span className="sub">— window {settings.windowDays}d · click cards to filter</span>
      </div>

      <div className="summary-row">
        {summaryCards.map(c => (
          <div
            key={c.lvl}
            className="scard"
            data-l={c.lvl}
            data-on={filterLevels.has(c.lvl)}
            onClick={() => toggleLevel(c.lvl)}
          >
            <div className="scard-lbl"><span className="dot"></span>{c.label}</div>
            <div className="scard-n">{counts[c.lvl] || 0}</div>
            <div className="scard-sub">{c.sub}</div>
          </div>
        ))}
      </div>

      <div className="row" style={{ marginBottom: 12 }}>
        <span className="muted tabnum">
          Showing {filtered.length} / {augmented.length}
        </span>
        <span className="spacer"></span>
        <button className="btn ghost" onClick={() => setFilterLevels(new Set())} disabled={filterLevels.size === 0}>
          Clear filter
        </button>
        <button className="btn primary" onClick={handleBulkDM} disabled={filtered.length === 0}>
          Copy check-in list
        </button>
      </div>

      <div className="pool">
        <table className="tbl">
          <thead>
            <tr>
              <th onClick={() => handleSort('activity_level')}>● {sortInd('activity_level')}</th>
              <th onClick={() => handleSort('nickname')}>Nick {sortInd('nickname')}</th>
              <th className="right" onClick={() => handleSort('power')}>PWR {sortInd('power')}</th>
              <th onClick={() => handleSort('last_login')}>Login {sortInd('last_login')}</th>
              <th className="right" onClick={() => handleSort('manual_distance')}>Dist {sortInd('manual_distance')}</th>
              <th className="right" onClick={() => handleSort('_changes')}>Δ{settings.windowDays}d {sortInd('_changes')}</th>
              <th className="no-sort">Daily Δ ({settings.windowDays}d)</th>
            </tr>
          </thead>
          <tbody>
            {filtered.map(m => (
              <tr key={m.id} onClick={() => setSelected(m)} style={{ cursor: 'pointer' }}>
                <td><ActivityBadge level={m.activity_level} /></td>
                <td><span className="nick">{m.nickname}</span></td>
                <td className="right num">
                  <span className="fl-cell">
                    <span className="fl-bar"><i style={{ width: `${(m.power / maxPower) * 100}%` }}></i></span>
                    <span>{formatPower(m.power)}</span>
                  </span>
                </td>
                <td className="num" title={m.last_login ? new Date(m.last_login).toUTCString() : 'never'}>
                  {m.last_login ? formatRelativePast(m.last_login, now) : <span className="muted">never</span>}
                </td>
                <td className="right num">
                  {m.manual_distance != null ? m.manual_distance : <span className="muted">—</span>}
                </td>
                <td className="right num">{m._changes}</td>
                <td>
                  <BarChart history={m._history} days={settings.windowDays} />
                </td>
              </tr>
            ))}
          </tbody>
        </table>
      </div>

      {selected && (
        <MemberDrawer
          member={selected}
          history={selected._history}
          settings={settings}
          now={now}
          onClose={() => setSelected(null)}
          onToast={onToast}
        />
      )}
    </div>
  );
}

function MemberDrawer({ member, history, settings, now, onClose, onToast }) {
  // Build a 14-day timeline with delta indicators
  const days = settings.windowDays;
  const rows = [];
  let prev = null;
  for (let i = 0; i < days; i++) {
    const d = new Date(now);
    d.setUTCHours(0, 0, 0, 0);
    d.setUTCDate(d.getUTCDate() - (days - 1 - i));
    const ts = d.toISOString();
    const snap = history.find(h => h.timestamp.slice(0, 10) === ts.slice(0, 10));
    const pw = snap ? snap.power : null;
    const delta = pw != null && prev != null && pw !== prev ? pw - prev : 0;
    rows.push({ date: ts.slice(0, 10), pw, delta });
    if (pw != null) prev = pw;
  }

  const handleCopyDM = async () => {
    const template = `Hey ${member.nickname}, haven't seen you online much — everything OK? Anything I can help with?`;
    await copyText(template);
    onToast(`DM template copied`);
  };

  return (
    <>
      <div className="drawer-mask" onClick={onClose}></div>
      <aside className="drawer">
        <div className="drawer-hd">
          <ActivityBadge level={member.activity_level} />
          <h3>{member.nickname}</h3>
          <button className="close" onClick={onClose}>×</button>
        </div>
        <div className="drawer-body">
          <div className="drawer-section">
            <h4>Profile</h4>
            <dl className="drawer-kv">
              <dt>Power</dt>       <dd>{formatPower(member.power)} <span className="muted">({member.power.toLocaleString()})</span></dd>
              <dt>Grade</dt>       <dd>{member.grade || <span className="muted">—</span>}</dd>
              <dt>Last login</dt>  <dd>{member.last_login ? <>{formatRelativePast(member.last_login, now)} <span className="muted">({new Date(member.last_login).toUTCString().slice(5, 22)})</span></> : <span className="muted">never</span>}</dd>
              <dt>Distance</dt>    <dd>{member.manual_distance != null ? `${member.manual_distance} tiles` : <span className="muted">unset</span>}</dd>
              <dt>Δ {days}d</dt>   <dd>{member._changes} growth day{member._changes !== 1 ? 's' : ''}</dd>
            </dl>
          </div>

          <div className="drawer-section">
            <h4>{days}-day daily Δ</h4>
            <BarChart history={history} days={days} width={400} height={48} />
            <table className="tbl" style={{ marginTop: 10, fontSize: 11 }}>
              <thead>
                <tr>
                  <th>Date</th>
                  <th className="right">Power</th>
                  <th className="right">Δ</th>
                </tr>
              </thead>
              <tbody>
                {rows.slice().reverse().map(r => (
                  <tr key={r.date}>
                    <td className="num">{r.date}</td>
                    <td className="right num">{r.pw != null ? formatPower(r.pw) : <span className="muted">—</span>}</td>
                    <td className="right num" style={{ color: r.delta > 0 ? 'var(--active)' : 'var(--fg-3)' }}>
                      {r.delta > 0 ? `+${formatPower(r.delta)}` : ''}
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>

          <div className="drawer-section">
            <h4>Outreach</h4>
            <pre className="drawer-template">{`Hey ${member.nickname}, haven't seen you online much — everything OK? Anything I can help with?`}</pre>
            <div style={{ marginTop: 8 }}>
              <button className="btn primary" onClick={handleCopyDM}>Copy DM template</button>
            </div>
          </div>
        </div>
      </aside>
    </>
  );
}

Object.assign(window, { ActivityPage });
