<?php

class Facet_Wp_Remote_Data_Handler {

	private static $facetwp_remote_data = null;

	public $background_process;

	private const FACETWP_API_ENDPOINT = '/wp-json/facetwp/v1/fetch';

	private const REMOTE_SITE_PROPERTY_POST_TYPE_SLUG = 'property';

	private const REMOTE_SITE_PROPERTIES_REST_ENDPOINT = '/wp-json/sw-facetwp/v1/properties';

	private const REMOTE_SITE_PROPERTY_REST_ENDPOINT = '/wp-json/sw-facetwp/v1/property';

	private const REMOTE_SITE_LATEST_PROPERTIES_REST_ENDPOINT = '/wp-json/sw-facetwp/v1/latest-listings';

	private const REMOTE_SITE_CURRENT_PROPERTIES_REST_ENDPOINT = '/wp-json/sw-facetwp/v1/current-listings';

    public const PRICE_RANGE_LINKS_FACET_NAME = 'price_range_links';

	public const SW_FACET_AUTOCOMPLETE_COOKIE_NAME = 'sw_facetwp_autocomplete_data';

	public static $posts_per_page = 12;

    public function __construct() {
	    $this->background_process = new Facet_Wp_Remote_Data_Background_Process();
    }

	public function facetwp_template_html( $output, $class ) {
		$current_page_id = $this->get_page_id_from_facet_params( $class->http_params );

		if ( ! $this->should_use_main_site_facet_wp_data( $current_page_id ) ) return $output;

		$remote_data = $this->get_facetwp_remote_data( $class );

		$posts_data = $remote_data['posts'] ?? null;

		if ( ! $posts_data ) return $output;

		$template_vars = [
			'properties_data' => $posts_data,
		];

		$template_path = apply_filters(
			'facet_wp_remote_data_listing_template_path',
			$this->get_template_path( 'listing-template', $current_page_id ),
			$template_vars
		);

		do_action( 'facet_wp_listing_page_load', $template_path, $template_vars );

		extract( $template_vars, EXTR_SKIP );

		ob_start();

		include $template_path;

		return ob_get_clean();
    }

    public function facetwp_facet_render_args( $args ) {
	    $current_page_id = $this->get_page_id_from_facet_params( $_POST['data']['http_params'] ?? null );

	    if ( ! $this->should_use_main_site_facet_wp_data( $current_page_id ) ) return $args;

	    $facet = $args['facet'];
	    $facet_name = $facet['name'];
	    $facet_type = $facet['type'];

	    if ( 'sort' === $facet_type ) {
		    $selected = FWP()->facet->facets[ $facet_name ]['selected_values'] ?? [];

		    // fallback to default
		    if ( empty( $selected ) ) {
			    $default_sort_value = get_option( 'facetwp_remote_data_default_sort_option' );

			    if ( ! empty( $default_sort_value ) ) {
				    $selected = [ $default_sort_value ];
			    }
		    }

		    $choices = [];

		    if ( ! empty( $facet['sort_options'] ) && is_array( $facet['sort_options'] ) ) {
			    foreach ( $facet['sort_options'] as $option ) {
				    if ( ! empty( $option['name'] ) && ! empty( $option['label'] ) ) {
					    $choices[] = [
						    'facet_value'         => $option['name'],
						    'facet_display_value' => $option['label'],
					    ];
				    }
			    }
		    }

		    $args['values'] = $choices;
		    $args['selected_values'] = $selected;

		    return $args;
	    }

		$remote_data = $this->get_facetwp_remote_data();

		$choices = $remote_data['facet_data']['facets'][$facet_name]['choices'] ?? null;

		if ( empty( $choices ) ) return $args;

		$values = [];

		foreach ( $choices as $choice ) {
			$values[] = [
				'facet_value' => $choice['value'],
				'facet_display_value' => $choice['label'],
				'term_id' => $choice['term_id'],
				'depth' => $choice['depth'],
				'counter' => $choice['count'],
			];
		}

		if ( ! empty( $values ) ) {
			$args['values'] = $values;
		}

		return $args;
	}

