<?php
/**
 * Meta query rules helper.
 *
 * @package PRECO
 */

namespace PRECO\Includes\Frontend\Engine\Filters\Query;

use PRECO\Includes\Frontend\Engine\Filters\PriceHelper;

defined( 'ABSPATH' ) || exit;

/**
 * Meta query rules helper.
 */
class MetaRuleHelper {
	/**
	 * Price helper.
	 *
	 * @var PriceHelper
	 */
	private $price;

	/**
	 * Constructor.
	 *
	 * @param PriceHelper $price Price helper.
	 */
	public function __construct( PriceHelper $price ) {
		$this->price = $price;
	}

	/**
	 * Add a stock status meta query clause.
	 *
	 * @param array  $meta_query Meta query array, modified by reference.
	 * @param string $relation   Rule relation (e.g. 'not_in').
	 * @param mixed  $value      Selected stock status key.
	 * @return void
	 */
	public function add_stock_status_rule( &$meta_query, $relation, $value ) {
		$status_map = array(
			'in_stock'     => 'instock',
			'out_of_stock' => 'outofstock',
			'backorder'    => 'onbackorder',
		);
		$key        = is_string( $value ) ? (string) $value : '';
		$stock      = isset( $status_map[ $key ] ) ? $status_map[ $key ] : '';
		if ( ! $stock ) {
			return;
		}

		$meta_query[] = array(
			'key'     => '_stock_status',
			'value'   => $stock,
			'compare' => ( 'not_in' === $relation ) ? '!=' : '=',
		);
	}

	/**
	 * Add an absolute price meta query clause.
	 *
	 * @param array  $meta_query Meta query array, modified by reference.
	 * @param string $relation   Rule relation (e.g. 'less').
	 * @param mixed  $value      Price threshold.
	 * @return void
	 */
	public function add_price_rule( &$meta_query, $relation, $value ) {
		if ( ! is_numeric( $value ) ) {
			return;
		}
		$n = (float) $value;
		if ( $n < 0 ) {
			return;
		}
		$meta_query[] = array(
			'key'     => '_price',
			'value'   => $n,
			'compare' => ( 'less' === $relation ) ? '<' : '>=',
			'type'    => 'NUMERIC',
		);
	}

	/**
	 * Add a price meta query clause relative to a product's current price.
	 *
	 * @param array  $meta_query Meta query array, modified by reference.
	 * @param string $relation   Rule relation (e.g. 'less').
	 * @param mixed  $value      Percentage of the reference product's price.
	 * @param mixed  $product_id Reference product ID.
	 * @return void
	 */
	public function add_relative_price_rule( &$meta_query, $relation, $value, $product_id ) {
		$product_id = absint( $product_id );
		if ( ! $product_id ) {
			return;
		}
		if ( ! is_numeric( $value ) ) {
			return;
		}

		$current_price = $this->price->get_effective_price_for_product_id( $product_id );
		if ( null === $current_price || (float) $current_price <= 0 ) {
			return;
		}

		$percent   = (float) $value;
		$threshold = (float) $current_price * ( $percent / 100 );
		if ( $threshold < 0 ) {
			return;
		}
		$meta_query[] = array(
			'key'     => '_price',
			'value'   => $threshold,
			'compare' => ( 'less' === $relation ) ? '<' : '>=',
			'type'    => 'NUMERIC',
		);
	}
}
