// Sliding session window for the admin panel: the access token is only valid for
// 15 minutes (see crates/auth/src/jwt.rs), matching the backend's employee_sessions
// expiry policy. While the admin is active we silently exchange the refresh-token
// cookie for a new access token before the old one expires; once idle for 15
// minutes we stop refreshing and let the token expire naturally, so the existing
// session-expired dialog (src/lib/session-expired.ts) kicks in on the next request.
const IDLE_LIMIT_MS = 15 * 60 * 1000;
const CHECK_INTERVAL_MS = 3 * 60 * 1000;
const ACTIVITY_EVENTS = ['mousedown', 'keydown', 'scroll', 'touchstart'] as const;

let lastActivityAt = Date.now();
let installed = false;

function markActivity(): void {
  lastActivityAt = Date.now();
}

async function refreshAccessToken(): Promise<void> {
  try {
    const res = await fetch('/api/admin/auth/refresh', {
      method: 'POST',
      credentials: 'include',
      headers: { Accept: 'application/json' },
    });
    if (!res.ok) return;
    const data = await res.json().catch(() => null);
    if (data?.access_token && typeof sessionStorage !== 'undefined') {
      sessionStorage.setItem('nxtgauge_admin_access_token', data.access_token);
    }
  } catch {
    // Network hiccup — the next successful check will catch up. If the token
    // does expire in the meantime, the session-expired dialog handles it.
  }
}

/** Idempotent — safe to call from every AdminShell mount. */
export function installSessionRefreshLoop(): void {
  if (installed || typeof window === 'undefined') return;
  installed = true;

  markActivity();
  for (const evt of ACTIVITY_EVENTS) {
    window.addEventListener(evt, markActivity, { passive: true });
  }

  setInterval(() => {
    if (Date.now() - lastActivityAt < IDLE_LIMIT_MS) {
      void refreshAccessToken();
    }
  }, CHECK_INTERVAL_MS);
}
