<?php
/**
 * WooCommerce Product Stock Level condition
 *
 * @link       https://personalizewp.com/
 * @since      3.2.0 Merged into PWP
 * @since      3.0.0
 *
 * @package    PersonalizeWP
 * @subpackage PersonalizeWP/Rule_Conditions/WooCommerce
 */

namespace PersonalizeWP\Rule_Conditions\WooCommerce;

use PersonalizeWP\Rule_Conditions\RuleCondition;
use PersonalizeWP\Rule_Conditions\Dependency\Woocommerce;

defined( 'ABSPATH' ) || exit; // Exit if accessed directly.

/**
 * Checks the stock status of the current product being viewed
 */
class Product_Stock_Level extends RuleCondition {

	/**
	 * Condition identifier
	 *
	 * @var string
	 */
	public string $identifier = 'woocommerce_product_stock_level';

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct();

		$this->category    = __( 'WooCommerce', 'personalizewp' );
		$this->description = __( 'Product Stock Level', 'personalizewp' );

		$this->measure_key = 'product_id';

		$this->comparators = [
			'in_stock'     => _x( 'In Stock', 'Comparator', 'personalizewp' ),
			'out_of_stock' => _x( 'Out of Stock', 'Comparator', 'personalizewp' ),
			'on_backorder' => _x( 'On Backorder', 'Comparator', 'personalizewp' ),
		];

		$this->comparison_values = [
			'true'  => _x( 'True', 'Comparison value', 'personalizewp' ),
			'false' => _x( 'False', 'Comparison value', 'personalizewp' ),
		];

		$this->comparison_type = 'select';
	}

	/**
	 * Test data against condition
	 *
	 * @param string $comparator Comparator test to run
	 * @param string $value      Comparison to check
	 * @param string $action     Action to take
	 * @param mixed  $meta       Additional meta data containing product_id(s)
	 *
	 * @return bool
	 */
	public function matchesCriteria( $comparator, $value, $action, $meta = [] ): bool {

		// Double check the API is available.
		if ( ! function_exists( 'wc_get_product' ) ) {
			return false;
		}

		// Convert to bool
		$value = (bool) ( 'true' === $value );

		// Get product IDs from meta
		$product_ids = [];

		$meta = (array) $meta;
		if ( isset( $meta[ $this->measure_key ] ) ) {
			$product_ids = explode( ',', $meta[ $this->measure_key ] );
			// Sanitise the product IDs.
			$product_ids = array_filter( array_unique( array_map( 'intval', $product_ids ) ) );
		}

		if ( empty( $product_ids ) ) {
			// Switch to using Product from current page URL
			$product_id = $this->get_current_product_id();
			if ( ! $product_id ) {
				// Nothing valid, immediate fail.
				return false;
			}
			$product_ids = [ $product_id ];
		}

		foreach ( $product_ids as $product_id ) {
			$product = wc_get_product( $product_id );
			if ( ! $product ) {
				// If no product found, comparison is true only when value is "false"
				return false === $value;
			}

			// Test each product in turn. When not valid can immediately stop.
			switch ( $comparator ) {
				case 'in_stock':
					$is_in_stock = $product->is_in_stock() && ! $product->is_on_backorder();
					$valid       = ( $is_in_stock === $value );
					if ( ! $valid ) {
						return false;
					}
					break;

				case 'out_of_stock':
					$is_out_of_stock = ! $product->is_in_stock() && ! $product->is_on_backorder();
					$valid           = ( $is_out_of_stock === $value );
					if ( ! $valid ) {
						return false;
					}
					break;

				case 'on_backorder':
					$is_on_backorder = $product->is_on_backorder();
					$valid           = ( $is_on_backorder === $value );
					if ( ! $valid ) {
						return false;
					}
					break;
			}
		}

		// At this point every product passed validity.
		return true;
	}

	/**
	 * Gets the current product ID being viewed.
	 *
	 * @return int|false
	 */
	protected function get_current_product_id() {

		// $_SERVER['REQUEST_URI'] have location parameter value set in setup_params_for_rule_conditions()
		$post_id = false;

		if ( ! empty( $GLOBALS['PERSONALIZEWP_PARAMS']['page_properties']['obj'] ) ) {
			$post_id = absint( $GLOBALS['PERSONALIZEWP_PARAMS']['page_properties']['obj'] );
		} elseif ( isset( $_SERVER['REQUEST_URI'] ) ) {
			// Fall back to the actual 'faked' URL of the current page.
			$url = home_url( esc_url_raw( wp_unslash( $_SERVER['REQUEST_URI'] ) ) );
			// Get the post ID from the URL
			$post_id = url_to_postid( $url );
		} else {
			return false;
		}

		if ( ! empty( $post_id ) ) {
			return false;
		}

		return $post_id;
	}

	/**
	 * Array of dependencies for the condition to be used
	 *
	 * @return array
	 */
	public function dependencies(): array {
		return [
			Woocommerce::instance(),
		];
	}
}
