// ─────────────────────────────────────────────────────────────
// src/middleware.js — rate limiting + requireAuth.
//
// Rate limiting is per-key (usually per-IP) with a sliding window
// stored in SQLite. Enough to stop scripted abuse without needing
// Redis. For real-deal DDoS protection, put Cloudflare / a WAF in
// front. For a self-hosted invite-only tool, this is plenty.
// ─────────────────────────────────────────────────────────────
import { q } from './db.js';
import { currentSession } from './sessions.js';

/**
 * rateLimit({ key, max, windowMs })
 *   key      — string OR function(req) → string
 *   max      — allowed requests per window
 *   windowMs — window size in milliseconds
 *
 * Returns 429 once the counter crosses max. Counter resets automatically
 * at window_end via the cleanup sweep in db.js.
 */
export function rateLimit({ key, max, windowMs }) {
  return (req, res, next) => {
    const id = typeof key === 'function' ? key(req) : key;
    const now = Date.now();
    const row = q.getRate.get(id);

    if (!row || row.window_end < now) {
      q.setRate.run(id, 1, now + windowMs);
      return next();
    }
    if (row.count >= max) {
      return res.status(429).end();
    }
    q.setRate.run(id, row.count + 1, row.window_end);
    next();
  };
}

/**
 * requireAuth — gate any route behind a valid session cookie.
 *
 * - For requests that accept HTML: redirect to "/" (entrance page).
 * - For JSON/API requests: return 401.
 *
 * Sets req.session = { id, email, issued_at, expires_at } on success.
 */
export function requireAuth(req, res, next) {
  const session = currentSession(req);
  if (!session) {
    if (req.accepts('html') && !req.xhr) {
      return res.redirect(302, '/');
    }
    return res.status(401).end();
  }
  req.session = session;
  next();
}
