<?php
/**
 * Simple Speed Test Class
 *
 * Just runs queries and times them. No complexity.
 *
 * @package MaplePress_SearchSpeedTest
 */

class MPSS_SpeedTest_Simple {

	/**
	 * Run speed test with specified number of queries.
	 *
	 * @param int    $query_count    Number of queries to run.
	 * @param string $execution_mode Execution mode: 'serial' or 'parallel'.
	 * @return array Results with timing data.
	 */
	public function run( $query_count = 10, $execution_mode = 'serial' ) {
		$start_time = microtime( true );

		// Debug logging
		error_log( 'MPSS_SpeedTest_Simple::run() called with mode: ' . $execution_mode );

		// Generate search queries
		$queries = $this->generate_queries( $query_count );

		// Execute based on mode
		if ( $execution_mode === 'parallel' ) {
			error_log( 'MPSS: Executing in PARALLEL mode' );
			$results = $this->run_parallel( $queries );
		} else {
			error_log( 'MPSS: Executing in SERIAL mode' );
			$results = $this->run_serial( $queries );
		}

		$end_time   = microtime( true );
		$total_time = $end_time - $start_time;

		// Calculate statistics
		$times  = array_column( $results, 'duration_ms' );
		$avg_ms = array_sum( $times ) / count( $times );
		$min_ms = min( $times );
		$max_ms = max( $times );

		return array(
			'results'       => $results,
			'total_time'    => round( $total_time, 2 ),
			'total_queries' => count( $results ),
			'avg_ms'        => round( $avg_ms, 2 ),
			'min_ms'        => round( $min_ms, 2 ),
			'max_ms'        => round( $max_ms, 2 ),
			'mode'          => $execution_mode,
		);
	}

	/**
	 * Run queries in serial mode (one at a time).
	 *
	 * @param array $queries Array of search query strings.
	 * @return array Results array.
	 */
	private function run_serial( $queries ) {
		$results = array();

		foreach ( $queries as $query ) {
			$query_start = microtime( true );

			// Make HTTP request to search URL to properly trigger MaplePress hooks
			$search_url = home_url( '/?s=' . urlencode( $query ) );
			$response = wp_remote_get(
				$search_url,
				array(
					'timeout' => 30,
					'headers' => array(
						'X-MaplePress-Test' => '1',
					),
				)
			);

			$query_end = microtime( true );
			$duration_ms = ( $query_end - $query_start ) * 1000;

			// Extract result count from response - try multiple patterns
			$result_count = 0;
			if ( ! is_wp_error( $response ) && wp_remote_retrieve_response_code( $response ) === 200 ) {
				$body = wp_remote_retrieve_body( $response );

				// Try various patterns to find result count
				$patterns = array(
					'/(\d+)\s+results?/i',                    // "5 results" or "1 result"
					'/found\s+(\d+)/i',                       // "Found 5"
					'/showing\s+(\d+)/i',                     // "Showing 5"
					'/<article/i',                            // Count article tags
					'/<div[^>]*class="[^"]*post[^"]*"/i',    // Count post divs
				);

				foreach ( $patterns as $pattern ) {
					if ( $pattern === '/<article/i' || strpos( $pattern, '<div' ) === 0 ) {
						// Count HTML elements
						$count = preg_match_all( $pattern, $body );
						if ( $count > 0 ) {
							$result_count = $count;
							break;
						}
					} else {
						// Extract number from text
						if ( preg_match( $pattern, $body, $matches ) ) {
							$result_count = intval( $matches[1] );
							break;
						}
					}
				}
			}

			$results[] = array(
				'query'        => $query,
				'duration_ms'  => round( $duration_ms, 2 ),
				'result_count' => $result_count,
			);
		}

		return $results;
	}

