<?php
if ( ! class_exists( 'NISHIKI_PRO_MULTIPLE_SEARCH' ) ) {
	/**
	 * Create Code.
	 */
	class NISHIKI_PRO_MULTIPLE_SEARCH extends NISHIKI_PRO_MULTIPLE_SEARCH_UTILITY {

		/**
		 * Constructor.
		 */
		public function __construct() {
			// フォーム追加
			add_action( 'admin_init', array( $this, 'register_form' ), 20 );

			// クエリー追加
			add_filter( 'query_vars', array( $this, 'add_query_vars_filter' ), 20 );

			// 検索結果フィルター
			add_action( 'pre_get_posts', array( $this, 'search_filter' ), 20 );

		}

		/**
		 * フォーム追加
		 */
		public function register_form() {
			$page_name = $this->plugin_name;

			$taxonomies = $this->get_taxonomies( 'objects' );

			register_setting(
				$page_name,
				$page_name,
				array( $this, 'sanitize' )
			);

			add_settings_section(
				$page_name,
				'',
				array( $this, 'general_cb' ),
				$page_name
			);

			foreach ( $taxonomies as $taxonomy ) {
				//$taxonomy_labels = get_taxonomy_labels( get_taxonomy( $taxonomy ) );
				//$taxonomy_name   = $taxonomy_labels->singular_name;
				$taxonomy_name   = $taxonomy->name;
				$taxonomy_label   = $taxonomy->label;
				
				if( $taxonomy->show_in_rest ){
					add_settings_field(
						'taxonomy_' . $taxonomy_name,
						$taxonomy_label . '(' . $taxonomy_name . ')',
						array( $this, 'multiple_search_cb' ),
						$page_name,
						$page_name,
						array(
							'title'       => $taxonomy_name,
							'label'       => 'multiple_search',
							'page_name'   => $page_name,
							'description' => '',
							'taxonomy'    => $taxonomy_name,
						)
					);
				}
			}

			add_settings_field(
				'multiple_search_display_count',
				__( '項目の隣に投稿数を表示する', 'nishiki_pro' ),
				array( $this, 'multiple_search_checkbox_cb' ),
				$page_name,
				$page_name,
				array(
					'title'       => '表示しない',
					'label'       => 'multiple_search_display_count',
					'page_name'   => $page_name,
					'description' => '',
				)
			);

			add_settings_field(
				'multiple_search_result',
				__( '検索結果ページに絞り込み検索を表示する', 'nishiki_pro' ),
				array( $this, 'multiple_search_checkbox_cb' ),
				$page_name,
				$page_name,
				array(
					'title'       => '表示する',
					'label'       => 'multiple_search_result',
					'page_name'   => $page_name,
					'description' => '',
				)
			);

			add_settings_field(
				'multiple_search_overlay',
				__( '検索ボタンを押した時に絞り込み検索を表示する', 'nishiki_pro' ),
				array( $this, 'multiple_search_checkbox_cb' ),
				$page_name,
				$page_name,
				array(
					'title'       => '表示する',
					'label'       => 'multiple_search_overlay',
					'page_name'   => $page_name,
					'description' => '',
				)
			);

			add_settings_field(
				'replace_filter_search_block_id',
				__( '「絞り込み検索」ブロックで作ったフォームを表示する', 'nishiki_pro' ),
				array( $this, 'multiple_search_text_cb' ),
				$page_name,
				$page_name,
				array(
					'title'       => '差し替え用 ID',
					'label'       => 'replace_filter_search_block_id',
					'page_name'   => $page_name,
					'description' => 'ここに ID を入力すると「検索結果ページのフォーム」「検索ボタンを押した時に表示するフォーム」を「絞り込み検索」ブロックで作成したフォームに差し替えます。',
				)
			);
		}

		/**
		 * フォームの出力（全ページ）
		 */
		public function general_cb() {
			$nonce = wp_create_nonce( $this->plugin_name );
			echo '<input type="hidden" name="' . esc_attr( $this->plugin_name ) . '" value="' . esc_attr( $nonce ) . '" />';
		}

		/**
		 * 入力値のサニタイズ
		 *
		 * @param array $input 入力値
		 * @return $new_input
		 */
		public function sanitize( $input ) {
			$new_input = array();

			$taxonomies = $this->get_taxonomies( 'objects' );

			foreach ( $taxonomies as $taxonomy ) {
				$taxonomy_name   = $taxonomy->name;

				if( $taxonomy->show_in_rest ){
					$new_input[ $taxonomy_name ]['display'] = ! empty( $input[ $taxonomy_name ]['display'] ) ? absint( $input[ $taxonomy_name ]['display'] ) : '';
					$new_input[ $taxonomy_name ]['label']   = ! empty( $input[ $taxonomy_name ]['label'] ) ? sanitize_text_field( $input[ $taxonomy_name ]['label'] ) : '';
					$new_input[ $taxonomy_name ]['formInputType']   = ! empty( $input[ $taxonomy_name ]['formInputType'] ) ? sanitize_text_field( $input[ $taxonomy_name ]['formInputType'] ) : '';
	
					if( ! empty( $input[ $taxonomy_name ]['terms'] ) && is_array( $input[ $taxonomy_name ]['terms'] ) ){
						$new_input[ $taxonomy_name ]['terms']   = array_map( 'absint', $input[ $taxonomy_name ]['terms'] );
					}
				}
			}

			if ( $input['multiple_search_result'] ) {
				$new_input['multiple_search_result'] = $input['multiple_search_result'];
			}

			if ( $input['multiple_search_overlay'] ) {
				$new_input['multiple_search_overlay'] = $input['multiple_search_overlay'];
			}

			if ( $input['multiple_search_display_count'] ) {
				$new_input['multiple_search_display_count'] = $input['multiple_search_display_count'];
			}

			if ( $input['replace_filter_search_block_id'] ) {
				$new_input['replace_filter_search_block_id'] = sanitize_text_field ( $input['replace_filter_search_block_id'] );
			}

			return $new_input;
		}

		/**
		 * クエリー追加
		 *
		 * @param array $vars 配列
		 * @return $vars
		 */
		public function add_query_vars_filter( $vars ) {
			$taxonomies = $this->get_taxonomies( 'objects' );

			// フォームのタイプ
			$form_input_types = array(
				'checkbox',
				'radio',
				'select',
			);

			foreach ( $taxonomies as $taxonomy ) {
				if( $taxonomy->show_in_rest ){
					foreach( $form_input_types as $form_input_type ){
						$vars[] = $form_input_type . '_' . $taxonomy->name;
					}
				}
			}
			
			foreach ( $taxonomies as $taxonomy ) {
				$vars[] = $taxonomy->name;
			}

			$vars[] = 'term_id';
			$vars[] = 'relation';

			return $vars;
		}

		/**
		 * 検索結果フィルター
		 *
		 * @param [type] $query クエリー
		 * @return void
		 */
		public function search_filter( $query ) {
			if ( ! is_admin() && $query->is_main_query() ) {
				if ( $query->is_search ) {

					$taxonomies = $this->get_taxonomies( 'objects' );

					$form_input_types = [ 'checkbox', 'radio', 'select' ];

					foreach ( $taxonomies as $taxonomy ) {
						if( $taxonomy->show_in_rest ){
							foreach( $form_input_types as $form_input_type ){
								$name = $form_input_type . '_' . $taxonomy->name;
								if( ! empty( $query->query[ $name ] ) ){
									if( is_array( $query->query[ $name ] ) ){
										foreach( $query->query[ $name ] as $term_id ){
											$tax_query[] = $this->create_tax_query( $term_id, $taxonomy->name );
										}
									} else {
										$tax_query[] = $this->create_tax_query( $query->query[ $name ], $taxonomy->name );
									}
								}
							}
						}
					}

					// relation
					if( get_query_var( 'relation' ) ){
						$tax_query['relation'] = get_query_var( 'relation' );
					} else {
						$tax_query['relation'] = '';
					}

					if( ! empty( $tax_query ) ){
						$query->set( 'tax_query', $tax_query );
					}

					// キーワード or 検索
					if( $tax_query['relation'] === 'or' ){
						add_filter( 'posts_search', [ __CLASS__, 'keyword_posts_search' ], 10, 2 );
						add_filter( 'posts_orderby', [ __CLASS__, 'keyword_search_oderby' ], 10, 2 );
					}
				}
			}
		}

		static public function keyword_posts_search( $search, $query ){
			global $wpdb;
    
			// 検索キーワードを取得
//			$search_terms = explode( ' ', $query->get( 's' ) );
			$search_terms = preg_split( '/[\s　]+/u', $query->get( 's' ), -1, PREG_SPLIT_NO_EMPTY );

			if ( count( $search_terms ) > 1 ) {
				$search_query = [];

				foreach ( $search_terms as $term ) {
					$search_query[] = $wpdb->prepare( "( $wpdb->posts.post_title LIKE %s OR $wpdb->posts.post_content LIKE %s )", '%' . $wpdb->esc_like( $term ) . '%', '%' . $wpdb->esc_like( $term ) . '%' );
				}

				// OR検索用のカスタムSQLを作成
				$search = ' AND (' . implode( ' OR ', $search_query ) . ') ';
			}

			return $search;
		}

		static public function keyword_search_oderby( $orderby, $query ) {
			if ( $query->is_search() ) {
				global $wpdb;
				$search_terms = preg_split( '/[\s　]+/u', $query->get( 's' ), -1, PREG_SPLIT_NO_EMPTY );
		
				// 検索スコアを加味した ORDER BY を適用
				$score_parts = [];
				foreach ( $search_terms as $term ) {
					$escaped_term = '%' . $wpdb->esc_like( $term ) . '%';
					$score_parts[] = $wpdb->prepare( "WHEN $wpdb->posts.post_title LIKE %s THEN 3", $escaped_term );
					$score_parts[] = $wpdb->prepare( "WHEN $wpdb->posts.post_content LIKE %s THEN 1", $escaped_term );
				}
		
				if ( ! empty( $score_parts ) ) {
					$orderby = "(CASE " . implode( ' ', $score_parts ) . " ELSE 0 END) DESC, $wpdb->posts.post_date DESC";
				}
			}
		
			return $orderby;
		}

		/**
		 * tax_query追加
		 */
		public function create_tax_query( $term_id, $taxonomy ){

			$data = [
				'taxonomy' => $taxonomy,
				'field' => 'term_id',
				'terms' => $term_id,
				'operator' => 'IN',
			];

			return $data;
		}


	}
}

$output = new NISHIKI_PRO_MULTIPLE_SEARCH();
