<?php
/**
 * Parallel Executor Class
 *
 * Executes search queries in parallel (concurrent requests) to simulate
 * multiple simultaneous users searching the site.
 *
 * @package MaplePress_SearchSpeedTest
 */

class MPSS_Parallel_Executor {

	/**
	 * Execute queries in parallel batches.
	 *
	 * @param array $queries     Array of search query strings.
	 * @param int   $concurrency Number of concurrent requests per batch.
	 * @return array Results array with timing and metadata.
	 */
	public function execute( $queries, $concurrency = 5 ) {
		$results = array();

		// Split queries into batches based on concurrency
		$batches = array_chunk( $queries, $concurrency );

		foreach ( $batches as $batch ) {
			$batch_results = $this->execute_batch( $batch );
			$results       = array_merge( $results, $batch_results );

			// Small delay between batches to prevent server overload
			usleep( 50000 ); // 50ms
		}

		return $results;
	}

	/**
	 * Execute a batch of queries concurrently using cURL multi-handle.
	 *
	 * @param array $queries Array of query strings for this batch.
	 * @return array Results for this batch.
	 */
	private function execute_batch( $queries ) {
		$results = array();

		// Prepare requests
		$requests = array();
		foreach ( $queries as $query ) {
			$search_url = add_query_arg( 's', urlencode( $query ), home_url( '/' ) );

			$requests[] = array(
				'url'   => $search_url,
				'query' => $query,
			);
		}

		// Execute in parallel
		$parallel_results = $this->execute_parallel_requests( $requests );

		return $parallel_results;
	}

	/**
	 * Execute multiple HTTP requests in parallel using cURL multi-handle.
	 *
	 * @param array $requests Array of request data (url, query).
	 * @return array Results array.
	 */
	private function execute_parallel_requests( $requests ) {
		$results      = array();
		$mh           = curl_multi_init();
		$curl_handles = array();

		// Add all requests to multi-handle
		foreach ( $requests as $index => $request ) {
			$ch = curl_init();
			curl_setopt( $ch, CURLOPT_URL, $request['url'] );
			curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
			curl_setopt( $ch, CURLOPT_FOLLOWLOCATION, true );
			curl_setopt( $ch, CURLOPT_TIMEOUT, 30 );
			curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false ); // For local testing
			curl_setopt( $ch, CURLOPT_SSL_VERIFYHOST, false ); // For local testing

			// Add custom headers to identify test traffic (optional)
			curl_setopt(
				$ch,
				CURLOPT_HTTPHEADER,
				array(
					'X-Speed-Test: MaplePress',
				)
			);

			curl_multi_add_handle( $mh, $ch );

			$curl_handles[ (int) $ch ] = array(
				'handle' => $ch,
				'query'  => $request['query'],
				'start'  => microtime( true ),
			);
		}

		// Execute all requests
		$running = null;
		do {
			curl_multi_exec( $mh, $running );
			curl_multi_select( $mh );
		} while ( $running > 0 );

		// Collect results
		foreach ( $curl_handles as $data ) {
			$info = curl_getinfo( $data['handle'] );

			// Use cURL's total_time which accurately measures the individual request time
			// NOT the time from batch start to collection (which would be incorrect)
			$duration_ms = round( $info['total_time'] * 1000, 2 );

			$results[] = array(
				'query'       => $data['query'],
				'duration_ms' => $duration_ms,
				'http_code'   => $info['http_code'],
				'timestamp'   => $data['start'],
				'success'     => $info['http_code'] === 200,
			);

			curl_multi_remove_handle( $mh, $data['handle'] );
			curl_close( $data['handle'] );
		}

		curl_multi_close( $mh );

		return $results;
	}
}
