<?php
/**
 * Logs debug data to a file. Here is an example usage
 * global $aio_wp_security;
 * $aio_wp_security->debug_logger->log_debug("Log messaged goes here");
 */
if (!defined('ABSPATH')) {
	exit;//Exit if accessed directly
}

class AIOWPSecurity_Logger {

	private $debug_enabled = false;

	private $debug_readable_level = array('SUCCESS','STATUS','NOTICE','WARNING','FAILURE','CRITICAL');
 
	public function __construct($debug_enabled) {
		$this->debug_enabled = $debug_enabled;
	}
	
	/**
	 * Translates the level code to its readable form
	 *
	 * @param  integer $level_code - The level code to translate (e.g: 2)
	 * @return string         - The level as its readable value (e.g: NOTICE)
	 */
	private function get_readable_level_from_code($level_code) {
		return isset($this->debug_readable_level[$level_code]) ? $this->debug_readable_level[$level_code] : 'UNKNOWN';
	}

	/**
	 * Clears the debug logs
	 *
	 * @return int|WP_Error     the amount of records deleted or WP_Error if query failed
	 */
	public function clear_logs() {
		global $wpdb;

		$debug_log_tbl = AIOWPSEC_TBL_DEBUG_LOG;

		if (is_super_admin()) {
			$ret = $wpdb->query("DELETE FROM $debug_log_tbl"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- We can't use %i because our plugin supports wordpress < 6.2.
		} else {
			$ret = $wpdb->query($wpdb->prepare("DELETE FROM $debug_log_tbl WHERE site_id = %d", get_current_blog_id())); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- We can't use %i because our plugin supports wordpress < 6.2.
		}

		if (false === $ret) {
			$error_msg = empty($wpdb->last_error) ? __('Unable to get the reason why', 'all-in-one-wp-security-and-firewall') : $wpdb->last_error;
			$ret = new WP_Error('db_unable_delete', __('Unable to clear the logs', 'all-in-one-wp-security-and-firewall'), $error_msg);
		}

		return $ret;
	}
	
	/**
	 * Logs the debug messages to the database
	 *
	 * @param string  $message    - The main debug message
	 * @param integer $level_code - The level code which indicates the severity of the message
	 * @param string  $type       - The type of debug message. Separates general debug messages from those generated by the cron, for example.
	 * @return void
	 */
	public function log_debug($message, $level_code = 0, $type = 'debug') {

		if (!$this->debug_enabled) {
			return;
		}

		global $wpdb;
		$debug_tbl_name = AIOWPSEC_TBL_DEBUG_LOG;

		$data = array(
			'created' => current_time('mysql'),
			'level' => $this->get_readable_level_from_code($level_code),
			'network_id' => get_current_network_id(),
			'site_id' => get_current_blog_id(),
			'message' => $message,
			'type' => $type,
		);

		$ret = $wpdb->query($wpdb->prepare("INSERT INTO ".$debug_tbl_name." (created, logtime, level, network_id, site_id, message,  type) VALUES (%s, UNIX_TIMESTAMP(), %s, %d, %d, %s, %s)", $data['created'], $data['level'], $data['network_id'], $data['site_id'], $data['message'], $data['type'])); // phpcs:ignore WordPress.DB.DirectDatabaseQuery, WordPress.DB.PreparedSQL.NotPrepared -- We can't use %i because our plugin supports wordpress < 6.2.
		if (false === $ret) {
			$error_msg = empty($wpdb->last_error) ? 'Could not write to the debug log' : $wpdb->last_error;
			error_log("All In One WP Security : {$error_msg}"); // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log -- We can't replace error_log with our debug logger here because the debug logger has failed.
		}
	}
 
	/**
	 * Logs the debug messages that relate to the cron
	 *
	 * @param string  $message    - The main debug message
	 * @param integer $level_code - The level code which indicates the severity of the message
	 * @return void
	 */
	public function log_debug_cron($message, $level_code = 0) {
		$this->log_debug($message, $level_code, 'cron_debug');
	}


}
