<?php
/**
 * System Information Collector
 *
 * Collects detailed system information for diagnosing performance bottlenecks.
 *
 * @package MaplePress
 */

class MaplePress_System_Info {

	/**
	 * Get all system information.
	 *
	 * @return array System information array.
	 */
	public static function get_all_info() {
		return array(
			'php'          => self::get_php_info(),
			'php_fpm'      => self::get_php_fpm_info(),
			'server'       => self::get_server_info(),
			'wordpress'    => self::get_wordpress_info(),
			'database'     => self::get_database_info(),
			'performance'  => self::get_performance_info(),
		);
	}

	/**
	 * Get PHP configuration information.
	 *
	 * @return array PHP configuration.
	 */
	private static function get_php_info() {
		return array(
			'version'              => PHP_VERSION,
			'sapi'                 => php_sapi_name(),
			'memory_limit'         => ini_get( 'memory_limit' ),
			'max_execution_time'   => ini_get( 'max_execution_time' ),
			'max_input_time'       => ini_get( 'max_input_time' ),
			'post_max_size'        => ini_get( 'post_max_size' ),
			'upload_max_filesize'  => ini_get( 'upload_max_filesize' ),
			'max_input_vars'       => ini_get( 'max_input_vars' ),
			'display_errors'       => ini_get( 'display_errors' ),
			'error_reporting'      => ini_get( 'error_reporting' ),
			'opcache_enabled'      => function_exists( 'opcache_get_status' ) && opcache_get_status() !== false,
			'opcache_status'       => function_exists( 'opcache_get_status' ) ? opcache_get_status() : null,
		);
	}

	/**
	 * Get PHP-FPM configuration information.
	 *
	 * @return array PHP-FPM configuration.
	 */
	private static function get_php_fpm_info() {
		$info = array(
			'is_fpm'              => false,
			'pool_name'           => 'N/A',
			'pm_type'             => 'N/A',
			'max_children'        => 'N/A',
			'start_servers'       => 'N/A',
			'min_spare_servers'   => 'N/A',
			'max_spare_servers'   => 'N/A',
			'max_requests'        => 'N/A',
			'status_url'          => 'N/A',
			'active_processes'    => 'N/A',
			'total_processes'     => 'N/A',
			'idle_processes'      => 'N/A',
			'listen_queue'        => 'N/A',
			'listen_queue_len'    => 'N/A',
			'config_file'         => 'N/A',
		);

		// Check if running under PHP-FPM
		if ( php_sapi_name() === 'fpm-fcgi' || php_sapi_name() === 'cgi-fcgi' ) {
			$info['is_fpm'] = true;

			// Try to find PHP-FPM config file
			$possible_config_paths = array(
				'/etc/php/' . PHP_MAJOR_VERSION . '.' . PHP_MINOR_VERSION . '/fpm/pool.d/www.conf',
				'/usr/local/etc/php-fpm.d/www.conf',
				'/etc/php-fpm.d/www.conf',
				'/etc/php/fpm/pool.d/www.conf',
			);

			foreach ( $possible_config_paths as $path ) {
				if ( file_exists( $path ) && is_readable( $path ) ) {
					$info['config_file'] = $path;
					$config = self::parse_php_fpm_config( $path );
					if ( $config ) {
						$info = array_merge( $info, $config );
					}
					break;
				}
			}

			// Try to get PHP-FPM status via FastCGI
			$status = self::get_php_fpm_status();
			if ( $status ) {
				$info = array_merge( $info, $status );
			}
		}

		return $info;
	}

	/**
	 * Parse PHP-FPM configuration file.
	 *
	 * @param string $config_file Path to config file.
	 * @return array|null Parsed configuration or null.
	 */
	private static function parse_php_fpm_config( $config_file ) {
		$config = array();

		$content = file_get_contents( $config_file );
		if ( ! $content ) {
			return null;
		}

		// Parse key configuration values (ignore comments after values)
		$patterns = array(
			'pool_name'          => '/^\[([^\]]+)\]/m',
			'pm_type'            => '/^pm\s*=\s*(\w+)/m',
			'max_children'       => '/^pm\.max_children\s*=\s*(\d+)/m',
			'start_servers'      => '/^pm\.start_servers\s*=\s*(\d+)/m',
			'min_spare_servers'  => '/^pm\.min_spare_servers\s*=\s*(\d+)/m',
			'max_spare_servers'  => '/^pm\.max_spare_servers\s*=\s*(\d+)/m',
			'max_requests'       => '/^pm\.max_requests\s*=\s*(\d+)/m',
		);

		foreach ( $patterns as $key => $pattern ) {
			if ( preg_match( $pattern, $content, $matches ) ) {
				$config[ $key ] = trim( $matches[1] );
			}
		}

		return $config;
	}

