<?php
/**
 * PostGate Logger Class
 *
 * Centralized logging utility for PostGate plugin events.
 * Respects WordPress WP_DEBUG and WP_DEBUG_LOG settings.
 * Automatically sanitizes sensitive data to comply with WordPress.org standards.
 *
 * Usage:
 * PostGate_Logger::error( 'Error message', [ 'order_id' => 123 ] );
 * PostGate_Logger::warning( 'Warning message', [ 'post_id' => 456 ] );
 * PostGate_Logger::info( 'Info message', [ 'event' => 'webhook_received' ] );
 *
 * @package PostGate
 * @subpackage Utilities
 * @since 1.0.0
 * @author QodeSphere
 * @license GPL-2.0+
 */

defined( 'ABSPATH' ) || exit;

/**
 * PostGate Logger
 *
 * Provides centralized logging with multiple severity levels.
 * All logs are conditional on WP_DEBUG and WP_DEBUG_LOG settings.
 * Sensitive data is automatically sanitized before logging.
 *
 * @since 1.0.0
 */
class PostGate_Logger {

	/**
	 * Log levels.
	 *
	 * @since 1.0.0
	 */
	private const LEVEL_ERROR = 'ERROR';
	private const LEVEL_WARNING = 'WARNING';
	private const LEVEL_INFO = 'INFO';

	/**
	 * List of sensitive field names to remove from context.
	 *
	 * @since 1.0.0
	 */
	private static $sensitive_keys = [
		'password',
		'token',
		'secret',
		'api_key',
		'card',
		'cvv',
		'ssn',
		'authorization',
		'access_token',
		'refresh_token',
		'webhook_secret',
	];

	/**
	 * Log an error message.
	 *
	 * Use for errors that require immediate attention and indicate something
	 * has failed that should not have failed.
	 *
	 * @since 1.0.0
	 *
	 * @param string $message The error message.
	 * @param array  $context Optional context data.
	 * @return void
	 */
	public static function error( $message, $context = [] ) {
		self::log( $message, $context, self::LEVEL_ERROR );
	}

	/**
	 * Log a warning message.
	 *
	 * Use for potentially harmful situations that should be reviewed but
	 * did not cause a failure.
	 *
	 * @since 1.0.0
	 *
	 * @param string $message The warning message.
	 * @param array  $context Optional context data.
	 * @return void
	 */
	public static function warning( $message, $context = [] ) {
		self::log( $message, $context, self::LEVEL_WARNING );
	}

	/**
	 * Log an informational message.
	 *
	 * Use for noteworthy but expected events that help trace program flow
	 * and state changes.
	 *
	 * @since 1.0.0
	 *
	 * @param string $message The info message.
	 * @param array  $context Optional context data.
	 * @return void
	 */
	public static function info( $message, $context = [] ) {
		self::log( $message, $context, self::LEVEL_INFO );
	}

	/**
	 * Core logging function.
	 *
	 * Checks debug settings, sanitizes context, and logs the message.
	 * Only logs if WP_DEBUG and WP_DEBUG_LOG are both enabled.
	 *
	 * @since 1.0.0
	 *
	 * @param string $message The log message.
	 * @param array  $context Optional context data.
	 * @param string $level   The log level (ERROR, WARNING, INFO).
	 * @return void
	 */
	private static function log( $message, $context = [], $level = self::LEVEL_INFO ) {
		// Only log if debug mode is enabled
		if ( ! self::is_debug_enabled() ) {
			return;
		}

		// Sanitize context to remove sensitive data
		$safe_context = self::sanitize_context( $context );

		// Build the log message with level prefix
		$log_message = sprintf(
			'[PostGate][%s] %s',
			$level,
			$message
		);

		// Append sanitized context if present
		if ( ! empty( $safe_context ) ) {
			$log_message .= ' | ' . wp_json_encode( $safe_context );
		}

		// Use WordPress error_log function
		// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
		error_log( $log_message );
	}

	/**
	 * Check if debug logging is enabled.
	 *
	 * Verifies that both WP_DEBUG and WP_DEBUG_LOG are defined and true.
	 *
	 * @since 1.0.0
	 *
	 * @return bool True if debug logging is enabled, false otherwise.
	 */
	private static function is_debug_enabled() {
		return defined( 'WP_DEBUG' ) && WP_DEBUG &&
			defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG;
	}

	/**
	 * Sanitize context data by removing sensitive information.
	 *
	 * Removes any fields that might contain sensitive data such as
	 * passwords, tokens, API keys, or payment information.
	 *
	 * @since 1.0.0
	 *
	 * @param array $context The context array to sanitize.
	 * @return array The sanitized context array.
	 */
	private static function sanitize_context( $context ) {
		if ( ! is_array( $context ) ) {
			return [];
		}

		// Remove sensitive keys (case-insensitive)
		foreach ( self::$sensitive_keys as $key ) {
			unset( $context[ $key ] );
			// Also check for variations
			foreach ( $context as $k => $v ) {
				if ( stripos( $k, $key ) !== false ) {
					unset( $context[ $k ] );
				}
			}
		}

		return $context;
	}
}