    public function facetwp_facet_price_range_links_render_args( $args ) {
	    if ( self::PRICE_RANGE_LINKS_FACET_NAME !== $args['facet']['name'] ) {
		    return $args;
	    }

	    global $wpdb;

	    $facets_from_option = $this->get_facets_from_options();

	    $current_request_facets = FWP()?->facet?->facets;

	    $facets_for_request = [];

	    if ( ! empty( $facets_from_option ) && ! empty( $current_request_facets ) ) {
		    foreach ( $facets_from_option as $facet ) {
			    $facets_for_request[ $facet['name'] ] = ! empty( $current_request_facets[ $facet['name'] ]['selected_values'] )
				    ? $current_request_facets[ $facet['name'] ]['selected_values']
				    : [];
		    }
	    }

	    unset( $facets_for_request[ self::PRICE_RANGE_LINKS_FACET_NAME ] );

	    $facetwp_remote_site_filtered_data = $this->get_remote_site_facetwp_filtered_data( null, null, $facets_for_request );

	    $post_ids = $facetwp_remote_site_filtered_data['results'] ?? [];

	    if ( empty( $post_ids ) ) {
		    $args['values'] = [];
		    return $args;
	    }

	    $ranges = [
		    '0|100000'          => 'Under $100,000',
		    '100000|200000'     => '$100,000 – $200,000',
		    '200000|300000'     => '$200,000 – $300,000',
		    '300000|400000'     => '$300,000 – $400,000',
		    '400000|500000'     => '$400,000 – $500,000',
		    '500000|600000'     => '$500,000 – $600,000',
		    '600000|700000'     => '$600,000 – $700,000',
		    '700000|800000'     => '$700,000 – $800,000',
		    '800000|900000'     => '$800,000 – $900,000',
		    '900000|1000000'    => '$900,000 – $1,000,000',
		    '1000000|999999999' => 'Over $1,000,000',
	    ];

	    $args['values'] = [];

	    foreach ( $ranges as $range_key => $label ) {
		    list( $min, $max ) = explode( '|', $range_key );

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

		    $count = (int) $wpdb->get_var( $wpdb->prepare( "
                SELECT COUNT(DISTINCT post_id)
                FROM {$wpdb->prefix}facetwp_index
                WHERE facet_name = %s
                    AND post_id IN (" . implode( ',', array_map( 'absint', $post_ids ) ) . ")
                    AND facet_value BETWEEN %d AND %d
            ", self::PRICE_RANGE_LINKS_FACET_NAME, $min, $max ) );

		    if ( $count > 0 ) {
			    $args['values'][] = [
				    'facet_value'         => $range_key,
				    'facet_display_value' => $label,
				    'counter'             => $count,
			    ];
		    }
	    }

	    // Tell FacetWP to not append raw values
	    $args['show_expanded'] = false;
	    $args['soft_limit']    = true;

	    return $args;
    }

	public function facetwp_pager_args( $pager_args, $class ) {
		$current_page_id = $this->get_page_id_from_facet_params( $class->http_params );

		if ( ! $this->should_use_main_site_facet_wp_data( $current_page_id ) ) return $pager_args;

		$remote_data = $this->get_facetwp_remote_data();

		$pager_args = $remote_data['facet_data']['pager'] ?? $pager_args;

		return $pager_args;
	}

	// @see web/wp-content/plugins/facetwp/includes/facets/autocomplete.php
	public function forward_facetwp_ajax_load_to_main_site() {
		if (
			! isset( $_POST['action'] )
			|| 'facetwp_autocomplete_load' !== $_POST['action']
		) {
			return;
		}

		$current_page_id = $this->get_page_id_from_facet_params( $_POST['data']['http_params'] ?? null );

		if ( ! $this->should_use_main_site_facet_wp_data( $current_page_id ) ) return;

		$response = $this->make_api_request(
			'post',
			'/wp-json/sw-facetwp/v1/forward-facetwp-autocomplete-ajax-call',
			null,
			$_POST,
		);

		if ( is_wp_error( $response ) ) {
			error_log( "ERROR fetching remote site FacetWP settings data. " . $response->get_error_message() );

			wp_send_json_error(
				new WP_Error( 'http_error', $response->get_error_message(), ['status' => 500] )
			);

			exit();
		}

		$http_code = wp_remote_retrieve_response_code( $response );
		$body_json = wp_remote_retrieve_body( $response );
		$data = json_decode( $body_json, true );

		if ( $http_code !== 200 ) {
			error_log( "ERROR fetching remote site FacetWP settings data. " . print_r( $data, true ) );

			wp_send_json_error(
				new WP_Error( 'http_error', "Received HTTP status code {$http_code} with message '{$data['message']}'", ['status' => $http_code] )
			);

			exit();
		}

		setcookie(
			self::SW_FACET_AUTOCOMPLETE_COOKIE_NAME,
			json_encode( $data ),
			time() + 60 * 10,
			COOKIEPATH,
			COOKIE_DOMAIN,
			is_ssl(),
			false
		);

		wp_send_json( $data );

		exit();
	}

	public function facetwp_map_init_args( $settings ) {
		if ( ! $this->should_use_main_site_facet_wp_data() ) return $settings;

		$locations_map_data = $this->get_properties_map_data_from_remote_site();

		if ( ! $locations_map_data ) return $settings;

        [
            'current_page_locations' => $current_page_locations,
            'all_locations' => $all_locations
        ] = $locations_map_data;

		if ( ! empty( $current_page_locations ) && ! empty( $all_locations ) ) {
			$settings['current_page_locations'] = $current_page_locations;
			$settings['locations'] = $all_locations;
		}

		return $settings;
	}

	public function facetwp_map_add_locations_on_refresh_event( $output, $data_array ) {
		if ( ! empty( $output ) ) {
			$output = json_decode( $output, true );

			if (
				is_array( $output )
				&& isset( $output['settings']['map'] )
				&& empty( $output['settings']['map']['locations'] )
			) {
				if ( empty( $output['settings']['map'] ) ) {
					$output['settings']['map'] = $this->get_map_facet_settings();

					if ( ! empty( $map_facet_settings ) ) {
						$output['facets']['map'] = $map_facet_settings;
					}
				}

				$locations_map_data = $this->get_properties_map_data_from_remote_site();

				if ( ! empty( $locations_map_data ) ) {
					[
						'current_page_locations' => $current_page_locations,
						'all_locations' => $all_locations
					] = $locations_map_data;

					if ( ! empty( $current_page_locations ) && ! empty( $all_locations ) ) {
						$output['settings']['map']['current_page_locations'] = $current_page_locations;
						$output['settings']['map']['locations'] = $all_locations;
					}
                }
			}
		}

		return is_array( $output ) ? json_encode( $output ) : $output;
	}

    private function get_properties_map_data_from_remote_site() {
	    $remote_data = $this->get_facetwp_remote_data();

	    if ( ! $remote_data ) return null;

	    $filtered_ids = $remote_data['facet_data']['results'] ?? [];

	    $all_locations = ! empty( $filtered_ids )
		    ? $this->get_remote_data_all_locations_from_ids( $filtered_ids )
		    : $this->get_remote_data_all_locations();

        return [
            'current_page_locations' => $this->generate_location_data_for_facet_map_setting( $remote_data['posts'] ?? [] ),
            'all_locations' => $this->generate_location_data_for_facet_map_setting( $all_locations ?? [] ),
        ];
    }

	private function get_remote_data_all_locations_from_ids( $post_ids ) {
		if ( empty( $post_ids ) ) return [];

		$response = $this->make_api_request(
			'post',
			'/wp-json/sw-facetwp/v1/get-all-locations',
			null,
			['post_ids' => $post_ids],
		);

		if ( is_wp_error( $response ) ) {
			error_log( 'Error fetching remote locations: ' . $response->get_error_message() );
			return [];
		}

		$code = wp_remote_retrieve_response_code( $response );
		$body = wp_remote_retrieve_body( $response );
		$data = json_decode( $body, true );

		if ( $code !== 200 || ! is_array( $data ) ) {
			error_log( "Invalid response: HTTP $code - " . print_r( $data, true ) );
			return [];
		}

		return $data;
	}

    public function get_remote_data_all_locations( $mls = null ) {
	    $selected_mls = $mls ?? ( FWP()->facet->facets['mls']['selected_values'][0] ?? null );

	    $transient_key = ! empty( $selected_mls )
		    ? Facet_Wp_Remote_Data_Cache::all_locations_for_mls( $selected_mls )
		    : Facet_Wp_Remote_Data_Cache::FACETWP_MAP_ALL_LOCATIONS;

	    $skip_cache = apply_filters( 'facetwp_remote_data_skip_cache', false );

	    $data = ! $skip_cache
		    ? Facet_Wp_Remote_Data_Cache::get( $transient_key )
		    : false;

	    if ( false === $data ) {
		    global $wpdb;

		    $table = $wpdb->prefix . 'facetwp_index';

		    if ( ! empty( $selected_mls ) ) {
			    // Fetch posts only for selected MLS
			    $query = "
                    SELECT DISTINCT post_id
                    FROM $table
                    WHERE facet_name = 'mls'
                        AND facet_value = %s
                ";

			    $post_ids = $wpdb->get_col( $wpdb->prepare( $query, $selected_mls ) );
		    } else {
			    // Default: all posts
			    $query = "
                    SELECT DISTINCT post_id
                    FROM $table
                    WHERE facet_name = 'mls'
                ";

			    $post_ids = $wpdb->get_col( $query );
		    }

		    if ( ! empty( $post_ids ) ) {
			    $response = $this->make_api_request(
				    'post',
				    '/wp-json/sw-facetwp/v1/get-all-locations',
				    null,
				    ['post_ids' => $post_ids],
			    );

			    if ( is_wp_error( $response ) ) {
				    error_log( "ERROR fetching remote site FacetWP settings data. " . $response->get_error_message() );

				    return new WP_Error( 'http_error', $response->get_error_message(), ['status' => 500] );
			    }

			    $http_code = wp_remote_retrieve_response_code( $response );
			    $body_json = wp_remote_retrieve_body( $response );
			    $data = json_decode( $body_json, true );

			    if ( $http_code !== 200 ) {
				    error_log( "ERROR fetching remote site FacetWP settings data. " . print_r( $data, true ) );

				    return new WP_Error( 'http_error', "Received HTTP status code {$http_code} with message '{$data['message']}'", ['status' => $http_code] );
			    }

			    Facet_Wp_Remote_Data_Cache::set( $transient_key, $data );
		    }
        }

	    return $data ?: null;
    }

    private function get_map_facet_settings() {
	    $transient_key = Facet_Wp_Remote_Data_Cache::FACETWP_MAP_FACET_SETTINGS;

	    $skip_cache = apply_filters( 'facetwp_remote_data_skip_cache', false );

	    $settings = ! $skip_cache
		    ? Facet_Wp_Remote_Data_Cache::get( $transient_key )
		    : false;

	    if ( false === $settings ) {
		    foreach ( FWP()->facet->facets as $name => $facet ) {
			    if ( 'map' == $facet['type'] ) {
				    $settings['config'] = [
					    'default_lat'   => (float) $facet['default_lat'],
					    'default_lng'   => (float) $facet['default_lng'],
					    'default_zoom'  => (int) $facet['default_zoom'],
					    'spiderfy'      => [
						    'markersWontMove'   => true,
						    'markersWontHide'   => true,
						    'basicFormatEvents' => true,
						    'keepSpiderfied'    => true
					    ]
				    ];

				    if ( 'yes' == $facet['cluster'] ) {
					    $settings['config']['cluster'] = [
						    'imagePath' => FACETWP_MAP_URL . '/assets/img/m',
						    'imageExtension' => 'png',
						    'zoomOnClick' => false,
						    'maxZoom' => 15,
					    ];
				    }

				    $settings['init'] = [
					    'gestureHandling' => 'auto',
					    'styles' => ( new FacetWP_Facet_Map_Addon() )->get_map_design( $facet['map_design'] ),
					    'zoom' => (int) $facet['default_zoom'] ?: 5,
					    'minZoom' => (int) $facet['min_zoom'] ?: 1,
					    'maxZoom' => (int) $facet['max_zoom'] ?: 20,
					    'center' => [
						    'lat' => (float) $facet['default_lat'],
						    'lng' => (float) $facet['default_lng'],
					    ],
				    ];

				    Facet_Wp_Remote_Data_Cache::set( $transient_key, $settings );

                    break;
			    }
		    }
        }

	    return $settings;
    }

	private function generate_location_data_for_facet_map_setting( $posts_data ) {
        if ( empty( $posts_data ) ) return [];

		$locations_settings_data = [];

		array_walk(
			$posts_data,
			function ( $post_data ) use ( &$locations_settings_data ) {
                if ( empty( $post_data ) ) return;

				$property_image = ! empty( $post_data['featured_image'] ) ? esc_url( $post_data['featured_image'] ) : '';
				$property_address = ! empty( $post_data['address'] ) ? esc_html( $post_data['address'] ) : '';
				$property_price = ! empty( $post_data['price'] ) ? '$' . number_format( $post_data['price'] ) : '';
				$property_bedrooms = (int) $post_data['bedrooms'];
				$property_bathrooms = (int) $post_data['bathrooms'];

				$property_square_feet = ! empty( $post_data['square_feet'] )
                    ? filter_var( $post_data['square_feet'], FILTER_SANITIZE_NUMBER_INT )
                    : 0.00;
				$property_square_feet = $property_square_feet >= 1000
					? rtrim( rtrim( number_format( $property_square_feet / 1000, 1 ), '0' ), '.' ) . 'k'
					: number_format( $property_square_feet );

				$property_link = $this->create_property_link( $post_data['property_id'], $post_data['address'] );

				$content_html = '
	                <div style="display: flex; align-items: center; justify-content: space-between; padding-right: 10px; font-family: Arial, sans-serif; width: 340px; position: absolute; top: 50%; transform: translateY(-50%); left: 0;">
	                    <a href="' . $property_link . '">
	                        <img src="' . $property_image . '" alt="' . $property_address . '" style="object-fit: cover; border-radius: 5px; width: 100%;">
	                    </a>
	                    <div style="display: flex; flex-direction: column; justify-content: center; width: 60%; padding-left: 10px;">
	                        <p style="margin: 0 0 10px 0; font-size: 1.5rem; font-weight: bold; color: #222;">' . $property_price . '</p>
	                        <div style="display: grid; grid-template-columns: repeat(3, 1fr); grid-gap: 12px; margin: 0; padding: 0; font-size: 14px; color: #555; list-style: none;">
	                            <div style="display: grid; grid-template-columns: repeat(1, 1fr); grid-gap: 4px; margin: 0; padding: 0;">
	                                <div style="font-size: 18px;">' . $property_bedrooms . '</div>
	                                <div style="margin-right: auto; color: #4a484a; font-size: .75rem; line-height: 16px; letter-spacing: 1px; font-weight: 400; text-transform: uppercase;">BEDS</div>
                                </div>
                                <div style="display: grid; grid-template-columns: repeat(1, 1fr); grid-gap: 4px; margin: 0; padding: 0;">
	                                <div style="font-size: 18px;">' . $property_bathrooms . '</div>
	                                <div style="margin-right: auto; color: #4a484a; font-size: .75rem; line-height: 16px; letter-spacing: 1px; font-weight: 400; text-transform: uppercase;">BATHS</div>
                                </div>
                                <div style="display: grid; grid-template-columns: repeat(1, 1fr); grid-gap: 4px; margin: 0; padding: 0;">
	                                <div style="font-size: 18px;">' . $property_square_feet . '</div>
	                                <div style="margin-right: auto; color: #4a484a; font-size: .75rem; line-height: 16px; letter-spacing: 1px; font-weight: 400; text-transform: uppercase;">SQFT</div>
                                </div>
	                        </div>
	                    </div>
	                </div>';

				$locations_settings_data[] = [
					'position' => [
						'lat' => apply_filters( 'location_map_data_lat', (float) $post_data['latitude'], $post_data ),
						'lng' => apply_filters( 'location_map_data_lng', (float) $post_data['longitude'], $post_data ),
					],
					'post_id' => (int) $post_data['post_id'],
					'content' => apply_filters( 'location_map_data_content', $content_html, $post_data )
				];
			}
		);

		return $locations_settings_data;
	}

	public function property_page_rewrite_rule() {
        add_rewrite_rule(
            '^property/([A-Za-z0-9]+)-[^/]+/?$',
            'index.php?sw_remote_data_property_page=1&property_id=$matches[1]',
            'top'
        );
	}

	public function property_page_rewrite_rule_query_vars( $vars ) {
		$vars[] = 'sw_remote_data_property_page';
		$vars[] = 'property_id';

		return $vars;
	}

	public function property_page_template() {
		global $wp_query;

		if ( '1' === get_query_var( 'sw_remote_data_property_page' ) ) {
			$property_id = sanitize_text_field( get_query_var( 'property_id' ) );

			if ( empty( $property_id ) ) wp_die( 'No Property ID' );

			$transient_key = Facet_Wp_Remote_Data_Cache::property_remote_site_data( $property_id );

			$skip_cache = apply_filters( 'facetwp_remote_data_skip_cache', false );

			$post_remote_data = ! $skip_cache
				? Facet_Wp_Remote_Data_Cache::get( $transient_key )
				: false;

			if ( false === $post_remote_data ) {
				$post_remote_data = $this->get_property_remote_site_data( $property_id );

                if ( ! $post_remote_data ) {
                    $wp_query->set_404();
                    status_header( 404 );
                    get_template_part( 404 );

                    exit();
                }

				Facet_Wp_Remote_Data_Cache::set( $transient_key, $post_remote_data );
			}

			$template_vars = [
				'property_data' => $post_remote_data,
			];

			$template_path = apply_filters(
				'facet_wp_remote_data_property_template_path',
				$this->get_template_path( 'property-template' ),
				$template_vars
			);

			do_action( 'facet_wp_property_page_load', $template_path, $template_vars );

			extract( $template_vars, EXTR_SKIP );

			include $template_path;

			exit();
		}
	}

    public function facetwp_facet_dropdown_show_counts() {
        return false;
    }

	public function facetwp_indexer_is_enabled() {
		return false;
	}

    public static function force_cache_update() {
	    if ( defined( 'WP_CLI' ) && WP_CLI ) {
		    WP_CLI::log( 'Facet_Wp_Remote_Data_Handler::force_cache_update()' );
	    }

        add_filter( 'facetwp_remote_data_skip_cache', '__return_true' );

        $instance = ( new self );

        $instance->update_home_page_cache();

        $latest_listings_posts_per_page = apply_filters( 'sw_warmup_cache_latest_listings_posts_per_page', 12 );
        self::get_latest_listings( $latest_listings_posts_per_page );

        $current_listings_posts_per_page = apply_filters( 'sw_warmup_cache_current_listings_posts_per_page', 12 );
        self::get_current_listings( $current_listings_posts_per_page );

//	    $instance->force_update_mls_search_landing_pages_cache();
    }

	private function update_home_page_cache() {
		$post_id = get_option( 'page_on_front' );

		$class = new stdClass();
		$class->http_params = [
			'get' => [],
			'uri' => '',
			'url_vars' => [],
		];

        // Preselected facets
		$preselected_facets = [];

		if ( ! empty( $post_id ) ) {
			$facets = FWP()->helper->get_facets();

			foreach ( $facets as $facet ) {
				$facet_name = $facet['name'];

				$preselected_value = get_post_meta(
					$post_id,
					Facet_Wp_Remote_Data_Neighborhood_Page::PREFIX_FACET_WP_REMOTE_DATA_PRESELECTED__FACET . $facet_name,
					true
				);

				if ( ! empty( $preselected_value ) && empty( $facets_for_request[ $facet_name ] ) ) {
					$preselected_facets[ $facet_name ] = $preselected_value;
				}
			}
		}

		if ( ! empty( $preselected_facets ) ) {
			$class->http_params['get'][ '_' . $facet_name ] = implode( ',', $preselected_facets );

			foreach ( $preselected_facets as $facet_name => $facet_value ) {
				$class->http_params['url_vars'][ $facet_name ][] = $facet_value;
			}
		}

        // Allowed property types
		$allowed_property_types = get_option( 'facetwp_remote_data_only_show_property_types' );

		if ( ! empty( $allowed_property_types ) ) {
			$class->http_params['get']['_property_type'] = implode( ',', $allowed_property_types );

			foreach ( $allowed_property_types as $allowed_property_type ) {
				$class->http_params['url_vars']['property_type'][] = $allowed_property_type;
			}
		}

		$this->get_facetwp_remote_data( $class );
	}

	private function get_facetwp_remote_data( $class = null ) {
		$skip_cache = apply_filters( 'facetwp_remote_data_skip_cache', false );

		if (
			( is_null( self::$facetwp_remote_data ) && ! is_null( $class ) )
            || ( is_null( self::$facetwp_remote_data ) && $skip_cache )
		) {
			$query_args = $class && ! empty( array_filter( $class->http_params ) )
				? $class->http_params
				: 'facetwp_remote_data_default';

			$transient_key = Facet_Wp_Remote_Data_Cache::remote_site_facet_search_data( $query_args );

			$cached_data = ! $skip_cache
				? Facet_Wp_Remote_Data_Cache::get( $transient_key )
				: false;

			if ( false === $cached_data ) {
				$facetwp_remote_site_filtered_data = $this->get_remote_site_facetwp_filtered_data( $class );

				$all_post_ids = $facetwp_remote_site_filtered_data['results'] ?? [];

				$page = isset( $_GET['_paged'] ) && is_numeric( $_GET['_paged'] ) && $_GET['_paged'] > 0
					? (int) $_GET['_paged']
					: 1;

				$per_page = apply_filters( 'facet_wp_remote_data_posts_per_page', self::$posts_per_page );

                $sort_facet_option = $this->get_sort_facet_selection( $class );

				$posts_data = $this->get_remote_site_posts( $all_post_ids, false, $page, $per_page, $sort_facet_option );

                $cached_data = [
                    'facet_data' => $facetwp_remote_site_filtered_data,
                    'posts' => $posts_data
                ];

                Facet_Wp_Remote_Data_Cache::set( $transient_key, $cached_data );
			}

            self::$facetwp_remote_data = $cached_data;
		}

		return self::$facetwp_remote_data ?? null;
	}

	private function get_filtered_post_ids_from_local_index( $facets_for_request ) {
		global $wpdb;

		$post_id_sets  = [];
		$facets_config = $this->get_facets_from_options();

		foreach ( $facets_for_request as $facet => $values ) {
			if ( empty( $values ) ) {
				continue;
			}

			$facet_type = '';
			foreach ( $facets_config as $config ) {
				if ( $config['name'] === $facet ) {
					$facet_type = $config['type'] ?? '';
					break;
				}
			}

			if ( 'sort' === $facet_type ) continue;

			$values = is_array( $values ) ? $values : [ $values ];

			if ( 'map' === $facet && count( $values ) === 4 ) {
				// Handle bounding box for map
				list( $min_lat, $min_lng, $max_lat, $max_lng ) = array_map( 'floatval', $values );

				$map_filtered_ids = $wpdb->get_col( $wpdb->prepare( "
                    SELECT post_id
                    FROM {$wpdb->prefix}facetwp_index
                    WHERE facet_name = 'map'
                        AND CAST(facet_value AS DECIMAL(10,6)) BETWEEN %f AND %f
                        AND CAST(facet_display_value AS DECIMAL(10,6)) BETWEEN %f AND %f
                ", $min_lat, $max_lat, $min_lng, $max_lng ) );

				if ( ! empty( $map_filtered_ids ) ) {
					$post_id_sets[] = $map_filtered_ids;
				} else {
					return []; // no matches from map bounds
				}

				continue;
			}

			if ( in_array( $facet_type, [ 'autocomplete', 'proximity' ], true ) ) {
				// LIKE search
				$conditions = [];
				$params = [ $facet ];

				foreach ( $values as $value ) {
					$conditions[] = "facet_display_value LIKE %s";
					$params[] = '%' . $wpdb->esc_like( $value ) . '%';
				}

				$where = implode( ' OR ', $conditions );

				$query = "
                    SELECT DISTINCT post_id
                    FROM {$wpdb->prefix}facetwp_index
                    WHERE facet_name = %s AND ( $where )
                ";

				$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );

			} elseif ( 'number_range' === $facet_type && count( $values ) === 2 ) {
				$from = isset( $values[0] ) && is_numeric( $values[0] ) ? (float) $values[0] : null;
				$to   = isset( $values[1] ) && is_numeric( $values[1] ) ? (float) $values[1] : null;

				if ( null !== $from && null !== $to ) {
					// BETWEEN
					$query = "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = %s AND facet_value BETWEEN %f AND %f
                    ";
					$params = [ $facet, $from, $to ];
					$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );

				} elseif ( null !== $from ) {
					// Only FROM
					$query = "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = %s AND facet_value >= %f
                    ";
					$params = [ $facet, $from ];
					$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );

				} elseif ( null !== $to ) {
					// Only TO
					$query = "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = %s AND facet_value <= %f
                    ";
					$params = [ $facet, $to ];
					$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );

				} else {
					// Both empty
					$ids = [];
				}

			} elseif ( self::PRICE_RANGE_LINKS_FACET_NAME === $facet ) {
				// Custom price range logic from dropdown (formatted like "100000|200000")
				$conditions = [];
				$params = [];

				foreach ( $values as $value ) {
					$range = explode( '|', $value );

					if ( 2 === count( $range ) ) {
						$conditions[] = '(facet_value BETWEEN %f AND %f)';
						$params[] = (float) $range[0];
						$params[] = (float) $range[1];
					}
				}

				if ( ! empty( $conditions ) ) {
					$where = implode( ' OR ', $conditions );

					$query = "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = %s AND ( $where )
                    ";

					$params = array_merge( [ $facet ], $params );

					$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );
				} else {
					$ids = [];
				}

			} else {
				// Exact match IN search
				$placeholders = implode( ',', array_fill( 0, count( $values ), '%s' ) );
				$query = "
                    SELECT DISTINCT post_id
                    FROM {$wpdb->prefix}facetwp_index
                    WHERE facet_name = %s AND facet_value IN ($placeholders)
                ";
				$params = array_merge( [ $facet ], $values );

				$ids = $wpdb->get_col( $wpdb->prepare( $query, ...$params ) );
			}

			$post_id_sets[] = $ids;
		}

