<?php
namespace EASYERLO\Inc;

defined('ABSPATH') || die('Hey, what are you doing here? You silly human!');

/**
 * Easy Error Log Ajax Class.
 *
 * This class handles all the AJAX requests for the Easy Error Log plugin.
 *
 * @package EASYERLO\Inc
 */
class EASYERLO_Ajax {

	/**
	 * Init class to all Ajax.
	 */
	public function init() {
		add_action('wp_ajax_clean_debug_log', array( $this, 'clean_debug_log_callback' ));
		add_action('wp_ajax_reset_debug_constant', array( $this, 'reset_debug_constant_callback' ));
		add_action('wp_ajax_toggle_debug_mode', array( $this, 'toggle_debug_mode_callback' ));
		add_action('wp_ajax_get_debug_mode_status', array( $this, 'get_debug_mode_status_callback' ));
		add_action('wp_ajax_download_debug_log', array( $this, 'download_debug_log_callback' ));
		add_action('wp_ajax_get_error_count', array( $this, 'get_error_count_callback' ));
		add_action('wp_ajax_check_debug_constants_status', array( $this, 'check_debug_constants_status_callback' ));
		add_action('wp_ajax_toggle_widgets_mode', array( $this, 'toggle_widgets_mode_callback' ));
		add_action('wp_ajax_get_widgets_mode_status', array( $this, 'get_widgets_mode_status_callback' ));
		add_action( 'wp_ajax_display_error_log', array( $this, 'display_error_log_callback' ) );
		add_action( 'wp_ajax_nopriv_display_error_log', array( $this, 'display_error_log_callback' ) );
		add_action('wp_ajax_get_file_content', array( $this, 'get_file_content_callback' ));
		add_action('wp_ajax_save_file_content', array( $this, 'save_file_content_callback' ));
	}

	/**
	 * AJAX callback function to display error log.
	 */
	public function display_error_log_callback() {
		// Check if we're in admin area.
		$is_admin = is_admin();

		// Only check widget mode for frontend requests.
		if ( ! $is_admin ) {
			$widgets_mode = get_option('fe_widgets_mode', 'false');
			if ( 'true' !== $widgets_mode ) {
				wp_die();
			}
		}

		$debug_log_paths = array(
			WP_CONTENT_DIR . '/debug.log',
			ABSPATH . 'debug.log',
		);

		$debug_log_path = '';
		foreach ( $debug_log_paths as $path ) {
			if ( file_exists($path) ) {
				$debug_log_path = $path;
				break;
			}
		}

		if ( file_exists($debug_log_path) ) {
			$debug_log_entries = file($debug_log_path, FILE_IGNORE_NEW_LINES);
			if ( empty($debug_log_entries) ) {
				echo '<div>' . esc_html__('Debug log empty. No errors found.', 'easy-error-log') . '</div>';
			} else {
				// Create array to store unique errors.
				$unique_errors = array();
				$current_entry = '';
				$current_timestamp = '';

				// Combine multi-line entries.
				foreach ( $debug_log_entries as $line ) {
					// Check if line starts with a timestamp.
					if ( preg_match('/^\[(.*?)\](.+)$/', $line, $matches) ) {
						// save previous entry.
						if ( '' !== $current_entry ) {
							$content_key = trim($current_entry);
							if ( ! isset($unique_errors[ $content_key ]) ) {
								// Extract file path and line number from the entry.
								$file_path = '';
								$line_number = '';
								if ( preg_match('/in (.+) on line (\d+)/', $current_entry, $location) ) {
									$file_path = $location[1];
									$line_number = $location[2];
								}

								$unique_errors[ $content_key ] = array(
									'timestamp' => $current_timestamp,
									'full_message' => "[$current_timestamp] " . $current_entry,
									'file_path' => $file_path,
									'line_number' => $line_number,
								);
							}
						}
						// Start new entry.
						$current_timestamp = $matches[1];
						$current_entry = $matches[2];
					} else {
						// Continuation of the current entry.
						$current_entry .= "\n" . $line;
					}
				}

				// Save the last entry.
				if ( '' !== $current_entry ) {
					$content_key = trim($current_entry);
					if ( ! isset($unique_errors[ $content_key ]) ) {
						// Extract file path and line number from the last entry.
						$file_path = '';
						$line_number = '';
						if ( preg_match('/in (.+) on line (\d+)/', $current_entry, $location) ) {
							$file_path = $location[1];
							$line_number = $location[2];
						}

						$unique_errors[ $content_key ] = array(
							'timestamp' => $current_timestamp,
							'full_message' => "[$current_timestamp] " . $current_entry,
							'file_path' => $file_path,
							'line_number' => $line_number,
						);
					}
				}

				// Display the unique entries.
				foreach ( $unique_errors as $error ) {
					$editor_link = '';
					if ( $error['file_path'] && $error['line_number'] ) {
						// Always show the Open button, regardless of local or live site
						$editor_link = sprintf(
							'<button class="open-in-editor" data-path="%s" data-line="%s">Open</button>',
							esc_attr($error['file_path']),
							esc_attr($error['line_number'])
						);
					}

					echo "<div class='debug-log-errors'>"
						. nl2br(esc_html($error['full_message']))
						. wp_kses($editor_link, array(
							'button' => array(
								'class' => array(),
								'data-path' => array(),
								'data-line' => array(),
							),
						))
						. '</div>';
				}
			}
		} else {
			echo '<div>' . esc_html__('Debug log file not found.', 'easy-error-log') . '</div>';
		}
		die();
	}


