const prisma = require('../lib/prisma');

/**
 * Factory that creates audit middleware for a given Prisma model.
 * On UPDATE: captures before/after diff.
 * On DELETE: captures the full record before deletion.
 *
 * @param {string} tableName - The human-readable table name for audit logs
 * @param {object} model     - The Prisma model delegate (e.g., prisma.experiment)
 * @param {string} idParam   - The route param name that holds the record id (default: 'id')
 */
function auditMiddleware(tableName, model, idParam = 'id') {
  return async (req, res, next) => {
    const recordId = req.params[idParam];
    if (!recordId) return next();

    try {
      const before = await model.findUnique({ where: { id: recordId } });
      if (!before) return next();

      // Attach before-state so route handlers can reference it if needed
      req._auditBefore = before;

      // Shared audit writer — called by both res.json and res.send interceptors
      async function writeAuditLog() {
        if (res.statusCode >= 200 && res.statusCode < 300) {
          try {
            const action = req.method === 'DELETE' ? 'DELETE' : 'UPDATE';
            const after = action === 'DELETE' ? null : await model.findUnique({ where: { id: recordId } });
            await prisma.auditLog.create({
              data: {
                table_name: tableName,
                record_id: recordId,
                action,
                changes: { before, after },
              },
            });
          } catch (auditErr) {
            console.error('Audit log write failed:', auditErr.message);
          }
        }
      }

      // Wrap res.json (used by JSON-returning routes)
      const originalJson = res.json.bind(res);
      res.json = async function (data) {
        await writeAuditLog();
        return originalJson(data);
      };

      // Wrap res.send (used by DELETE 204 routes)
      const originalSend = res.send.bind(res);
      res.send = async function (data) {
        await writeAuditLog();
        return originalSend(data);
      };

      next();
    } catch (err) {
      next(err);
    }
  };
}

module.exports = auditMiddleware;
