<?php
class BeRocket_aapf_custom_search_filters {
    const SEARCH_MIN_LENGTH = 2;
    const SEARCH_MAX_LENGTH = 64;
    const SEARCH_CACHE_TTL = 300;

    function __construct() {
        add_filter('brfr_data_ajax_filters', array($this, 'settings_page'), 1200);
        add_filter('BeRocket_AAPF_search_field_s_apply', array($this, 's_apply'), 1000, 3);
        add_filter('bapf_custom_search_addon_data', array($this, 'addon_data'));
        add_filter('brfr_get_option_ajax_filters', array($this, 'defaults_value'));
    }
    public function settings_page($data) {
        $data['Advanced'] = berocket_insert_to_array(
            $data['Advanced'],
            'header_part_fixes',
            array(
                'header_part_custom_search' => array(
                    'section' => 'header_part',
                    "value"   => __('Custom Search Add-on', 'BeRocket_AJAX_domain'),
                    "extra"   => "id='custom_search_by'",
                ),
                'custom_search_by' => array(
                    "label"     => __( 'Search By', "BeRocket_AJAX_domain" ),
                    "tr_class"  => "berocket_custom_search_by",
                    "items" => array(
                        "custom_search_by_title" => array(
                            "type"      => "checkbox",
                            "name"      => 'custom_search_by_title',
                            "value"     => '1',
                            'label_for' => __('Title', 'BeRocket_AJAX_domain'),
                        ),
                        'custom_search_by_description' => array(
                            "type"      => "checkbox",
                            "name"      => "custom_search_by_description",
                            "value"     => '1',
                            'label_for' => __('Description', 'BeRocket_AJAX_domain'),
                        ),
                        'custom_search_by_excerpt' => array(
                            "type"      => "checkbox",
                            "name"      => "custom_search_by_excerpt",
                            "value"     => '1',
                            'label_for' => __('Excerpt', 'BeRocket_AJAX_domain'),
                        ),
                        'custom_search_by_sku' => array(
                            "type"      => "checkbox",
                            "name"      => "custom_search_by_sku",
                            "value"     => '1',
                            'label_for' => __('SKU', 'BeRocket_AJAX_domain'),
                        ),
                    ),
                ),
            ),
            true
        );
        $search_types = array('berocket' => array('value' => '', 'text' => 'BeRocket'));
        if( function_exists('relevanssi_do_query') ) {
            $search_types['relevanssi'] = array('value' => 'relevanssi', 'text' => 'Relevanssi');
        }
        if( count($search_types) > 1 ) {
            $data['Advanced'] = berocket_insert_to_array(
                $data['Advanced'],
                'header_part_custom_search',
                array(
                    'custom_search_type' => array(
                        "label"    => __( 'Search Type', "BeRocket_AJAX_domain" ),
                        "name"     => "custom_search_type",
                        "class"    => "berocket_custom_search_by_type",
                        "type"     => "selectbox",
                        "options"  => $search_types,
                        "value"    => '',
                    ),
                )
            );
        }
        add_action('admin_footer', array($this, 'admin_script'));
        return $data;
    }
    function admin_script() {
        ?>
        <script>
        if( jQuery('.berocket_custom_search_by_type').length ) {
            function berocket_custom_search_by() {
                if( ! jQuery('.berocket_custom_search_by_type').val() ) {
                    jQuery('.berocket_custom_search_by').show();
                } else {
                    jQuery('.berocket_custom_search_by').hide();
                }
            }
            berocket_custom_search_by();
            jQuery(document).on('change', '.berocket_custom_search_by_type', berocket_custom_search_by);
        }
        </script>
        <?php
    }
    function s_apply($result, $args, $search) {
        $search = $this->normalize_search_term( $search );
        if ( false === $search ) {
            $args['post__in'] = array( 0 );
            return $args;
        }
        $BeRocket_AAPF = BeRocket_AAPF::getInstance();
        $options = $BeRocket_AAPF->get_option();
        if( ! function_exists('relevanssi_do_query') || empty($options['custom_search_type']) ) {
            $result = $this->berocket_search($args, $search);
        } elseif( $options['custom_search_type'] == 'relevanssi') {
            $result = $this->relevanssi_search($args, $search);
        }
        return $result;
    }

    private function normalize_search_term( $search ) {
        if ( ! is_scalar( $search ) ) {
            return false;
        }

        $search = trim( wp_strip_all_tags( (string) $search ) );
        $length = function_exists( 'mb_strlen' ) ? mb_strlen( $search ) : strlen( $search );
        if ( $length < self::SEARCH_MIN_LENGTH || $length > self::SEARCH_MAX_LENGTH ) {
            return false;
        }

        return $search;
    }

