/**
 * jobs/logRotation.js
 *
 * Tiny log rotation. The structured logger (middleware/logger.js)
 * appends to data/server.log and the error stream appends to
 * data/server-err.log. Without rotation both grow forever; a busy
 * day can push them past 100MB. Passengers on cPanel + LiteSpeed
 * can't easily truncate a file the running process has open (same
 * WAL inode trap we hit with the DB), so the safe pattern is:
 *
 *   1. Check size on startup + every hour.
 *   2. If > MAX_BYTES, rename:
 *         server.log      → server.log.1
 *         server.log.1    → server.log.2
 *         ...
 *         server.log.4    → server.log.5
 *         server.log.5    → DELETED (keep 5 generations)
 *   3. The logger's `fs.appendFileSync` will lazily create the new
 *      server.log on the next write — no need to touch it from
 *      here.
 *
 * Set NCII_LOG_MAX_BYTES=20971520 (20MB) to override.
 */

'use strict';

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

const DATA_DIR = path.resolve(__dirname, '..', 'data');
const FILES = ['server.log', 'server-err.log'];
const KEEP = 5;
const MAX_BYTES = parseInt(process.env.NCII_LOG_MAX_BYTES, 10) || (10 * 1024 * 1024);
const CHECK_MS = 60 * 60 * 1000;   // hourly

function shift(name) {
  // server.log.4 → server.log.5, ..., server.log → server.log.1
  for (let i = KEEP - 1; i >= 0; i--) {
    const from = path.join(DATA_DIR, i === 0 ? name : `${name}.${i}`);
    const to   = path.join(DATA_DIR, `${name}.${i + 1}`);
    if (fs.existsSync(from)) {
      if (i === KEEP - 1) {
        try { fs.unlinkSync(from); } catch (_) {}
      } else {
        try { fs.renameSync(from, to); } catch (e) {
          console.warn('[logRotation] rename failed:', from, '→', to, e.message);
        }
      }
    }
  }
}

function rotate(name) {
  const full = path.join(DATA_DIR, name);
  if (!fs.existsSync(full)) return false;
  let sz;
  try { sz = fs.statSync(full).size; } catch (_) { return false; }
  if (sz < MAX_BYTES) return false;
  console.log(`[logRotation] rotating ${name} (${(sz/1024/1024).toFixed(2)}MB)`);
  shift(name);
  return true;
}

function tick() {
  let rotated = 0;
  for (const f of FILES) {
    if (rotate(f)) rotated++;
  }
  return rotated;
}

function start() {
  // Don't touch logs at require() time (logger isn't initialised yet
  // from this file's POV). Defer to the next tick.
  setImmediate(() => {
    try { tick(); } catch (e) { console.warn('[logRotation] initial tick failed:', e.message); }
  });
  setInterval(() => {
    try { tick(); } catch (e) { console.warn('[logRotation] tick failed:', e.message); }
  }, CHECK_MS);
  console.log(`[logRotation] started (max=${(MAX_BYTES/1024/1024).toFixed(1)}MB, keep=${KEEP}, every ${CHECK_MS/3600000}h)`);
}

module.exports = { start, tick, rotate, MAX_BYTES, KEEP };