const db = require('../config/db');
const logger = require('../utils/logger');

/**
 * Logs an audit event to the audit_logs table.
 * @param {object} params
 * @param {number} params.userId      - The user performing the action
 * @param {string} params.action      - e.g. 'create', 'update', 'delete', 'login', 'logout'
 * @param {string} params.entityType  - e.g. 'product', 'transaction', 'customer', 'user'
 * @param {number|null} params.entityId - ID of the affected entity
 * @param {object|null} params.details - Additional context (JSON)
 * @param {string|null} params.ipAddress - Client IP
 */
async function logAudit({ userId, action, entityType, entityId = null, details = null, ipAddress = null }) {
  try {
    await db.query(
      `INSERT INTO audit_logs (user_id, action, entity_type, entity_id, details, ip_address)
       VALUES (?, ?, ?, ?, ?, ?)`,
      [userId, action, entityType, entityId, details ? JSON.stringify(details) : null, ipAddress]
    );
  } catch (err) {
    // Audit logging should never break the main flow
    logger.error('Audit log error:', err.message);
  }
}

/**
 * Express middleware factory that automatically logs the request action.
 * Attach AFTER the main controller so we only log successful operations.
 *
 * Usage:
 *   router.post('/', ctrl.create, auditMiddleware('create', 'product'));
 *
 * For cases where entity_id comes from the response or params, this
 * middleware reads from res.locals.auditEntityId or req.params.id.
 */
function auditMiddleware(action, entityType) {
  return (req, res, next) => {
    // Only log if response was successful (2xx)
    const originalJson = res.json.bind(res);
    res.json = function (body) {
      // Determine entity ID from various sources
      const entityId = res.locals?.auditEntityId
        || body?.id
        || body?.data?.id
        || req.params?.id
        || null;

      const details = {};
      if (req.method === 'POST' || req.method === 'PUT' || req.method === 'PATCH') {
        // Capture a sanitized copy (exclude passwords)
        const sanitized = { ...req.body };
        delete sanitized.password;
        delete sanitized.password_hash;
        delete sanitized.pin;
        delete sanitized.pin_hash;
        delete sanitized.current_password;
        delete sanitized.new_password;
        details.body = sanitized;
      }
      if (req.method === 'DELETE') {
        details.deleted = true;
      }

      if (req.user?.id) {
        logAudit({
          userId: req.user.id,
          action,
          entityType,
          entityId: entityId ? parseInt(entityId, 10) || null : null,
          details: Object.keys(details).length > 0 ? details : null,
          ipAddress: req.ip || req.connection?.remoteAddress,
        });
      }

      return originalJson(body);
    };
    next();
  };
}

/**
 * Helper to log audit directly from a controller (for transactional flows).
 */
function logAuditFromReq(req, action, entityType, entityId, extraDetails = {}) {
  return logAudit({
    userId: req.user?.id,
    action,
    entityType,
    entityId,
    details: Object.keys(extraDetails).length > 0 ? extraDetails : null,
    ipAddress: req.ip || req.connection?.remoteAddress,
  });
}

module.exports = { logAudit, auditMiddleware, logAuditFromReq };