    function berocket_search($args, $search) {
        global $wpdb;
        $BeRocket_AAPF = BeRocket_AAPF::getInstance();
        $options = $BeRocket_AAPF->get_option();
        $cache_key = 'bapf_custom_search_' . md5( wp_json_encode( array(
            $search,
            ! empty( $options['custom_search_by_title'] ),
            ! empty( $options['custom_search_by_description'] ),
            ! empty( $options['custom_search_by_excerpt'] ),
            ! empty( $options['custom_search_by_sku'] ),
        ) ) );
        $posts = get_transient( $cache_key );
        if ( false !== $posts && is_array( $posts ) ) {
            return $this->set_search_posts( $args, $posts );
        }

        $query = array(
            'select' => "SELECT DISTINCT {$wpdb->posts}.ID FROM {$wpdb->posts}",
            'join'   => "LEFT JOIN {$wpdb->term_relationships} AS br_product_cat_relationships ON {$wpdb->posts}.ID = br_product_cat_relationships.object_id
                         LEFT JOIN {$wpdb->term_taxonomy} AS br_product_cat_taxonomy ON br_product_cat_relationships.term_taxonomy_id = br_product_cat_taxonomy.term_taxonomy_id AND br_product_cat_taxonomy.taxonomy = 'product_cat'
                         LEFT JOIN {$wpdb->terms} AS br_product_cat_terms ON br_product_cat_taxonomy.term_id = br_product_cat_terms.term_id",
            'where'  => array()
        );

        $search_like = '%' . $wpdb->esc_like( $search ) . '%';
        if( ! empty($options['custom_search_by_title'])
            || ( empty($options['custom_search_by_description']) && empty($options['custom_search_by_excerpt']) && empty($options['custom_search_by_sku']) )
        ) {
            $query['where'][] = $wpdb->prepare("{$wpdb->posts}.post_title LIKE %s", $search_like);
        }
        if( ! empty($options['custom_search_by_description']) ) {
            $query['where'][] = $wpdb->prepare("{$wpdb->posts}.post_content LIKE %s", $search_like);
        }
        if( ! empty($options['custom_search_by_excerpt']) ) {
            $query['where'][] = $wpdb->prepare("{$wpdb->posts}.post_excerpt LIKE %s", $search_like);
        }
        if( ! empty($options['custom_search_by_sku']) ) {
            $query['join'] .= " LEFT JOIN {$wpdb->postmeta} as br_sku on {$wpdb->posts}.ID = br_sku.post_id AND br_sku.meta_key = '_sku'";
            $query['where'][] = $wpdb->prepare("br_sku.meta_value LIKE %s", $search_like);
        }
        $query['where'][] = $wpdb->prepare( 'br_product_cat_terms.name LIKE %s', $search_like );
        $query['where'] = implode(' OR ', $query['where']);
        $query_string = $query['select'] . ' ' . $query['join'];
        if( ! empty($query['where']) ) {
            $query_string .= " WHERE {$wpdb->posts}.post_type IN ('product', 'product_variation') AND {$wpdb->posts}.post_status = 'publish' AND (" . $query['where'] . ')';
            $posts = $wpdb->get_col($query_string);
        }
        $posts = is_array( $posts ) ? array_values( array_unique( array_filter( array_map( 'absint', $posts ) ) ) ) : array();
        set_transient( $cache_key, $posts, self::SEARCH_CACHE_TTL );
        return $this->set_search_posts( $args, $posts );
    }

    private function set_search_posts( $args, $posts ) {
        if ( empty( $posts ) || ! is_array( $posts ) ) {
            $args['post__in'] = array( 0 );
        } elseif( ! empty($args['post__in']) && is_array($args['post__in']) && count($args['post__in']) > 0 ) {
            $posts = array_values( array_intersect( array_map( 'absint', $args['post__in'] ), $posts ) );
            $args['post__in'] = empty( $posts ) ? array( 0 ) : $posts;
        } else {
            $args['post__in'] = $posts;
        }
        return $args;
    }
    function relevanssi_search($args, $search) {
        $cache_key = 'bapf_relevanssi_search_' . md5( $search );
        $posts = get_transient( $cache_key );
        if ( false !== $posts && is_array( $posts ) ) {
            return $this->set_search_posts( $args, $posts );
        }

        $new_args  = $args;
        $new_args['s'] = $search;
        $new_args['nopaging'] = true;
        $new_args['post_type'] = array( 'product', 'product_variation' );
        $new_args['post_status'] = 'publish';
        $new_args['no_found_rows'] = true;
        $new_args['fields'] = 'ids';
        global $wpdb;
        $queryrelevanssi = new WP_Query();
        $queryrelevanssi->parse_query( $new_args );
        $queryrelevanssi = apply_filters( 'relevanssi_modify_wp_query', $queryrelevanssi );

        $posts = relevanssi_do_query( $queryrelevanssi );
        $posts = is_array( $posts ) ? array_values( array_unique( array_filter( array_map( 'absint', $posts ) ) ) ) : array();
        set_transient( $cache_key, $posts, self::SEARCH_CACHE_TTL );
        return $this->set_search_posts( $args, $posts );
    }
    function addon_data($data) {
        $data['tooltip'] .= '<br><a href="'.admin_url('admin.php?page=br-product-filters&tab=advanced#custom_search_by').'">'.__('Add-on options', 'BeRocket_AJAX_domain').'</a>';
        return $data;
    }
    function defaults_value($options) {
        if( empty($options['custom_search_by_title']) && empty($options['custom_search_by_description']) && empty($options['custom_search_by_excerpt']) && empty($options['custom_search_by_sku']) ) {
            $options['custom_search_by_title']       = '1';
            $options['custom_search_by_description'] = '1';
            $options['custom_search_by_excerpt']     = '1';
        }
        return $options;
    }
}
new BeRocket_aapf_custom_search_filters();