	/**
	 * AJAX callback function to clean debug log.
	 */
	public function clean_debug_log_callback() {
		$debug_log_paths = array(
			WP_CONTENT_DIR . '/debug.log',
			ABSPATH . 'debug.log',
		);

		$debug_log_path = '';
		foreach ( $debug_log_paths as $path ) {
			if ( file_exists($path) ) {
				$debug_log_path = $path;
				break;
			}
		}

		if ( file_exists( $debug_log_path ) ) {
			file_put_contents( $debug_log_path, '' );
			echo '<p>' . esc_html__( 'Debug log cleaned successfully.', 'easy-error-log' ) . '</p>';
		} else {
			echo '<p>' . esc_html__( 'Debug log file not found.', 'easy-error-log' ) . '</p>';
		}
		die();
	}


	/**
	 * Reset debug constant callback.
	 */
	public function reset_debug_constant_callback() {
		update_option('easyerlo_debug_mode_enabled', ''); // Reset the option value.
		echo esc_html__('Debug constant reset successfully.', 'easy-error-log'); // Return success message.
		wp_die();
	}


	/**
	 * Callback function for toggling debug mode.
	 */
	public function toggle_debug_mode_callback() {
		$config_path = ABSPATH . 'wp-config.php';
		if ( file_exists( $config_path ) ) {
			$config_contents = file_get_contents( $config_path );

			// Check if WP_DEBUG is defined.
			if ( preg_match( '/define\s*\(\s*\'WP_DEBUG\'\s*,\s*([^\)]+)\);/s', $config_contents, $matches ) ) {
				// Toggle WP_DEBUG value.
				$new_debug_value = ( 'true' === $matches[1] ) ? 'false' : 'true';
				$config_contents = preg_replace( '/define\s*\(\s*\'WP_DEBUG\'\s*,\s*([^\)]+)\);/s', "define('WP_DEBUG', $new_debug_value);", $config_contents );

				// Toggle WP_DEBUG_LOG value.
				if ( 'false' === $new_debug_value ) {
					$config_contents = preg_replace('/define\s*\(\s*\'WP_DEBUG_LOG\'\s*,\s*([^\)]+)\);/s', "define('WP_DEBUG_LOG', false);", $config_contents);
				} else {
					$config_contents = preg_replace('/define\s*\(\s*\'WP_DEBUG_LOG\'\s*,\s*([^\)]+)\);/s', "define('WP_DEBUG_LOG', true);", $config_contents);
				}

				// Update wp-config.php with the new values.
				file_put_contents( $config_path, $config_contents );
				$debug_status = ( 'true' === $new_debug_value ) ? 'ON' : 'OFF';

				printf(
					// Translators: %s is the debug status (ON or OFF).
					esc_html__( 'Log: %s', 'easy-error-log' ),
					esc_html( $debug_status )
				);

			} else {
				echo esc_html__( 'WP_DEBUG constant not found', 'easy-error-log' );
			}
		} else {
			echo esc_html__( 'wp-config not found.', 'easy-error-log' );
		}
		die();
	}


	/**
	 * AJAX callback function to get the current debug mode status.
	 */
	public function get_debug_mode_status_callback() {
		$debug_mode_status = ( defined( 'WP_DEBUG' ) && WP_DEBUG ) ? 'ON' : 'OFF';
		echo esc_html($debug_mode_status);
		wp_die();
	}

	/**
	 * AJAX callback function to download debug log.
	 */
	public function download_debug_log_callback() {
		$debug_log_paths = array(
			WP_CONTENT_DIR . '/debug.log',
			ABSPATH . 'debug.log',
		);

		$debug_log_path = '';
		foreach ( $debug_log_paths as $path ) {
			if ( file_exists($path) ) {
				$debug_log_path = $path;
				break;
			}
		}

		if ( file_exists( $debug_log_path ) ) {
			// Return the URL to the debug log file.
			echo esc_url( content_url( '/debug.log' ) );
		} else {
			echo esc_html__( 'Debug log file not found.', 'easy-error-log' );
		}
		wp_die();
	}

