<?php /** @noinspection PhpMissingParamTypeInspection */

/** @noinspection PhpComposerExtensionStubsInspection */

namespace WPDRMS\ASP\Hooks\Ajax;

use WPDRMS\ASP\Misc\PluginLicense;
use WPDRMS\ASP\Query\SearchQuery;
use WPDRMS\ASP\Statistics\StatisticsService;
use WPDRMS\ASP\Utils\Ajax;
use WPDRMS\ASP\Utils\Search as SearchUtils;

if ( !defined('ABSPATH') ) {
	die('-1');
}

class Search extends AbstractAjax {

	/**
	 * Oversees and handles the search request
	 *
	 * @param bool $dont_group
	 * @return array|mixed|void
	 */
	public function handle( $dont_group = false ) {

		$s = $_POST['aspp']; // phpcs:ignore

		if ( is_array($_POST['options']) ) { // phpcs:ignore
			$options = $_POST['options']; // phpcs:ignore
		} else {
			parse_str($_POST['options'], $options); // phpcs:ignore
		}

		$id       = (int) $_POST['asid']; // phpcs:ignore
		$instance = wd_asp()->instances->get($id);
		$sd       = &$instance['data'];

		// Hooking point for custom output & early exit
		$custom_output = apply_filters(
			'asp/ajax/search/custom_output',
			'',
			$id, $s, $options, $_POST['asp_call_num'] ?? 0, $_POST['autop'] ?? '' // phpcs:ignore
		);
		if ( !empty($custom_output) ) {
			Ajax::prepareHeaders('application/json');
			echo $custom_output; // phpcs:ignore
			die();
		}

		// If previewed, we need the details
		if ( isset($_POST['asp_preview_options']) && ( current_user_can('activate_plugins') || ASP_DEMO ) ) {
			require_once ASP_PATH . 'backend' . DIRECTORY_SEPARATOR . 'settings' . DIRECTORY_SEPARATOR . 'types.inc.php';
			parse_str( $_POST['asp_preview_options'], $preview_options ); // phpcs:ignore
			$_POST['asp_preview_options'] = wpdreams_parse_params($preview_options); // phpcs:ignore
			$_POST['asp_preview_options'] = wd_asp()->instances->decode_params($_POST['asp_preview_options']); // phpcs:ignore
			$sd                           = $_POST['asp_preview_options']; // phpcs:ignore
		}

		$asp_query = new SearchQuery(
			array(
				's'            => $s,
				'_id'          => $id,
				'_ajax_search' => true,
				'_call_num'    => $_POST['asp_call_num'] ?? 0, // phpcs:ignore
			),
			$id,
			$options
		);
		$results   = $asp_query->posts;

		if ( count($results) > 0 ) {
			$results = apply_filters('asp_only_non_keyword_results', $results, $id, $s, $asp_query->getArgs());
		} elseif ( $sd['result_suggestions'] ) {
				$results = $asp_query->resultsSuggestions( $sd['keywordsuggestions'] );
		} elseif ( $sd['keywordsuggestions'] ) {
			$results = $asp_query->kwSuggestions();
		}

		if (
			count($results) <= 0 &&
			$sd['keywordsuggestions'] &&
			( !isset($_GET['asp_call_num']) || $_GET['asp_call_num'] < 2 )
		) {
			$results = $asp_query->resultsSuggestions();
		} elseif ( count($results) > 0 ) {
			$results = apply_filters('asp_only_non_keyword_results', $results, $id, $s, $asp_query->getArgs());
		}

		$results = apply_filters('asp_ajax_results', $results, $id, $s, $sd);

		do_action('asp_after_search', $s, $results, $id);

		$html_results = SearchUtils::generateHTMLResults($results, $sd, $id, $s);

		// Override from hooks
		if ( isset($_POST['asp_get_as_array']) ) {
			return $results;
		}

		$html_results = apply_filters('asp_before_ajax_output', $html_results, $id, $results, $asp_query->getArgs());

		// Check if the script is cached from an older version and return the legacy output
		$version = isset($_POST['version']) ? sanitize_text_field(wp_unslash($_POST['version'])) : '4.27.2';

		$lang = $asp_query->args->_wpml_lang !== '' ? $asp_query->args->_wpml_lang :
			( $asp_query->args->_polylang_lang !== '' ? $asp_query->args->_polylang_lang : '' );

		$response = array(
			'html'               => $html_results,
			'results_count'      => isset($results['keywords']) ? 0 : $asp_query->returned_posts,
			'full_results_count' => $asp_query->found_posts,
			'lang'               => $lang,
			'results'            => $results,
			'statistics_id'      => StatisticsService::$last_search_id,
		);

		$response = apply_filters('asp/ajax/search/response', $response, $id, $s, $options, $_POST['asp_call_num'] ?? 0, $_POST['autop'] ?? ''); // phpcs:ignore

		if ( version_compare($version, '4.28', '>=') ) {
			if ( defined('JSON_INVALID_UTF8_IGNORE') ) {
				$final_output = wp_json_encode(
					$response,
					JSON_INVALID_UTF8_IGNORE
				);
			} else {
				$final_output = wp_json_encode(
					$response
				);
			}
		} else {
			$final_output = $this->getLegacyResponse($response);
		}

		$final_output = apply_filters('asp/ajax/search/output', $final_output, $id, $s, $options, $_POST['asp_call_num'] ?? 0, $_POST['autop'] ?? ''); // phpcs:ignore
		Ajax::prepareHeaders('application/json');
		echo $final_output; // phpcs:ignore
		die();
	}

	/**
	 * @depecated 4.29+
	 * @param array $response
	 * @return string
	 */
	private function getLegacyResponse( array $response ): string {
		$final_output = '';
		/* Clear output buffer, possible warnings */
		$final_output .= '___ASPSTART_HTML___' . $response['html'] . '___ASPEND_HTML___';
		unset($response['html']);
		$final_output .= '___ASPSTART_DATA___';
		if ( defined('JSON_INVALID_UTF8_IGNORE') ) {
			$final_output .= wp_json_encode(
				$response,
				JSON_INVALID_UTF8_IGNORE
			);
		} else {
			$final_output .= wp_json_encode(
				$response
			);
		}
		$final_output .= '___ASPEND_DATA___';

		return $final_output;
	}
}
