<?php

class Facet_Wp_Remote_Data_Acf_Helper {

	// @see web/wp-content/plugins/advanced-custom-fields-pro/includes/fields/class-acf-field-post_object.php
	public function forward_ajax_acf_post_object_query_to_main_site() {
		$nonce             = acf_request_arg( 'nonce', '' );
		$key               = acf_request_arg( 'field_key', '' );
		$conditional_logic = (bool) acf_request_arg( 'conditional_logic', false );

		if ( $conditional_logic ) {
			if ( ! acf_current_user_can_admin() ) {
				die();
			}

			// Use the standard ACF admin nonce.
			$nonce = '';
			$key   = '';
		}

		if ( ! acf_verify_ajax( $nonce, $key, ! $conditional_logic ) ) {
			die();
		}

		$field = get_field_object( $key );

		if ( 'post_object' === $field['type'] ) {
			$post_type = current( $field['post_type'] );

			if ( 'property' === $post_type ) {
				$response = ( new Facet_Wp_Remote_Data_Handler )->make_api_request(
					'post',
					'/wp-json/sw-facetwp/v1/forward-acf-post-object-query-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();
				}

				wp_send_json(
					[
						'limit' => 20,
						'more' => false,
						'results' => $data,
					]
				);

				exit();
			}
		}
	}

	public static function force_update_properties_in_acf_fields_cache() {
		if ( defined( 'WP_CLI' ) && WP_CLI ) {
			WP_CLI::log( 'Facet_Wp_Remote_Data_Acf_Helper::force_update_properties_in_acf_fields_cache()' );
		}

		$property_ids_from_blocks = self::get_acf_fields_from_blocks();
		$property_ids_from_pages_and_posts = self::get_acf_fields_from_pages_and_posts();

		add_filter( 'facetwp_remote_data_skip_cache', '__return_true' );

		if ( ! empty( $property_ids_from_blocks ) ) {
			foreach ( $property_ids_from_blocks as $key => $property_ids ) {
				sw_get_remote_site_properties( $property_ids );
			}
		}

		if ( ! empty( $property_ids_from_pages_and_posts ) ) {
			foreach ( $property_ids_from_pages_and_posts as $key => $property_ids ) {
				sw_get_remote_site_properties( $property_ids );
			}
		}
	}

	public function posts_pre_query_for_property_cpt( $posts, $query ) {
		if (
			isset( $query->query_vars['post_type'] )
			&& (
				( is_array( $query->query_vars['post_type'] ) && 'property' === current( $query->query_vars['post_type'] ) )
				|| ( is_string( $query->query_vars['post_type'] ) && 'property' === $query->query_vars['post_type'] )
			)
			&& ! empty( $query->query_vars['post__in'] )
		) {
			$post_ids = $query->query_vars['post__in'];

			$transient_key = Facet_Wp_Remote_Data_Cache::property_posts_remote_site_data( $post_ids );

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

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

			if ( false === $properties ) {
				$properties = ( new Facet_Wp_Remote_Data_Handler() )->get_remote_site_posts( $post_ids );
			}

			if ( is_wp_error( $properties ) ) {
				return $posts;
			}

			if ( ! empty( $properties ) ) {
				Facet_Wp_Remote_Data_Cache::set( $transient_key, $properties );

				$posts = [];

				foreach ( $properties as $property ) {
					$post = new stdClass();
					$post->ID = $property['property_id'];
					$post->post_title = $property['address'];
					$post->post_type = 'property';
					$post->post_status = 'publish';

					$posts[] = $post;
				}
			}
		}

		return $posts;
	}

