/**
 * routes/audit.js
 * Append-only audit log stored as NDJSON in data/audit.log.
 *
 * Exports:
 *   router          – Express router (mount at /api/audit in server.js)
 *   writeAudit(req, action, detail)  – call from any other route to record an event
 */
const express = require('express');
const fs      = require('fs');
const path    = require('path');
const router  = express.Router();
const authMw  = require('../middleware/auth');

const AUDIT_LOG = path.join(__dirname, '../data/audit.log');
const MAX_LINES = 5000; // keep the last N entries (trim on startup / clear)

// ── Core writer ────────────────────────────────────────────
function writeAudit(req, action, detail) {
  // req can be a full Express request or a plain object { username, ip }
  const username = (req && req.user && req.user.username) || (req && req.username) || 'system';
  const ip       = (req && req.ip) || (req && req.headers && req.headers['x-forwarded-for']) || '–';
  const entry = {
    time:   new Date().toISOString(),
    user:   username,
    ip:     ip.replace('::ffff:', ''), // normalise IPv4-mapped IPv6
    action,
    detail: detail || ''
  };
  try {
    fs.mkdirSync(path.dirname(AUDIT_LOG), { recursive: true });
    fs.appendFileSync(AUDIT_LOG, JSON.stringify(entry) + '\n');
  } catch (e) {
    console.error('[audit] Failed to write audit.log:', e.message);
  }
}

// ── GET /api/audit — return entries (newest first) ─────────
router.get('/', authMw, (req, res) => {
  if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin only' });
  try {
    if (!fs.existsSync(AUDIT_LOG)) return res.json([]);
    const limit = Math.min(parseInt(req.query.limit) || 200, 1000);
    const user  = req.query.user  || '';
    const action= req.query.action|| '';

    let lines = fs.readFileSync(AUDIT_LOG, 'utf8')
      .split('\n')
      .filter(Boolean)
      .map(l => { try { return JSON.parse(l); } catch { return null; } })
      .filter(Boolean);

    if (user)   lines = lines.filter(e => e.user   === user);
    if (action) lines = lines.filter(e => e.action === action);

    lines.reverse(); // newest first
    res.json(lines.slice(0, limit));
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ── DELETE /api/audit — clear log (admin only) ─────────────
router.delete('/', authMw, (req, res) => {
  if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin only' });
  try {
    fs.writeFileSync(AUDIT_LOG, '');
    writeAudit(req, 'audit.clear', 'Audit log cleared');
    res.json({ ok: true });
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

// ── GET /api/audit/users — distinct usernames for filter ───
router.get('/users', authMw, (req, res) => {
  if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin only' });
  try {
    if (!fs.existsSync(AUDIT_LOG)) return res.json([]);
    const users = new Set();
    fs.readFileSync(AUDIT_LOG, 'utf8')
      .split('\n').filter(Boolean)
      .forEach(l => { try { users.add(JSON.parse(l).user); } catch {} });
    res.json([...users].sort());
  } catch (e) {
    res.status(500).json({ error: e.message });
  }
});

module.exports = router;
module.exports.writeAudit = writeAudit;