		if ( empty( $post_id_sets ) ) {
			return null;
		}

		$post_ids = array_shift( $post_id_sets );

		foreach ( $post_id_sets as $set ) {
			$post_ids = array_intersect( $post_ids, $set );
		}

		$post_ids = array_values( $post_ids ?: [] );

		$remove_duplicate_addresses = get_option( 'facetwp_remote_data_remove_duplicate_addresses', false );

		if ( ! empty( $post_ids ) && $remove_duplicate_addresses ) {
			global $wpdb;

			$address_facet = apply_filters( 'facetwp_remote_data_address_facet_name', 'address' );
			$strategy      = apply_filters( 'facetwp_remote_data_dedupe_strategy', 'latest' ); // 'latest' or 'earliest'
			$keep_fn       = ( 'earliest' === $strategy ) ? 'MIN' : 'MAX';

			$ids          = array_values( array_unique( array_map( 'absint', $post_ids ) ) );
			$placeholders = implode( ',', array_fill( 0, count( $ids ), '%d' ) );

			/**
			 * Normalization without regex:
			 * - Lowercase
			 * - Trim + strip trailing commas/dots
			 * - Replace CR/LF/TAB with space (using CHAR() so it's SQL-mode safe)
			 * - Collapse multiple spaces by running REPLACE('  ',' ') a few times
			 *   (good enough for practical inputs)
			 */
			$norm_expr = "
                LOWER(
                    TRIM(BOTH ',. ' FROM
                        REPLACE(
                            REPLACE(
                                REPLACE(
                                    REPLACE(
                                        REPLACE(
                                            REPLACE(i.facet_display_value, CHAR(13), ''),  -- CR
                                        CHAR(10), ' '),                                   -- LF
                                    CHAR(9),  ' '),                                     -- TAB
                                '  ', ' '),
                            '  ', ' '),
                        '  ', ' ')
                    )
                )
            ";

			// One ID per normalized address (MAX/MIN post_id decides which one to keep)
			$sql = "
                SELECT {$keep_fn}(i.post_id) AS post_id
                FROM {$wpdb->prefix}facetwp_index i
                WHERE i.facet_name = %s
                    AND i.post_id IN ($placeholders)
                GROUP BY {$norm_expr}
            ";

			$keep_ids = $wpdb->get_col(
				$wpdb->prepare( $sql, array_merge( [ $address_facet ], $ids ) )
			);

			// Preserve original order from $post_ids
			$keep_set = array_flip( array_map( 'intval', (array) $keep_ids ) );
			$post_ids = array_values( array_filter( $ids, static fn( $id ) => isset( $keep_set[ (int) $id] ) ) );
		}