	/**
	 * Get PHP-FPM status from status endpoint.
	 *
	 * @return array|null Status information or null.
	 */
	private static function get_php_fpm_status() {
		// Try common PHP-FPM status URLs
		$status_urls = array(
			'http://localhost/fpm-status',
			'http://127.0.0.1/fpm-status',
			'http://localhost/status',
		);

		foreach ( $status_urls as $url ) {
			$response = wp_remote_get( $url . '?json' );
			if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
				$body = wp_remote_retrieve_body( $response );
				$data = json_decode( $body, true );
				if ( $data ) {
					return array(
						'pool_name'          => $data['pool'] ?? 'N/A',
						'total_processes'    => $data['total processes'] ?? 'N/A',
						'active_processes'   => $data['active processes'] ?? 'N/A',
						'idle_processes'     => $data['idle processes'] ?? 'N/A',
						'listen_queue'       => $data['listen queue'] ?? 'N/A',
						'listen_queue_len'   => $data['listen queue len'] ?? 'N/A',
						'max_children'       => $data['max children reached'] ?? 'N/A',
					);
				}
			}
		}

		return null;
	}

	/**
	 * Get server information.
	 *
	 * @return array Server information.
	 */
	private static function get_server_info() {
		return array(
			'software'           => isset( $_SERVER['SERVER_SOFTWARE'] ) ? $_SERVER['SERVER_SOFTWARE'] : 'Unknown',
			'os'                 => PHP_OS,
			'hostname'           => gethostname(),
			'server_addr'        => isset( $_SERVER['SERVER_ADDR'] ) ? $_SERVER['SERVER_ADDR'] : 'Unknown',
			'document_root'      => isset( $_SERVER['DOCUMENT_ROOT'] ) ? $_SERVER['DOCUMENT_ROOT'] : 'Unknown',
			'cpu_count'          => self::get_cpu_count(),
			'memory_total'       => self::get_memory_total(),
			'memory_available'   => self::get_memory_available(),
			'load_average'       => self::get_load_average(),
		);
	}

	/**
	 * Get CPU core count.
	 *
	 * @return int|string CPU count or 'Unknown'.
	 */
	private static function get_cpu_count() {
		if ( function_exists( 'shell_exec' ) ) {
			// Linux
			$output = shell_exec( 'nproc 2>/dev/null' );
			if ( $output ) {
				return (int) trim( $output );
			}

			// macOS
			$output = shell_exec( 'sysctl -n hw.ncpu 2>/dev/null' );
			if ( $output ) {
				return (int) trim( $output );
			}
		}

		return 'Unknown';
	}

	/**
	 * Get total system memory in MB.
	 *
	 * @return string Memory in MB or 'Unknown'.
	 */
	private static function get_memory_total() {
		if ( function_exists( 'shell_exec' ) ) {
			// Linux
			$output = shell_exec( "free -m | grep Mem | awk '{print $2}'" );
			if ( $output ) {
				return trim( $output ) . ' MB';
			}

			// macOS
			$output = shell_exec( 'sysctl -n hw.memsize 2>/dev/null' );
			if ( $output ) {
				return round( (int) trim( $output ) / 1024 / 1024 ) . ' MB';
			}
		}

		return 'Unknown';
	}

	/**
	 * Get available system memory in MB.
	 *
	 * @return string Available memory or 'Unknown'.
	 */
	private static function get_memory_available() {
		if ( function_exists( 'shell_exec' ) ) {
			// Linux
			$output = shell_exec( "free -m | grep Mem | awk '{print $7}'" );
			if ( $output ) {
				return trim( $output ) . ' MB';
			}
		}

		return 'Unknown';
	}

	/**
	 * Get system load average.
	 *
	 * @return string Load average or 'Unknown'.
	 */
	private static function get_load_average() {
		if ( function_exists( 'sys_getloadavg' ) ) {
			$load = sys_getloadavg();
			return sprintf( '%.2f, %.2f, %.2f', $load[0], $load[1], $load[2] );
		}

		return 'Unknown';
	}

	/**
	 * Get WordPress information.
	 *
	 * @return array WordPress information.
	 */
	private static function get_wordpress_info() {
		global $wp_version;

		return array(
			'version'           => $wp_version,
			'multisite'         => is_multisite(),
			'site_url'          => get_site_url(),
			'home_url'          => get_home_url(),
			'debug_mode'        => defined( 'WP_DEBUG' ) && WP_DEBUG,
			'memory_limit'      => WP_MEMORY_LIMIT,
			'max_memory_limit'  => WP_MAX_MEMORY_LIMIT,
			'theme'             => wp_get_theme()->get( 'Name' ),
			'active_plugins'    => count( get_option( 'active_plugins', array() ) ),
		);
	}

	/**
	 * Get database information.
	 *
	 * @return array Database information.
	 */
	private static function get_database_info() {
		global $wpdb;

		$info = array(
			'extension'         => $wpdb->db_version(),
			'server'            => $wpdb->get_var( 'SELECT VERSION()' ),
			'client_version'    => $wpdb->db_version(),
			'database_name'     => DB_NAME,
			'database_host'     => DB_HOST,
			'database_charset'  => DB_CHARSET,
			'table_prefix'      => $wpdb->prefix,
		);

		// Get MySQL configuration
		$variables = array(
			'max_connections',
			'max_allowed_packet',
			'query_cache_size',
			'innodb_buffer_pool_size',
			'tmp_table_size',
			'max_heap_table_size',
		);

		foreach ( $variables as $var ) {
			$value = $wpdb->get_var( "SHOW VARIABLES LIKE '$var'" );
			if ( $value ) {
				$info[ $var ] = $wpdb->get_var( "SHOW VARIABLES LIKE '$var'", 1 );
			}
		}

		// Get current connections
		$info['current_connections'] = $wpdb->get_var( "SHOW STATUS LIKE 'Threads_connected'" )
			? $wpdb->get_var( "SHOW STATUS LIKE 'Threads_connected'", 1 )
			: 'Unknown';

		return $info;
	}

	/**
	 * Get performance-related information.
	 *
	 * @return array Performance information.
	 */
	private static function get_performance_info() {
		return array(
			'object_cache'      => wp_using_ext_object_cache() ? 'External' : 'Built-in',
			'curl_available'    => function_exists( 'curl_version' ),
			'curl_version'      => function_exists( 'curl_version' ) ? curl_version()['version'] : 'N/A',
			'allow_url_fopen'   => ini_get( 'allow_url_fopen' ) ? 'Yes' : 'No',
			'compression'       => extension_loaded( 'zlib' ) ? 'Available' : 'Not available',
			'https_support'     => is_ssl() ? 'Yes' : 'No',
		);
	}

	/**
	 * Format system info as HTML.
	 *
	 * @param array $info System information array.
	 * @return string HTML output.
	 */
	public static function format_as_html( $info ) {
		ob_start();
		?>
		<div class="maplepress-system-info">
			<?php foreach ( $info as $section => $data ) : ?>
				<div class="system-info-section">
					<h3 style="margin-top: 0; padding: 10px; background: #f0f0f1; border-left: 4px solid #2271b1;">
						<?php echo esc_html( ucwords( str_replace( '_', ' ', $section ) ) ); ?>
					</h3>
					<table class="widefat" style="margin-top: 0;">
						<tbody>
							<?php foreach ( $data as $key => $value ) : ?>
								<?php
								// Check if this is the opcache_status field (which contains a large array)
								$is_opcache_status = ( $key === 'opcache_status' && is_array( $value ) );
								$field_id = 'maplepress-field-' . sanitize_title( $section . '-' . $key );
								?>
								<tr>
									<td style="width: 250px; font-weight: bold; vertical-align: top;">
										<?php echo esc_html( ucwords( str_replace( '_', ' ', $key ) ) ); ?>
										<?php if ( $is_opcache_status ) : ?>
											<br>
											<button type="button"
													class="button button-secondary button-small maplepress-toggle-field"
													data-target="<?php echo esc_attr( $field_id ); ?>"
													style="margin-top: 5px;">
												<span class="dashicons dashicons-visibility" style="vertical-align: middle; font-size: 14px;"></span>
												<span class="toggle-text">Show</span>
											</button>
										<?php endif; ?>
									</td>
									<td>
										<?php if ( $is_opcache_status ) : ?>
											<div id="<?php echo esc_attr( $field_id ); ?>" style="display: none;">
												<pre><?php echo esc_html( print_r( $value, true ) ); ?></pre>
											</div>
											<span class="opcache-hidden-notice" style="color: #666; font-style: italic;">
												Click "Show" to view opcache details
											</span>
										<?php elseif ( is_array( $value ) ) : ?>
											<pre><?php echo esc_html( print_r( $value, true ) ); ?></pre>
										<?php elseif ( is_bool( $value ) ) : ?>
											<?php echo $value ? '<span style="color: green;">✓ Yes</span>' : '<span style="color: red;">✗ No</span>'; ?>
										<?php else : ?>
											<?php echo esc_html( $value ); ?>
										<?php endif; ?>
									</td>
								</tr>
							<?php endforeach; ?>
						</tbody>
					</table>
				</div>
			<?php endforeach; ?>
		</div>

		<style>
		.maplepress-system-info .system-info-section {
			margin-bottom: 30px;
		}
		.maplepress-system-info pre {
			margin: 0;
			padding: 10px;
			background: #f9f9f9;
			border-left: 3px solid #ccc;
			overflow-x: auto;
		}
		</style>

		<script>
		jQuery(document).ready(function($) {
			// Toggle field visibility for opcache_status
			$('.maplepress-toggle-field').on('click', function() {
				var button = $(this);
				var targetId = button.data('target');
				var content = $('#' + targetId);
				var notice = button.closest('tr').find('.opcache-hidden-notice');
				var icon = button.find('.dashicons');
				var text = button.find('.toggle-text');

				if (content.is(':visible')) {
					content.slideUp(300);
					notice.show();
					icon.removeClass('dashicons-hidden').addClass('dashicons-visibility');
					text.text('Show');
				} else {
					content.slideDown(300);
					notice.hide();
					icon.removeClass('dashicons-visibility').addClass('dashicons-hidden');
					text.text('Hide');
				}
			});
		});
		</script>
		<?php
		return ob_get_clean();
	}
}
