<?php
/**
 * Responsible for logging.
 *
 * @package    wp2fa
 * @subpackage utils
 * @copyright  2026 Melapress
 * @license    https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0
 * @link       https://wordpress.org/plugins/wp-2fa/
 * @since      1.4.2
 */

declare(strict_types=1);

namespace WP2FA\Utils;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

if ( ! class_exists( '\WP2FA\Utils\Debugging' ) ) {
	/**
	 * Utility class for creating modal popup markup.
	 *
	 * @package WP2FA\Utils
	 *
	 * @since 1.4.2
	 */
	class Debugging {

		/**
		 * Local cache for the logging dir so that it doesn't need to be repopulated each time get_logging_dir_path is called.
		 *
		 * @var string
		 *
		 * @since 1.4.2
		 */
		private static $logging_dir_path = '';

		/**
		 * Retrieve the logging status
		 *
		 * @return boolean
		 *
		 * @since 1.4.2
		 */
		private static function is_logging_enabled() {
			/**
			 * Enables / Disables the logging for the plugin.
			 *
			 * @param bool $disabled - Default logging for the plugin.
			 */
			return apply_filters( WP_2FA_PREFIX . 'logging_enabled', false );
		}

		/**
		 * Logs the given message
		 *
		 * @param string $message - The message to log.
		 *
		 * @return void
		 *
		 * @since 1.4.2
		 */
		public static function log( $message ) {
			if ( self::is_logging_enabled() ) {
				self::write_to_log( self::get_log_timestamp() . "\n" . sanitize_text_field( $message ) . "\n" . __( 'Current memory usage: ', 'wp-2fa' ) . memory_get_usage( true ) . "\n" );
			}
		}

		/**
		 * Retrieves the path to the log file
		 *
		 * @return string
		 *
		 * @since 1.4.2
		 */
		private static function get_logging_dir_path() {
			if ( strlen( self::$logging_dir_path ) === 0 ) {
				$uploads_dir            = wp_upload_dir( null, false );
				self::$logging_dir_path = trailingslashit( trailingslashit( $uploads_dir['basedir'] ) . WP_2FA_LOGS_DIR );
			}

			return self::$logging_dir_path;
		}

		/**
		 * Write data to log file.
		 *
		 * @param string $data     - Data to write to file.
		 * @param bool   $override - Set to true if overriding the file.
		 *
		 * @return bool
		 *
		 * @since 1.4.2
		 */
		private static function write_to_log( $data, $override = false ) {
			$logging_dir_path = self::get_logging_dir_path();
			if ( ! is_dir( $logging_dir_path ) ) {
				self::create_index_file();
				self::create_htaccess_file();
			}

			$log_file_name = gmdate( 'Y-m-d' );

			return self::write_to_file( 'wp-2fa-debug-' . $log_file_name . '-' . self::get_random_file_string_addon() . '.log', $data, $override );
		}

		/**
		 * Create an index.php file, if none exists, in order to
		 * avoid directory listing in the specified directory.
		 *
		 * @return bool
		 *
		 * @since 1.4.2
		 */
		private static function create_index_file() {
			return self::write_to_file( 'index.php', '<?php // Silence is golden' );
		}

		/**
		 * Create an .htaccess file, if none exists, in order to
		 * block access to directory listing in the specified directory.
		 *
		 * @return bool
		 *
		 * @since 1.4.2
		 */
		private static function create_htaccess_file() {
			return self::write_to_file( '.htaccess', 'Deny from all' );
		}

		/**
		 * Write data to log file in the uploads directory.
		 *
		 * @param string $filename - File name.
		 * @param string $content  - Contents of the file.
		 * @param bool   $override - (Optional) True if overriding file contents.
		 *
		 * @return bool
		 *
		 * @since 1.4.2
		 */
		private static function write_to_file( $filename, $content, $override = false ) {
			global $wp_filesystem;
			require_once ABSPATH . 'wp-admin/includes/file.php';
			WP_Filesystem();

			$logging_dir = self::get_logging_dir_path();

			$result = false;

			if ( ! is_dir( $logging_dir ) ) {
				if ( false === wp_mkdir_p( $logging_dir ) ) {
					return false;
				}
			}

			$filepath = $logging_dir . $filename;
			if ( ! $wp_filesystem->exists( $filepath ) || $override ) {
				$result = $wp_filesystem->put_contents( $filepath, $content, FS_CHMOD_FILE );
			} else {
				$existing_content = $wp_filesystem->get_contents( $filepath );
				$result           = $wp_filesystem->put_contents( $filepath, $existing_content . $content, FS_CHMOD_FILE );
			}

			return $result;
		}

		/**
		 * Returns the timestamp for log files.
		 *
		 * @return string
		 *
		 * @since 1.4.2
		 */
		private static function get_log_timestamp() {
			return '[' . gmdate( 'd-M-Y H:i:s' ) . ' UTC]';
		}

		/**
		 * Generates a short random string which is used to generate log file name.
		 *
		 * @return string
		 *
		 * @since 2.8.0
		 */
		private static function get_random_file_string_addon(): string {
			$rnd_string = Settings_Utils::get_option( 'debug_name', false );
			if ( ! $rnd_string ) {
				$rnd_string = (string) \wp_generate_password( 20, false, false );
				Settings_Utils::update_option( 'debug_name', $rnd_string );
			}

			return sanitize_text_field( $rnd_string );
		}
	}
}