	public static function get_acf_fields_from_blocks() {
		$post_types = get_post_types(
			[
				'public'   => true,
				'show_ui'  => true,
			]
		);

		$post_types[] = 'post';
		$post_types[] = 'page';

		$args = [
			'post_type'        => array_unique( $post_types ),
			'post_status'      => 'any',
			'posts_per_page'   => -1,
			'no_found_rows'    => true,
			'fields'           => 'ids',
		];

		$query = new WP_Query( $args );
		$all_blocks_property_ids = [];

		if ( $query->have_posts() ) {
			foreach ( $query->posts as $post_id ) {
				$post = get_post( $post_id );
				$blocks = parse_blocks( $post->post_content );

				foreach ( $blocks as $block ) {
					if ( empty( $block['blockName'] ) || strpos( $block['blockName'], 'acf/' ) !== 0 ) {
						continue;
					}

					$data = $block['attrs']['data'] ?? [];
					$block_property_ids = [];

					foreach ( $data as $key => $value ) {
						if ( str_starts_with( $key, '_' ) ) {
							continue;
						}

						$field_key_meta_key = '_' . $key;

						if ( empty( $data[ $field_key_meta_key ] ) || ! str_starts_with( $data[ $field_key_meta_key ], 'field_' ) ) {
							continue;
						}

						$field_key = $data[ $field_key_meta_key ];

						$field_post = get_posts([
							'name'        => $field_key,
							'post_type'   => 'acf-field',
							'post_status' => 'publish',
							'numberposts' => 1,
						])[0] ?? null;

						if ( ! $field_post ) {
							continue;
						}

						$field_config = maybe_unserialize( $field_post->post_content );

						if (
							isset( $field_config['type'], $field_config['post_type'] )
							&& $field_config['type'] === 'post_object'
							&& is_array( $field_config['post_type'] )
							&& in_array( 'property', $field_config['post_type'], true )
						) {
							if ( is_numeric( $value ) ) {
								$block_property_ids[] = (int) $value;
							} elseif ( is_array( $value ) ) {
								foreach ( $value as $id ) {
									if ( is_numeric( $id ) ) {
										$block_property_ids[] = (int) $id;
									}
								}
							}
						}
					}

					if ( ! empty( $block_property_ids ) ) {
						$all_blocks_property_ids[] = array_unique( $block_property_ids );
					}
				}
			}
		}

		return $all_blocks_property_ids;
	}

	public static function get_acf_fields_from_pages_and_posts() {
		global $wpdb;

		$post_types = get_post_types(
			[
				'public'   => true,
				'show_ui'  => true,
			]
		);

		$post_types[] = 'post';
		$post_types[] = 'page';

		$post_types   = array_unique( $post_types );

		$post_type_placeholders = implode( ',', array_fill( 0, count( $post_types ), '%s' ) );

		$acf_fields = $wpdb->get_results(
			"SELECT post_name, post_content
			FROM {$wpdb->posts}
			WHERE post_type = 'acf-field'
				AND post_status = 'publish'"
		);

		$target_field_keys = [];

		foreach ( $acf_fields as $acf_field ) {
			$content = maybe_unserialize( $acf_field->post_content );

			if (
				is_array( $content )
				&& isset( $content['type'], $content['post_type'] )
				&& $content['type'] === 'post_object'
				&& is_array( $content['post_type'] )
				&& in_array( 'property', $content['post_type'], true )
			) {
				$target_field_keys[] = $acf_field->post_name;
			}
		}

		if ( empty( $target_field_keys ) ) {
			return [];
		}

		$field_key_placeholders = implode( ',', array_fill( 0, count( $target_field_keys ), '%s' ) );

		$field_key_meta = $wpdb->get_results(
			$wpdb->prepare(
				"SELECT pm.post_id, pm.meta_key, pm.meta_value
				FROM {$wpdb->postmeta} pm
				INNER JOIN {$wpdb->posts} p ON p.ID = pm.post_id
				WHERE pm.meta_key LIKE '\\_%'
					AND pm.meta_value IN ($field_key_placeholders)
					AND p.post_type IN ($post_type_placeholders)
					AND p.post_status IN ('publish', 'private')",
				[
					...$target_field_keys,
					...$post_types
				]
			)
		);

		if ( empty( $field_key_meta ) ) {
			return [];
		}

		$results = [];

		foreach ( $field_key_meta as $meta ) {
			$post_id = (int) $meta->post_id;
			$value_key = ltrim( $meta->meta_key, '_' );

			$value_row = $wpdb->get_var(
				$wpdb->prepare(
					"SELECT meta_value FROM {$wpdb->postmeta}
					WHERE post_id = %d AND meta_key = %s",
					$post_id,
					$value_key
				)
			);

			if ( $value_row === null ) {
				continue;
			}

			$value = maybe_unserialize( $value_row );

			if ( is_numeric( $value ) ) {
				$results[ $post_id ][] = (int) $value;
			} elseif ( is_array( $value ) ) {
				foreach ( $value as $id ) {
					if ( is_numeric( $id ) ) {
						$results[ $post_id ][] = (int) $id;
					}
				}
			}
		}

		foreach ( $results as $post_id => $ids ) {
			$results[ $post_id ] = array_unique( array_filter( $ids ) );
		}

		return $results;
	}
}