		return $post_ids;
	}

	public function get_remote_site_facetwp_filtered_data( $class = null, $posts_per_page = null, $facets_for_request = [] ) {
		global $wpdb;

		$facets_from_option = $this->get_facets_from_options();

		if ( empty( $facets_for_request ) && ! empty( $facets_from_option ) ) {
			foreach ( $facets_from_option as $facet ) {
				$facets_for_request[ $facet['name'] ] = $class
					? $class->facets[ $facet['name'] ]['selected_values'] ?? []
					: [];
			}
		}

		$facets_for_request = $this->ensure_preselected_facet_choice_is_included( $facets_for_request, $class?->http_params );

		$facets_for_request = $this->inject_allowed_property_types_if_none_selected( $facets_for_request );

		$page = isset( $_GET['_paged'] ) && is_numeric( $_GET['_paged'] ) && $_GET['_paged'] > 0
			? (int) $_GET['_paged']
			: 1;

		$per_page = apply_filters( 'facet_wp_remote_data_posts_per_page', $posts_per_page ?? self::$posts_per_page );

		$filtered_post_ids = $this->get_filtered_post_ids_from_local_index( $facets_for_request );

		if ( is_null( $filtered_post_ids ) ) {
			// No filters selected, fetch all post IDs
			$total_count = (int) $wpdb->get_var( "
                SELECT COUNT(DISTINCT post_id)
                FROM {$wpdb->prefix}facetwp_index
                WHERE facet_name = 'mls'
            " );

			$post_ids_query = "
                SELECT DISTINCT post_id
                FROM {$wpdb->prefix}facetwp_index
                WHERE facet_name = 'mls'
                ORDER BY post_id DESC
            ";

			$results = $wpdb->get_col( $post_ids_query );
		} else {
			$total_count = count( $filtered_post_ids );
			$results = $filtered_post_ids;
		}

		$facets = [];

		foreach ( $facets_from_option as $facet ) {
			$name     = $facet['name'];
			$label    = $facet['label'] ?? ucfirst( $name );
			$type     = $facet['type'] ?? 'dropdown';
			$selected = $facets_for_request[ $name ] ?? [];

			if ( in_array( $type, ['autocomplete'] ) ) continue;

			if ( 'sort' === $type ) {
				$choices = [];

				if ( ! empty( $facet['sort_options'] ) && is_array( $facet['sort_options'] ) ) {
					foreach ( $facet['sort_options'] as $option ) {
						if ( ! empty( $option['name'] ) && ! empty( $option['label'] ) ) {
							$choices[] = [
								'value' => $option['name'],
								'label' => $option['label'],
							];
						}
					}
				}

				$selected = $facets_for_request[ $name ] ?? [];

				$facets[ $name ] = [
					'name'     => $name,
					'label'    => $label,
					'type'     => $type,
					'selected' => $selected,
					'choices'  => $choices,
					'settings' => $facet['settings'] ?? [],
				];

				continue;
			}

			$choices = [];

			// Determine if we should use unfiltered post IDs for this facet
			$use_unfiltered_post_ids = in_array( $type, [ 'dropdown', 'checkboxes' ], true );

			if ( $use_unfiltered_post_ids ) {
				// Check if MLS is selected
				$selected_mls = ! empty( $facets_for_request['mls'] )
					? (array) $facets_for_request['mls']
					: [];

				if ( ! empty( $selected_mls ) && 'mls' !== $name ) {
					$placeholders = implode( ',', array_fill( 0, count( $selected_mls ), '%s' ) );

					$post_ids_for_facet = $wpdb->get_col( $wpdb->prepare( "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = 'mls' AND facet_value IN ($placeholders)
                    ", ...$selected_mls ) );
				} else {
					// No MLS selected - show all MLS posts
					// (and always show all choices for 'mls' facet)
					$post_ids_for_facet = $wpdb->get_col( "
                        SELECT DISTINCT post_id
                        FROM {$wpdb->prefix}facetwp_index
                        WHERE facet_name = 'mls'
                    " );
				}
			} else {
				$post_ids_for_facet = $filtered_post_ids;
			}

			if ( ! empty( $post_ids_for_facet ) ) {
				$placeholders = implode( ',', array_fill( 0, count( $post_ids_for_facet ), '%d' ) );

				$query = "
                    SELECT facet_value, facet_display_value, COUNT(*) AS count
                    FROM {$wpdb->prefix}facetwp_index
                    WHERE facet_name = %s AND post_id IN ($placeholders)
                    GROUP BY facet_value, facet_display_value
                ";

				$params = array_merge( [ $name ], $post_ids_for_facet );

				$results_raw = $wpdb->get_results( $wpdb->prepare( $query, ...$params ), ARRAY_A );

				foreach ( $results_raw as $row ) {
					$choices[] = [
						'value'     => $row['facet_value'],
						'label'     => $row['facet_display_value'],
						'raw'       => $row['facet_display_value'],
						'count'     => (int) $row['count'],
						'depth'     => 0,
						'term_id'   => 0,
						'parent_id' => 0,
					];
				}
			}

			$facets[ $name ] = [
				'name'     => $name,
				'label'    => $label,
				'type'     => $type,
				'selected' => $selected,
				'choices'  => $choices,
				'settings' => $facet['settings'] ?? [],
			];
		}

		$facets = $this->sort_mls_facet( $facets );

		return [
			'results' => $results,
			'facets'  => $facets,
			'pager'   => [
				'total_rows'  => $total_count,
				'total_pages' => ceil( $total_count / $per_page ),
				'page'        => $page,
			],
		];
	}

	private function inject_allowed_property_types_if_none_selected( $facets_for_request ) {
		global $wpdb;

		// Check if user explicitly cleared 'property_type' facet
		if (
			isset( FWP()->facet->facets['property_type'] )
			&& empty( FWP()->facet->facets['property_type']['selected_values'] )
		) {
			return $facets_for_request;
		}

		// Skip if user selected values
		if ( ! empty( $facets_for_request['property_type'] ) ) {
			return $facets_for_request;
		}

		$allowed_types = get_option( 'facetwp_remote_data_only_show_property_types' );
		$excluded_types = get_option( 'facetwp_remote_data_excluded_property_types' );

		// Use allowed list if present
		if ( is_array( $allowed_types ) && ! empty( $allowed_types ) ) {
			$facets_for_request['property_type'] = $allowed_types;

			return $facets_for_request;
		}

		// Otherwise use exclusion list
		if ( is_array( $excluded_types ) && ! empty( $excluded_types ) ) {
			$placeholders = implode( ',', array_fill( 0, count( $excluded_types ), '%s' ) );

			$query = "
                SELECT DISTINCT facet_value
                FROM {$wpdb->prefix}facetwp_index
                WHERE facet_name = 'property_type'
                AND facet_value NOT IN ($placeholders)
            ";

			$allowed = $wpdb->get_col( $wpdb->prepare( $query, ...$excluded_types ) );

			if ( ! empty( $allowed ) ) {
				$facets_for_request['property_type'] = $allowed;
			}
		}

		return $facets_for_request;
	}

    private function get_sort_facet_selection( $class ) {
	    if ( empty( $class ) || empty( $class->facets ) ) {
		    return null;
	    }

	    foreach ( $class->facets as $facet_name => $facet_data ) {
		    if (
			    isset( $facet_data['type'] )
                && 'sort' === $facet_data['type']
                && ! empty( $facet_data['selected_values'][0] )
		    ) {
			    return $facet_data['selected_values'][0];
		    }
	    }

        // Preselected sort option
        $facets_from_options = ( new Facet_Wp_Remote_Data_Handler() )->get_facets_from_options();

        if ( ! empty( $facets_from_options ) ) {
            $sort_facet = array_filter( $facets_from_options, fn ( $facet ) => 'sort' === $facet['type'] );
            $sort_facet = ! empty( $sort_facet ) ? array_shift( $sort_facet ) : [];

            if ( ! empty( $sort_facet ) ) {
                $post_id = $this->get_page_id_from_facet_params( $class->http_params );

                $selected_value = get_post_meta(
                    $post_id,
                    Facet_Wp_Remote_Data_Neighborhood_Page::PREFIX_FACET_WP_REMOTE_DATA_PRESELECTED__FACET . $sort_facet['name'],
                    true
                );

                if ( ! empty( $selected_value ) ) {
                    return $selected_value;
                }
            }
        }

	    // No manual sort selected, fallback to default from settings
	    return get_option( 'facetwp_remote_data_default_sort_option' ) ?: null;
    }

    public function ensure_preselected_facet_choice_is_included( $facets_for_request, $http_params ) {
        $post_id = $this->get_page_id_from_facet_params( $http_params );

        if ( ! empty( $post_id ) ) {
	        $facets = FWP()->helper->get_facets();

	        foreach ( $facets as $facet ) {
		        $facet_name = $facet['name'];

		        $preselected_value = get_post_meta(
                    $post_id,
                    Facet_Wp_Remote_Data_Neighborhood_Page::PREFIX_FACET_WP_REMOTE_DATA_PRESELECTED__FACET . $facet_name,
                    true
                );

		        if ( ! empty( $preselected_value ) && empty( $facets_for_request[ $facet_name ] ) ) {
			        $facets_for_request[ $facet_name ] = $preselected_value;
		        }
	        }
        }

	    // Inject default sort if nothing selected
	    foreach ( $this->get_facets_from_options() as $facet ) {
		    if (
			    ( $facet['type'] ?? '' ) === 'sort'
			    && empty( $facets_for_request[ $facet['name'] ] )
		    ) {
			    $default_sort_value = get_option( 'facetwp_remote_data_default_sort_option' );

			    if ( ! empty( $default_sort_value ) ) {
				    $facets_for_request[ $facet['name'] ] = [ $default_sort_value ];
			    }
		    }
	    }

        return $facets_for_request;
    }

	public function sort_mls_facet( $facets ) {
		if ( ! empty( $facets['mls']['choices'] ) ) {
			$facet_choices = $facets['mls']['choices'];

			$sorted_facets = [];

			$order_with_new_labels = Mls::labels( keysToUpper: true );

			foreach ( $order_with_new_labels as $facet_current_label => $facet_new_label ) {
				$facet_choice = array_merge(
					...array_filter(
						$facet_choices,
						fn ( $facet ) => $facet['label'] === $facet_current_label
					)
				);

				if ( ! empty( $facet_choice ) ) {
					$facet_choice['label'] = $facet_new_label;

					$sorted_facets[] = $facet_choice;
				}
			}

			$facets['mls']['choices'] = $sorted_facets;
		}

		return $facets;
	}

	public function get_remote_site_posts( $post_ids = [], $return_all_posts_data = true, $page = null, $per_page = null, $sort_facet_option = null ) {
		if ( empty( $post_ids ) ) return [];

		$post_ids_string = implode( ',', $post_ids );

		$posts_response = $this->make_api_request(
			'post',
			self::REMOTE_SITE_PROPERTIES_REST_ENDPOINT,
            null,
			[
                'post_ids' => $post_ids_string,
                'return_all_posts_data' => $return_all_posts_data,
                'page' => $page,
                'per_page' => $per_page,
                'sort_facet_option' => $sort_facet_option,
            ],
		);

		if ( is_wp_error( $posts_response ) ) {
			error_log( 'Error fetching posts from remote site: ' . $posts_response->get_error_message() );

            return null;
		}

		$http_code = wp_remote_retrieve_response_code( $posts_response );
        $body_json = wp_remote_retrieve_body( $posts_response );
        $data = json_decode( $body_json, true );

		if ( $http_code < 200 || $http_code >= 300 ) {
			$message = $data['message'] ?? 'Unknown error';

			error_log( "Error fetching posts from remote site - HTTP $http_code: $message" );

			return null;
		}

        if ( ! empty( $data ) ) {
	        $data = array_map(
                function ( $post_data ) {
                    $post_data['link'] = $this->create_property_link( $post_data['property_id'], $post_data['address'] );

                    return $post_data;
                },
		        $data
            );
        }

		return $data;
	}

    private static function get_listings_data( $remote_site_rest_endpoint, $transient_key, $posts_per_page = 12, $paged = 1, $extra_payload = [] ) {
	    $skip_cache = apply_filters( 'facetwp_remote_data_skip_cache', false );

	    $posts_data = ! $skip_cache
		    ? Facet_Wp_Remote_Data_Cache::get( $transient_key )
		    : false;

	    if ( false === $posts_data ) {
		    $payload = array_merge( [
			    'posts_per_page' => $posts_per_page,
			    'page' => $paged,
			    'site_owner_office_name' => trim( get_option( 'facetwp_remote_data_site_owner_office_name', '' ) ),
			    'office_listings_within_weeks' => trim( get_option( 'facetwp_remote_data_latest_listings_within_weeks', '' ) ),
		    ], $extra_payload );

		    $posts_response = ( new self )->make_api_request(
			    'post',
			    $remote_site_rest_endpoint,
			    null,
			    $payload
		    );

		    if ( is_wp_error( $posts_response ) ) {
			    error_log( 'Error fetching posts from remote site: ' . $posts_response->get_error_message() );

                return null;
		    }

		    $code = wp_remote_retrieve_response_code( $posts_response );
		    $posts_body = wp_remote_retrieve_body( $posts_response );
		    $posts_data = json_decode( $posts_body, true );

		    if ( $code < 200 || $code >= 300 ) {
			    $message = $posts_data['message'] ?? 'Unknown error';

			    error_log( "Error fetching posts from remote site - HTTP $code: $message" );

			    return null;
		    }

		    if ( in_array( $code, [204, 205], true ) ) {
			    return [];
		    }

            if ( ! empty( $posts_data ) ) {
	            $posts_data = array_map(
                    function ( $post_data ) {
                        $post_data['link'] = ( new self )->create_property_link( $post_data['property_id'], $post_data['address'] );

                        return $post_data;
                    },
		            $posts_data
                );

                Facet_Wp_Remote_Data_Cache::set( $transient_key, $posts_data );
            }
	    }

	    return $posts_data ?: null;
    }

    public static function get_latest_listings( $posts_per_page = 12, $paged = 1 ) {
	    $allowed_types  = get_option( 'facetwp_remote_data_only_show_property_types', [] );
	    $excluded_types = get_option( 'facetwp_remote_data_excluded_property_types', [] );

	    return self::get_listings_data(
            self::REMOTE_SITE_LATEST_PROPERTIES_REST_ENDPOINT,
            Facet_Wp_Remote_Data_Cache::remote_site_data_latest_listings( $posts_per_page, $paged ),
            $posts_per_page,
            $paged,
            [
				'allowed_property_types' => $allowed_types,
				'excluded_property_types' => $excluded_types,
			]
        );
    }

	public static function get_current_listings( $posts_per_page = 12, $paged = 1 ) {
		$allowed_types  = get_option( 'facetwp_remote_data_only_show_property_types', [] );
		$excluded_types = get_option( 'facetwp_remote_data_excluded_property_types', [] );

		return self::get_listings_data(
			self::REMOTE_SITE_CURRENT_PROPERTIES_REST_ENDPOINT,
			Facet_Wp_Remote_Data_Cache::remote_site_data_current_listings( $posts_per_page, $paged ),
			$posts_per_page,
			$paged,
            [
				'allowed_property_types' => $allowed_types,
				'excluded_property_types' => $excluded_types,
			]
		);
	}

	private function create_property_link( $property_id, $property_address ) {
		$property_url_path = $property_id
		                     . '-'
		                     . preg_replace( '/[^a-zA-Z0-9-]+/', '-', sanitize_title( $property_address ) );

		$property_link = trailingslashit( home_url( "/property/{$property_url_path}" ) );

		return $property_link;
	}

	public function get_facets_from_options() {
		$option = get_option( 'facetwp_settings' );

		if ( ! empty( $option ) ) {
			$settings = ( false !== $option ) ? json_decode( $option, true ) : [];
		}

		return $settings['facets'] ?? [];
	}

	public function get_property_remote_site_data( $property_id ) {
		$post_response = $this->make_api_request(
			'get',
			self::REMOTE_SITE_PROPERTY_REST_ENDPOINT. '/' . $property_id,
		);

		if ( is_wp_error( $post_response ) ) {
			error_log( 'Error fetching post from remote site: ' . $post_response->get_error_message() );

            return null;
		}

		$code = wp_remote_retrieve_response_code( $post_response );
		$post_body = wp_remote_retrieve_body( $post_response );
		$data = json_decode( $post_body, true );

		if ( $code < 200 || $code >= 300 ) {
			$message = $data['message'] ?? 'Unknown error';

			error_log( "Error fetching post from remote site - HTTP $code: $message" );

			return null;
		}

		$data = $this->maybe_unserialize_recursive( $data );

		return $data;
	}

	protected function maybe_unserialize_recursive( $data ) {
		foreach ( $data as $key => $value ) {
			if ( is_array( $value ) ) {
				$data[ $key ] = $this->maybe_unserialize_recursive( $value );
			} elseif ( is_string( $value ) ) {
				$data[ $key ] = maybe_unserialize( $value );
			}
		}

		return $data;
	}

	public function make_api_request( $type, $api_endpoint, $query_vars = null, $body = null ) {
		$remote_site_url = get_option( 'facetwp_remote_data_remote_site_url' );

		$request_url = $remote_site_url . $api_endpoint;

		if ( empty( $remote_site_url ) ) {
			return new WP_Error( 'no_remote_url', 'Remote site URL is not set.', ['status' => 400] );
		}

		$auth_header = Facet_Wp_Remote_Data_Utils::get_auth_header();

		if ( empty( $auth_header ) ) {
			return new WP_Error( 'no_credentials', 'Remote site credentials are not set.', ['status' => 403] );
		}

		if ( $query_vars ) {
			$request_url = add_query_arg( $query_vars, $request_url );
		}

		$request_data = [
			'headers' => [
				'Authorization' => 'Basic ' . $auth_header,
				'Subsite-Url' => get_bloginfo( 'url' ),
				'Content-Type' => 'application/json'
			],
			'timeout' => 180,
			'sslverify' => Facet_Wp_Remote_Data_Utils::should_ssl_verify(),
		];

		if ( $body ) {
			$request_data['body'] = json_encode( $body );
		}

		$request_function = 'wp_remote_' . $type;

		if ( function_exists( $request_function ) ) {
			$response = $request_function( $request_url, $request_data );
		}

		return $response ?? null;
	}

	public function get_template_path( $page_template, $post_id = null ) {
		// Check if a post-specific template is set
		if ( $post_id ) {
			$custom_template_name = get_post_meta( $post_id, 'sw_facetwp_page_listing_template', true );

			if ( $custom_template_name ) {
				$custom_template_file = locate_template( "facet-wp-remote-data/{$custom_template_name}.php" );

				if ( ! empty( $custom_template_file ) ) {
					return $custom_template_file;
				}
			}
		}

		// Allow themes to override the template by checking in the theme folder.
		$theme_template = locate_template( "facet-wp-remote-data/facet-wp-remote-data-{$page_template}.php" );

		$default_template = dirname( plugin_dir_path( __FILE__ ) ) . "/templates/facet-wp-remote-data-{$page_template}.php";

		return $theme_template ?: $default_template;
	}

	private function get_page_id_from_facet_params( $http_params ) {
		global $post;

		if ( $post ) {
			return $post->ID;
		}

		if ( ! empty( $http_params['uri'] ) ) {
			$uri = ltrim( $http_params['uri'], '/' );

			// Try regular page lookup
			$page = get_page_by_path( $uri );

			if ( $page instanceof WP_Post ) {
				return $page->ID;
			}

			// Custom post type lookup
			$segments = explode( '/', $uri );

			if ( ! empty( $segments ) ) {
				// Rebuild the path, excluding the path base
				array_shift( $segments );

				$path = implode( '/', $segments );

				$page = get_page_by_path( $path, OBJECT, 'community' );

				if ( $page instanceof WP_Post ) {
					return $page->ID;
				}
			}
		}

		if ( ! empty( $_SERVER['HTTP_REFERER'] ) ) {
			$page_id = url_to_postid( $_SERVER['HTTP_REFERER'] );

			if ( $page_id ) return $page_id;
		}

		return get_option( 'page_on_front' );
	}

	public function should_use_main_site_facet_wp_data( $current_page_id = null ) {
		$selected_pages = get_option( 'facetwp_remote_data_selected_pages', [] );
		$selected_cpts = get_option( 'facetwp_remote_data_selected_cpts', [] );

		$current_page_id = $current_page_id ?: ( is_singular() ? get_queried_object_id() : null );

        if ( ! $current_page_id ) return false;

		if ( in_array( $current_page_id, $selected_pages ) ) return true;

        $current_page_post_type = get_post_type( $current_page_id );

        if ( ! $current_page_post_type ) return false;

        if ( in_array( $current_page_post_type, $selected_cpts ) ) return true;

        return false;
	}

	public function facetwp_gmaps_api_key( $api_key ) {
		return ! empty( get_option( 'facetwp_remote_data_google_api_key' ) )
			? get_option( 'facetwp_remote_data_google_api_key ')
			: $api_key;
	}

	public function facetwp_scripts() {
		?>
		<script>
            (function($) {
                document.addEventListener('facetwp-loaded', function() {
                    if ('undefined' === typeof FWP_MAP) {
                        return;
                    }

                    var filterButton = $(".facetwp-map-filtering");

                    if (!filterButton.hasClass('enabled') && 'undefined' == typeof FWP_MAP.enableFiltering) {
                        filterButton.text(FWP_JSON['map']['resetText']);
                        FWP_MAP.is_filtering = true;
                        filterButton.addClass('enabled');
                        FWP_MAP.enableFiltering = true;
                    }
                });

                document.addEventListener('facetwp-loaded', function() {
                    if (! FWP.loaded) {
                        FWP.hooks.addFilter('facetwp/ajax_settings', function(settings) {
                            settings.headers = { 'X-WP-Nonce': FWP_JSON.nonce };
                            return settings;
                        });
                    }
                });

                FWP.hooks.addAction('facetwp/reset', function() {
                    $.each(FWP.facet_type, function(type, name) {
                        if ('map' === type) {
                            var $button = $('.facetwp-map-filtering');
                            $button.text(FWP_JSON['map']['filterText']);
                            FWP_MAP.is_filtering = false;
                            $button.toggleClass('enabled');
                        }
                    });
                });
            })(fUtil);
		</script>
		<?php
	}

    private function force_update_mls_search_landing_pages_cache() {
	    $facet_with_choices = ( new Facet_Wp_Remote_Data_Neighborhood_Page )->get_facets_with_choices();

	    $mls_facet = ! empty( $facet_with_choices )
		    ? array_filter(
			    $facet_with_choices,
			    fn ( $facet ) => $facet['name'] === 'mls'
		    )
		    : [];

	    if ( ! empty( $mls_facet ) ) {
		    $mls_facet = current( $mls_facet );

		    $facets_from_option = $this->get_facets_from_options();

		    // Allowed property types
		    $allowed_property_types = get_option( 'facetwp_remote_data_only_show_property_types' );

            // Default sort option
		    $default_sort_value = get_option( 'facetwp_remote_data_default_sort_option' );

		    if ( ! empty( $facets_from_option ) ) {
			    foreach ( $mls_facet['choices'] as $choice ) {
				    $value = $choice['value'];

				    $facets_for_request = [];

				    foreach ( $facets_from_option as $facet ) {
					    $facets_for_request[ $facet['name'] ] = 'mls' === $facet['name']
						    ? $value
						    : [];
				    }

				    $facetwp_remote_site_filtered_data = $this->get_remote_site_facetwp_filtered_data( null, null, $facets_for_request );

				    $posts_data = $this->get_remote_site_posts( $facetwp_remote_site_filtered_data['results'] ?? [] );

				    $data_for_cache = [
					    'facet_data' => $facetwp_remote_site_filtered_data,
					    'posts' => $posts_data
				    ];

				    $class = new stdClass();
				    $class->http_params = [
					    'get' => [],
					    'uri' => 'listings',
					    'url_vars' => [],
				    ];

				    $class->http_params['get']['_mls'] = $value;
				    $class->http_params['url_vars']['mls'][] = $value;

				    if ( ! empty( $allowed_property_types ) ) {
					    $class->http_params['get']['_property_type'] = implode( ',', $allowed_property_types );

					    foreach ( $allowed_property_types as $allowed_property_type ) {
						    $class->http_params['url_vars']['property_type'][] = $allowed_property_type;
					    }
				    }

                    // Listing data
				    $transient_key = Facet_Wp_Remote_Data_Cache::remote_site_facet_search_data( $class->http_params );

				    Facet_Wp_Remote_Data_Cache::set( $transient_key, $data_for_cache );

                    // Map data
				    $all_mls_locations = $this->get_remote_data_all_locations( $value );

				    $map_transient_key = Facet_Wp_Remote_Data_Cache::all_locations_for_mls( $value );

				    Facet_Wp_Remote_Data_Cache::set( $map_transient_key, $all_mls_locations );

                    if ( ! empty( $default_sort_value ) ) {
	                    $get = $class->http_params['get'];
	                    $pairs = [];
	                    foreach ( $get as $k => $v ) {
		                    $pairs[] = [ $k => $v ];
	                    }

	                    array_splice( $pairs, 1, 0, [ [ '_sort_' => $default_sort_value ] ] );

	                    $updated_get = [];
	                    foreach ( $pairs as $pair ) {
		                    foreach ( $pair as $k => $v ) {
			                    $updated_get[ $k ] = $v;
		                    }
	                    }

	                    $class->http_params['get'] = $updated_get;

                        $class->http_params['url_vars']['sort_'][] = $default_sort_value;

	                    // Listing data
	                    $transient_key = Facet_Wp_Remote_Data_Cache::remote_site_facet_search_data( $class->http_params );

	                    Facet_Wp_Remote_Data_Cache::set( $transient_key, $data_for_cache );

	                    // Map data
	                    $all_mls_locations = $this->get_remote_data_all_locations( $value );

	                    $map_transient_key = Facet_Wp_Remote_Data_Cache::all_locations_for_mls( $value );

	                    Facet_Wp_Remote_Data_Cache::set( $map_transient_key, $all_mls_locations );
                    }
			    }
		    }
	    }
    }

    public function set_index_table_background_job( $total_batches ) {
	    for ( $batch = 1; $batch <= $total_batches; $batch++ ) {
		    $this->background_process->push_to_queue(
			    [
				    'batch' => $batch,
				    'tries' => 0,
			    ]
		    );
	    }

	    $this->background_process->save();
    }

}