<?php

namespace WeDevs\AppBridge\Integrations\WooCommerce\Bookings;

use WC_Booking_Cart_Manager;
use WeDevs\AppBridge\Core\Contracts\Hookable;
use WP_REST_Request;

class BookingAddToCartItem implements Hookable {
	public function register_hooks(): void {
		add_filter(
            'woocommerce_store_api_add_to_cart_data',
            [ $this, 'booking_add_to_cart_data' ], 10, 2
        );
	}

	/**
	 * Add booking-related data from the Store API request to the global $_POST array.
	 * This ensures compatibility with WooCommerce Bookings, allowing it to process the
	 * booking details correctly when the item is added to the cart.
	 *
	 * @param $add_to_cart_data
	 * @param WP_REST_Request $request
	 *
	 * @phpcs:disabled WordPress.Security.NonceVerification.Recommended
	 *
	 * @return mixed
	 */
	public function booking_add_to_cart_data( $add_to_cart_data, WP_REST_Request $request ) {
		// check product is booking type
		$product_id = $request->get_param( 'id' );
		$product    = wc_get_product( $product_id );

		if ( ! $product || 'booking' !== $product->get_type() ) {
			return $add_to_cart_data;
		}

		if ( class_exists( 'WC_Booking_Cart_Manager' ) === false ) {
			return $add_to_cart_data;
		}

        /**
         * Remove the default WooCommerce Bookings validation filter to avoid conflicts
         * with Store API request handling.
         *
         * In a typical AJAX (frontend) request cycle, WooCommerce triggers the
         * 'woocommerce_add_to_cart_validation' filter before running the add-to-cart
         * process. However, in the Store API request cycle, the order is reversed:
         * the add-to-cart process is triggered first, and validation occurs afterward.
         *
         * This difference can cause WC_Booking_Cart_Manager::validate_add_cart_item()
         * to misinterpret modified $_POST data coming from the Store API request,
         * resulting in incorrect validation errors.
         *
         * To ensure compatibility with the Store API booking flow, this method removes
         * the validation filter temporarily. Additionally, WooCommerce has deprecated
         * this filter in newer versions, making this step both necessary and forward-compatible.
         *
         * @see https://github.com/woocommerce/woocommerce/blob/474a5d2e02f2f256f472b4d43675e93e6d8ea9cd/plugins/woocommerce/src/StoreApi/Utilities/CartController.php#L326
         */
		$this->remove_class_filter( 'woocommerce_add_to_cart_validation', WC_Booking_Cart_Manager::class, 'validate_add_cart_item' );

		$_POST = $request->get_param( 'cart_item_data' ) ? array_merge( $_POST, $request->get_param( 'cart_item_data' ) ) : $_POST; // phpcs:ignore

		return $add_to_cart_data;
	}

	/**
	 * Remove a class method from a WordPress filter hook.
	 *
	 * @param $hook
	 * @param $class_name
	 * @param $method_name
	 * @param $priority
	 *
	 * @return void
	 */
	protected function remove_class_filter( $hook, $class_name, $method_name, $priority = 10 ) {
		global $wp_filter;

		if ( empty( $wp_filter[ $hook ]->callbacks[ $priority ] ) ) {
			return;
		}

		foreach ( $wp_filter[ $hook ]->callbacks[ $priority ] as $id => $callback ) {
			if (
            is_array( $callback['function'] ) &&
            is_object( $callback['function'][0] ) &&
            get_class( $callback['function'][0] ) === $class_name &&
            $callback['function'][1] === $method_name
			) {
				unset( $wp_filter[ $hook ]->callbacks[ $priority ][ $id ] );
			}
		}
	}
}