	/**
	 * Run queries in parallel mode (multiple concurrent requests).
	 *
	 * @param array $queries Array of search query strings.
	 * @return array Results array.
	 */
	private function run_parallel( $queries ) {
		error_log( 'MPSS: run_parallel called with ' . count( $queries ) . ' queries' );

		$results = array();

		// Build search URLs
		$search_urls = array();
		foreach ( $queries as $query ) {
			$search_urls[] = array(
				'url'   => home_url( '/?s=' . urlencode( $query ) ),
				'query' => $query,
			);
		}

		error_log( 'MPSS: Built ' . count( $search_urls ) . ' search URLs' );

		// Initialize cURL multi handle
		$mh = curl_multi_init();
		$curl_handles = array();
		$request_info = array();

		// Add all requests to multi handle
		foreach ( $search_urls as $index => $search_data ) {
			$ch = curl_init();
			curl_setopt( $ch, CURLOPT_URL, $search_data['url'] );
			curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
			curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
			curl_setopt( $ch, CURLOPT_TIMEOUT, 30 );
			curl_setopt( $ch, CURLOPT_HTTPHEADER, array(
				'X-MaplePress-Test: 1',
			) );

			curl_multi_add_handle( $mh, $ch );
			$ch_id = (int) $ch;
			$curl_handles[ $ch_id ] = $ch;
			$request_info[ $ch_id ] = array(
				'query' => $search_data['query'],
				'index' => $index,
				'start_time' => null,
				'end_time' => null,
			);
		}

		error_log( 'MPSS: Added ' . count( $curl_handles ) . ' handles, request_info has ' . count( $request_info ) . ' entries' );

		// Execute all queries simultaneously and track start/end times
		$running = null;

		// Record start time for ALL requests (they all start together)
		$batch_start = microtime( true );
		foreach ( $request_info as $ch_id => $info ) {
			$request_info[ $ch_id ]['start_time'] = $batch_start;
		}

		// Start executing - all requests run concurrently
		do {
			curl_multi_exec( $mh, $running );

			// Check for completed requests and record their end time
			while ( $done = curl_multi_info_read( $mh ) ) {
				if ( $done['msg'] == CURLMSG_DONE ) {
					$ch_id = (int) $done['handle'];
					// Record when THIS specific request finished
					if ( ! isset( $request_info[ $ch_id ]['end_time'] ) ) {
						$request_info[ $ch_id ]['end_time'] = microtime( true );
					}
				}
			}

			if ( $running > 0 ) {
				curl_multi_select( $mh );
			}
		} while ( $running > 0 );

		$batch_end = microtime( true );
		$batch_duration_ms = ( $batch_end - $batch_start ) * 1000;

		error_log( 'MPSS: Batch completed in ' . round( $batch_duration_ms, 2 ) . 'ms, processing ' . count( $request_info ) . ' results' );

		// Collect results - calculate duration from start/end times
		foreach ( $request_info as $ch_id => $info ) {
			$ch = $curl_handles[ $ch_id ];

			// Calculate duration from start to end time
			if ( isset( $info['start_time'] ) && isset( $info['end_time'] ) ) {
				$duration_seconds = $info['end_time'] - $info['start_time'];
				$duration_ms = $duration_seconds * 1000;

				// Debug: log a few samples
				static $debug_count = 0;
				if ( $debug_count < 3 ) {
					error_log( sprintf(
						'MPSS: Sample #%d - start=%.6f, end=%.6f, duration_sec=%.6f, duration_ms=%.2f',
						$debug_count,
						$info['start_time'],
						$info['end_time'],
						$duration_seconds,
						$duration_ms
					) );
					$debug_count++;
				}
			} else {
				// Fallback - shouldn't happen
				$duration_ms = 0;
			}

			$curl_info = curl_getinfo( $ch );
			$response = curl_multi_getcontent( $ch );
			$http_code = $curl_info['http_code'];

			// Extract result count using multiple patterns
			$result_count = 0;
			if ( $http_code === 200 && ! empty( $response ) ) {
				$patterns = array(
					'/(\d+)\s+results?/i',
					'/found\s+(\d+)/i',
					'/showing\s+(\d+)/i',
					'/<article/i',
					'/<div[^>]*class="[^"]*post[^"]*"/i',
				);

				foreach ( $patterns as $pattern ) {
					if ( $pattern === '/<article/i' || strpos( $pattern, '<div' ) === 0 ) {
						$count = preg_match_all( $pattern, $response );
						if ( $count > 0 ) {
							$result_count = $count;
							break;
						}
					} else {
						if ( preg_match( $pattern, $response, $matches ) ) {
							$result_count = intval( $matches[1] );
							break;
						}
					}
				}
			}

			$results[ $info['index'] ] = array(
				'query'        => $info['query'],
				'duration_ms'  => round( $duration_ms, 2 ),
				'result_count' => $result_count,
			);

			curl_multi_remove_handle( $mh, $ch );
			curl_close( $ch );
		}

		curl_multi_close( $mh );

		// Sort results by original index to maintain query order
		ksort( $results );

		return array_values( $results );
	}

	/**
	 * Generate random search queries from existing content.
	 *
	 * @param int $count Number of queries to generate.
	 * @return array Array of search query strings.
	 */
	private function generate_queries( $count ) {
		error_log( 'MPSS: generate_queries called with count=' . $count );

		$posts = get_posts(
			array(
				'post_type'      => array( 'post', 'page' ),
				'post_status'    => 'publish',
				'posts_per_page' => $count * 3,
				'orderby'        => 'rand',
			)
		);

		error_log( 'MPSS: get_posts returned ' . count( $posts ) . ' posts' );

		$queries = array();

		foreach ( $posts as $post ) {
			if ( count( $queries ) >= $count ) {
				break;
			}

			// Get words from title
			$words = array_filter( explode( ' ', $post->post_title ) );

			if ( empty( $words ) ) {
				continue;
			}

			// 50% single word, 50% two words
			if ( mt_rand( 1, 2 ) === 1 || count( $words ) === 1 ) {
				$queries[] = $words[ array_rand( $words ) ];
			} else {
				$start     = mt_rand( 0, count( $words ) - 2 );
				$queries[] = $words[ $start ] . ' ' . $words[ $start + 1 ];
			}
		}

		// If we don't have enough, pad with generic searches
		while ( count( $queries ) < $count ) {
			$queries[] = 'test';
		}

		$final_queries = array_slice( $queries, 0, $count );
		error_log( 'MPSS: generate_queries returning ' . count( $final_queries ) . ' queries' );

		return $final_queries;
	}
}
