<?php
/**
 * Shop archive (category/tag) recommendations.
 *
 * @package PRECO
 */

namespace PRECO\Includes\Frontend\Pages;

use PRECO\Includes\Frontend\Core\PageRecommendationsBase;

defined( 'ABSPATH' ) || exit;

/**
 * Shop archive (category/tag) recommendations.
 */
class ShopArchiveRecommendations extends PageRecommendationsBase {

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

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

	/**
	 * Map of location key => hook definition.
	 *
	 * @return array
	 */
	protected function locations() {
		return array(
			'before-product-loop' => array(
				'hook'          => 'woocommerce_before_shop_loop',
				'priority'      => 5,
				'accepted_args' => 0,
			),
			'after-product-loop'  => array(
				'hook'          => 'woocommerce_after_shop_loop',
				'priority'      => 50,
				'accepted_args' => 0,
			),
			'no-results'          => array(
				'hook'          => 'woocommerce_no_products_found',
				'priority'      => 10,
				'accepted_args' => 0,
			),
		);
	}

	/**
	 * Register hooks for both classic and block-based shop archive.
	 *
	 * Classic archive: woocommerce_before/after_shop_loop actions.
	 * Block archive:   render_block_woocommerce/product-collection filter.
	 *                  Only fires once (the first product-collection block = the main loop).
	 *
	 * @return void
	 */
	public function register_hooks() {
		if ( ! $this->is_active_page() ) {
			return;
		}
		if ( ! $this->config->is_page_enabled( $this->page_key() ) ) {
			return;
		}

		// Classic template hooks.
		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 archive: wrap the first woocommerce/product-collection block only.
		$injected = false;
		add_filter(
			'render_block_woocommerce/product-collection',
			function ( $block_content ) use ( &$injected ) {
				if ( $injected ) {
					return $block_content;
				}
				$injected = true;

				ob_start();
				$this->render_location( 'before-product-loop', array() );
				$before = ob_get_clean();

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

				return $before . $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 ) {
		$term_slug = '';
		$taxonomy  = '';

		$qo = \get_queried_object();
		if ( $qo && isset( $qo->taxonomy, $qo->slug ) && is_string( $qo->taxonomy ) && is_string( $qo->slug ) ) {
			if ( in_array( $qo->taxonomy, array( 'product_cat', 'product_tag' ), true ) ) {
				$taxonomy  = (string) $qo->taxonomy;
				$term_slug = (string) $qo->slug;
			}
		}

		return array(
			'page'                  => $this->page_key(),
			'location_key'          => (string) $location_key,
			'queried_term_taxonomy' => (string) $taxonomy,
			'queried_term_slug'     => (string) $term_slug,
		);
	}
}
