<?php
/**
 * Cart page recommendations.
 *
 * @package PRECO
 */

namespace PRECO\Includes\Frontend\Pages;

use PRECO\Includes\Frontend\Core\PageRecommendationsBase;

defined( 'ABSPATH' ) || exit;

/**
 * Cart page recommendations.
 */
class CartPageRecommendations extends PageRecommendationsBase {

	/**
	 * Page key in option structure.
	 *
	 * @return string
	 */
	protected function page_key() {
		return 'cart';
	}

	/**
	 * Is the current request the relevant page?
	 *
	 * @return bool
	 */
	protected function is_active_page() {
		return function_exists( 'is_cart' ) && \is_cart();
	}

	/**
	 * Map of location key => hook definition.
	 *
	 * @return array
	 */
	protected function locations() {
		return array(
			'before-cart'       => array(
				'hook'          => 'woocommerce_before_cart',
				'priority'      => 10,
				'accepted_args' => 0,
			),
			'after-cart'        => array(
				'hook'          => 'woocommerce_after_cart',
				'priority'      => 10,
				'accepted_args' => 0,
			),
			'after-cart-totals' => array(
				'hook'          => 'woocommerce_after_cart_totals',
				'priority'      => 10,
				'accepted_args' => 0,
			),
		);
	}

	/**
	 * Register hooks for both classic and block-based cart.
	 *
	 * Classic cart: uses woocommerce_before_cart / woocommerce_after_cart actions.
	 * Block cart:   uses the render_block_woocommerce/cart filter to prepend/append HTML.
	 *
	 * @return void
	 */
	public function register_hooks() {
		if ( ! $this->is_active_page() ) {
			return;
		}
		if ( ! $this->is_page_enabled_for_request() ) {
			return;
		}

		// Classic cart hooks (shortcode-based cart page).
		foreach ( $this->locations() as $location_key => $def ) {
			$hook          = isset( $def['hook'] ) ? (string) $def['hook'] : '';
			$priority      = isset( $def['priority'] ) ? (int) $def['priority'] : 10;
			$accepted_args = isset( $def['accepted_args'] ) ? (int) $def['accepted_args'] : 0;
			if ( ! $hook ) {
				continue;
			}
			add_action(
				$hook,
				function ( ...$args ) use ( $location_key ) {
					$this->render_location( $location_key, $args );
				},
				$priority,
				max( 0, $accepted_args )
			);
		}

		// Block cart: inject via render_block filter on the woocommerce/cart block.
		add_filter(
			'render_block_woocommerce/cart',
			function ( $block_content ) {
				ob_start();
				$this->render_location( 'before-cart', array() );
				$before = ob_get_clean();

				ob_start();
				$this->render_location( 'after-cart', array() );
				$after = ob_get_clean();

				return $before . $block_content . $after;
			},
			10,
			1
		);

		$self = $this;
		// Block cart: inject via render_block filter on the woocommerce/cart block.
		add_filter(
			'render_block_woocommerce/proceed-to-checkout-block',
			function ( $block_content ) use ( $self ) {
				ob_start();
				$self->render_location( 'after-cart-totals', array() );
				$after = ob_get_clean();

				return $block_content . $after;
			},
			10,
			1
		);
	}

	/**
	 * Build context for rule evaluation.
	 *
	 * @param string $location_key Location key.
	 * @param array  $hook_args Hook args.
	 * @return array
	 */
	protected function build_context( $location_key, $hook_args ) {
		$exclude_ids = array();
		if ( function_exists( 'WC' ) && \WC() && \WC()->cart && method_exists( \WC()->cart, 'get_cart' ) ) {
			foreach ( \WC()->cart->get_cart() as $item ) {
				if ( isset( $item['product_id'] ) ) {
					$exclude_ids[] = absint( $item['product_id'] );
				}
			}
		}

		return array(
			'page'         => $this->page_key(),
			'location_key' => (string) $location_key,
			'exclude_ids'  => array_values( array_unique( array_filter( $exclude_ids ) ) ),
		);
	}
}