	/**
	 * Count errors.
	 */
	public function get_error_count_callback() {
		// Check if we're in admin area
		$is_admin = is_admin();

		// Only check widget mode for frontend requests
		if ( ! $is_admin ) {
			$widgets_mode = get_option('fe_widgets_mode', 'false');
			if ( 'true' !== $widgets_mode ) {
				wp_die();
			}
		}

		$debug_log_paths = array(
			WP_CONTENT_DIR . '/debug.log',
			ABSPATH . 'debug.log',
		);

		$debug_log_path = '';
		foreach ( $debug_log_paths as $path ) {
			if ( file_exists($path) ) {
				$debug_log_path = $path;
				break;
			}
		}

		$error_count = 0;
		if ( file_exists($debug_log_path) ) {
			$debug_log_entries = file( $debug_log_path, FILE_IGNORE_NEW_LINES );
			if ( ! empty($debug_log_entries) ) {
				// Count unique errors by combining multi-line entries
				$current_entry = '';
				$current_timestamp = '';
				$unique_errors = array();

				foreach ( $debug_log_entries as $line ) {
					if ( preg_match('/^\[(.*?)\](.+)$/', $line, $matches) ) {
						// Save previous entry
						if ( '' !== $current_entry ) {
							$content_key = trim($current_entry);
							if ( ! isset($unique_errors[ $content_key ]) ) {
								$unique_errors[ $content_key ] = true;
							}
						}
						// Start new entry
						$current_timestamp = $matches[1];
						$current_entry = $matches[2];
					} else {
						// Continuation of current entry
						$current_entry .= "\n" . $line;
					}
				}

				// Save the last entry
				if ( '' !== $current_entry ) {
					$content_key = trim($current_entry);
					if ( ! isset($unique_errors[ $content_key ]) ) {
						$unique_errors[ $content_key ] = true;
					}
				}

				$error_count = count($unique_errors);
			}
		}

		echo esc_html($error_count);
		wp_die();
	}


	/**
	 * Show status
	 */
	public function check_debug_constants_status_callback() {
		$status = array(
			'WP_DEBUG' => defined('WP_DEBUG') ? WP_DEBUG : 'Not Found',
			'WP_DEBUG_LOG' => defined('WP_DEBUG_LOG') ? WP_DEBUG_LOG : 'Not Found',
		);
		wp_send_json_success($status);
		wp_die();
	}

	/**
	 * Toggle widgets mode.
	 */
	public function toggle_widgets_mode_callback() {
		// Check the current value of the option.
		$widgets_mode = get_option( 'fe_widgets_mode', 'false' );

		// Toggle the value.
		if ( 'true' === $widgets_mode ) {
			$widgets_mode = 'false';
		} else {
			$widgets_mode = 'true';
		}

		// Update the option with the new value.
		update_option( 'fe_widgets_mode', $widgets_mode );

		// Send the new mode back as the response.
		wp_send_json_success( array( 'widgets_mode' => $widgets_mode ) );
	}

	/**
	 * Get widgets mode status.
	 */
	public function get_widgets_mode_status_callback() {
		// Get the current mode value.
		$widgets_mode = get_option( 'fe_widgets_mode', 'false' );
		wp_send_json_success( array( 'widgets_mode' => $widgets_mode ) );
	}

	/**
	 * AJAX callback function to get file content.
	 */
	public function get_file_content_callback() {
		
		if ( ! isset($_POST['nonce']) || ! wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'easyerlo_admin_nonce') ) {
			wp_send_json_error('Security check failed');
			return;
		}
		$file_path = isset($_POST['file_path']) ? sanitize_text_field(wp_unslash($_POST['file_path'])) : '';
		$line_number = isset($_POST['line_number']) ? intval($_POST['line_number']) : 0;

		if ( empty($file_path) ) {
			wp_send_json_error('File path is required');
			return;
		}

		// Check if file exists and is readable
		if ( ! file_exists($file_path) || ! is_readable($file_path) ) {
			wp_send_json_error('File not found or not readable');
			return;
		}

		// Get file content
		$content = file_get_contents($file_path);
		if ( $content === false ) {
			wp_send_json_error('Could not read file');
			return;
		}

		wp_send_json_success([
			'content' => $content,
			'line_number' => $line_number,
		]);
	}

	/**
	 * AJAX callback function to save file content.
	 */
	public function save_file_content_callback() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error( array(
				'message' => __( 'You do not have permission to perform this action', 'easy-error-log' ),
			) );
		}

		if ( ! isset($_POST['nonce']) || ! wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'easyerlo_admin_nonce') ) {
			wp_send_json_error('Security check failed');
			return;
		}

		$file_path = isset($_POST['file_path']) ? sanitize_text_field( wp_unslash($_POST['file_path']) ) : '';
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Raw content needed for code editor
		$content = isset($_POST['content']) ? wp_unslash($_POST['content']) : '';

		if ( empty($file_path) ) {
			wp_send_json_error('File path is required');
			return;
		}

		// Check if file exists and is writable
		if ( ! file_exists($file_path) || ! is_writable($file_path) ) {
			wp_send_json_error('File not found or not writable');
			return;
		}

		// Save file content
		$result = file_put_contents($file_path, $content);
		if ( $result === false ) {
			wp_send_json_error('Could not save file');
			return;
		}

		wp_send_json_success('File saved successfully');
	}
}
