'use strict';

// Rolling request log for Syncro API calls.
// Shared between server.js (writes) and auth/admin.js (reads).

const fs   = require('fs');
const path = require('path');

const PERSIST_PATH   = path.join(__dirname, 'data', 'syncro-history.json');
const SEVEN_DAYS_MS  = 7 * 24 * 60 * 60 * 1000;
const PERSIST_INTERVAL_MS = 60_000; // flush to disk at most once per minute

const _log     = [];          // timestamps for rolling 60s count
const _buckets = new Map();   // minuteTs (ms) → request count

// ── Load persisted history on startup ────────────────────────────────────────
(function _loadHistory() {
  try {
    const raw  = fs.readFileSync(PERSIST_PATH, 'utf8');
    const data = JSON.parse(raw);
    const cutoff = Date.now() - SEVEN_DAYS_MS;
    for (const [tsStr, count] of Object.entries(data)) {
      const ts = Number(tsStr);
      if (ts >= cutoff) _buckets.set(ts, count);
    }
  } catch (_) {
    // File missing or corrupt — start fresh, no problem
  }
})();

// ── Persist helper ────────────────────────────────────────────────────────────
let _persistTimer = null;

function _schedulePersist() {
  if (_persistTimer) return;
  _persistTimer = setTimeout(() => {
    _persistTimer = null;
    _flushToDisk();
  }, PERSIST_INTERVAL_MS);
}

function _flushToDisk() {
  try {
    const obj = {};
    for (const [ts, count] of _buckets) obj[ts] = count;
    fs.writeFileSync(PERSIST_PATH, JSON.stringify(obj));
  } catch (_) {}
}

// ── Public API ────────────────────────────────────────────────────────────────
function logRequest() {
  const now = Date.now();

  // Rolling 60s log
  _log.push(now);
  while (_log.length && _log[0] < now - 60_000) _log.shift();

  // Per-minute bucket
  const minuteTs = Math.floor(now / 60_000) * 60_000;
  _buckets.set(minuteTs, (_buckets.get(minuteTs) ?? 0) + 1);

  // Prune buckets older than 7 days (Map is in insertion/chronological order)
  const cutoff = now - SEVEN_DAYS_MS;
  for (const ts of _buckets.keys()) {
    if (ts < cutoff) _buckets.delete(ts);
    else break;
  }

  _schedulePersist();
}

function getUsage() {
  const now = Date.now();
  while (_log.length && _log[0] < now - 60_000) _log.shift();
  return _log.length;
}

// Returns an array of { ts, count } for the given window (capped at 7 days).
// Already in ascending chronological order.
function getHistory(windowMs) {
  const now    = Date.now();
  const cutoff = now - Math.min(windowMs, SEVEN_DAYS_MS);
  const result = [];
  for (const [ts, count] of _buckets) {
    if (ts >= cutoff) result.push({ ts, count });
  }
  return result;
}

// Returns the number of minute buckets in the last 7 days where requests >= limit.
function getLimitHits(limit) {
  const cutoff = Date.now() - SEVEN_DAYS_MS;
  let hits = 0;
  for (const [ts, count] of _buckets) {
    if (ts >= cutoff && count >= limit) hits++;
  }
  return hits;
}

module.exports = { logRequest, getUsage, getHistory, getLimitHits };
