<?php

class Facet_Wp_Remote_Data_Handler {

	private static $facetwp_remote_data = null;

	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 static $posts_per_page = 12;

	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_name = $args['facet']['name'];

		$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_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_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-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 );
		$body = json_decode( $body_json, true );

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

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

			exit();
		}

		wp_send_json( $body );

		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;

        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( $remote_data['facet_data']['facets']['map']['all_locations'] ?? [] ),
        ];
    }

    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
		    ? get_transient( $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['property_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/([0-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() {
		if ( '1' === get_query_var( 'sw_remote_data_property_page' ) ) {
			$property_id = (int) 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
				? get_transient( $transient_key )
				: false;

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

				if ( ! $post_remote_data ) wp_die( 'Invalid Property ID' );

				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();
		}
	}

	private function get_facetwp_remote_data( $class = null ) {
		if (
			is_null( self::$facetwp_remote_data )
			&& ! is_null( $class )
		) {
			$query_args = ! empty( $class->http_params )
				? $class->http_params
				: ( ! empty( $class->template['name'] )
					? $class->template['name']
					: 'facetwp_remote_data_default'
				);

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

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

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

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

				$posts_data = $this->get_remote_site_posts( $facetwp_remote_site_filtered_data );

				$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;
	}

	public function get_remote_site_facetwp_filtered_data( $class = null, $posts_per_page = null ) {
		$remote_site_url = Facet_Wp_Remote_Data_Utils::get_remote_site_url();

		$auth_header = Facet_Wp_Remote_Data_Utils::get_auth_header();

        if ( empty( $remote_site_url ) || empty( $auth_header ) ) {
            return null;
        }

		$facets_from_option = $this->get_facets_from_options();

		$facets_for_request = [];

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

		$request_data = [
			'data' => [
				'facets' => $facets_for_request,
				'query_args' => [
					'post_type'      => self::REMOTE_SITE_PROPERTY_POST_TYPE_SLUG,
					'posts_per_page' => apply_filters( 'facet_wp_remote_data_posts_per_page', $posts_per_page ?? self::$posts_per_page ),
					'paged'          => $_GET['_paged'] ?? 1
				]
			]
		];

		$response = $this->make_api_request(
			'post',
			self::FACETWP_API_ENDPOINT,
			null,
			$request_data,
		);

		if ( is_wp_error( $response ) ) {
			error_log( 'Fetching FacetWP data from remote site error: ' . $response->get_error_message() );
		} else {
			$body = wp_remote_retrieve_body( $response );
			$data = json_decode( $body, true );
		}

		return $data ?? null;
	}

	private function get_remote_site_posts( $facetwp_remote_site_filtered_data ) {
		$post_ids = $facetwp_remote_site_filtered_data['results'] ?? [];

		if ( empty( $post_ids ) ) return null;

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

		$posts_response = $this->make_api_request(
			'get',
			self::REMOTE_SITE_PROPERTIES_REST_ENDPOINT,
			[ 'post_ids'  => $post_ids_string ],
		);

		if ( is_wp_error( $posts_response ) ) {
			error_log( 'Error fetching posts from remote site: ' . $posts_response->get_error_message() );
		} else {
			$posts_body = wp_remote_retrieve_body( $posts_response );
			$posts_data = json_decode( $posts_body, true );

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

					return $post_data;
				},
				$posts_data
			);
		}

		return $posts_data ?? null;
	}

	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;
	}

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

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

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

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

		if ( is_wp_error( $post_response ) ) {
			error_log( 'Error fetching post from remote site: ' . $post_response->get_error_message() );
		} else {
			$post_body = wp_remote_retrieve_body( $post_response );
			$post_data = json_decode( $post_body, true );
		}

		return $post_data ?? null;
	}

	private 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' => 30,
			'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;
	}

	private 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 ( ! empty( $http_params['uri'] ) ) {
			return get_page_by_path( $http_params['uri'] )?->ID;
		}

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

		return get_option( 'page_on_front' );
	}

	private 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;
                    }
                });

                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
	}

}