<?php
function logAuditTrail($pdo, $userId, $action, $entity, $entityId = null, $changes = null, $ipAddress = null) {
    // Validate required fields
    if (empty($userId) || empty($action) || empty($entity)) {
        throw new InvalidArgumentException("User ID, action, and entity are required.");
    }

    // Sanitize user ID
    $userId = filter_var($userId, FILTER_VALIDATE_INT);
    if ($userId === false) {
        throw new InvalidArgumentException("User ID must be a valid integer.");
    }

    // Sanitize changes (ensure it's a JSON string)
    if ($changes !== null && !is_string($changes)) {
        // Exclude sensitive fields from logging
        $changes = array_filter($changes, function ($key) {
            return !in_array($key, ['password', 'credit_card', 'ssn']); // Add more sensitive fields as needed
        }, ARRAY_FILTER_USE_KEY);
        $changes = json_encode($changes);
    }

    // Sanitize IP address
    $ipAddress = $ipAddress ?? $_SERVER['REMOTE_ADDR'];
    if (!filter_var($ipAddress, FILTER_VALIDATE_IP)) {
        $ipAddress = '0.0.0.0'; // Fallback for invalid IPs
    }

    try {
        // Prepare the SQL statement
        $stmt = $pdo->prepare("
            INSERT INTO audit_trail 
            (user_id, action, entity, entity_id, changes, ip_address, created_at)
            VALUES 
            (:user_id, :action, :entity, :entity_id, :changes, :ip_address, NOW())
        ");

        // Execute the statement with sanitized data
        $stmt->execute([
            'user_id' => $userId,
            'action' => $action,
            'entity' => $entity,
            'entity_id' => $entityId,
            'changes' => $changes,
            'ip_address' => $ipAddress
        ]);

        return true; // Return true on success
    } catch (PDOException $e) {
        // Log the error and rethrow the exception
        error_log("Failed to log audit trail: " . $e->getMessage());
        throw new RuntimeException("Failed to log audit trail: " . $e->getMessage());
    }
}