<?php
/**
 * Bounds resolver.
 *
 * @package PRECO
 */

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

defined( 'ABSPATH' ) || exit;

/**
 * Bounds resolver.
 */
class BoundsResolver {
	/**
	 * Effective price resolver.
	 *
	 * @var EffectivePriceResolver
	 */
	private $prices;

	/**
	 * Constructor.
	 *
	 * @param EffectivePriceResolver $prices Effective price resolver.
	 */
	public function __construct( EffectivePriceResolver $prices ) {
		$this->prices = $prices;
	}

	/**
	 * Resolve min/max price bounds from rules.
	 *
	 * @param array $rules Rules array.
	 * @param array $context Context.
	 * @return array{min:float|null,max:float|null,max_exclusive:bool}|array
	 */
	public function resolve_from_rules( $rules, $context ) {
		if ( ! is_array( $rules ) || empty( $rules ) ) {
			return array();
		}

		$min           = null;
		$max           = null;
		$max_exclusive = false;

		$product_id = isset( $context['product_id'] ) ? absint( $context['product_id'] ) : 0;

		foreach ( $rules as $rule ) {
			if ( ! is_array( $rule ) ) {
				continue;
			}
			if ( isset( $rule['enabled'] ) && false === $rule['enabled'] ) {
				continue;
			}
			$trigger_type = isset( $rule['triggerType'] ) ? (string) $rule['triggerType'] : '';
			$relation     = isset( $rule['relation'] ) ? (string) $rule['relation'] : '';
			$value        = $rule['value'] ?? null;

			if ( in_array( $trigger_type, array( 'product_price', 'price' ), true ) ) {
				if ( ! is_numeric( $value ) ) {
					continue;
				}
				$n = (float) $value;
				if ( $n < 0 ) {
					continue;
				}
				if ( 'less' === $relation ) {
					$max           = ( null === $max ) ? $n : min( (float) $max, $n );
					$max_exclusive = true;
				} else {
					$min = ( null === $min ) ? $n : max( (float) $min, $n );
				}
				continue;
			}

			if ( 'relative_price' === $trigger_type ) {
				if ( ! is_numeric( $value ) ) {
					continue;
				}
				$current_price = $product_id ? $this->prices->resolve_for_product_id( $product_id ) : null;
				if ( null === $current_price || (float) $current_price <= 0 ) {
					continue;
				}
				$current_price = (float) $current_price;
				$percent       = (float) $value;
				$threshold     = $current_price * ( $percent / 100 );
				if ( $threshold < 0 ) {
					continue;
				}
				if ( 'less' === $relation ) {
					$max           = ( null === $max ) ? $threshold : min( (float) $max, (float) $threshold );
					$max_exclusive = true;
				} else {
					$min = ( null === $min ) ? $threshold : max( (float) $min, (float) $threshold );
				}
			}
		}

		if ( null === $min && null === $max ) {
			return array();
		}
		if ( null !== $min && null !== $max && (float) $min > (float) $max ) {
			return array(
				'min'           => 1.0,
				'max'           => 0.0,
				'max_exclusive' => $max_exclusive,
			);
		}

		return array(
			'min'           => null === $min ? null : (float) $min,
			'max'           => null === $max ? null : (float) $max,
			'max_exclusive' => (bool) $max_exclusive,
		);
	}
}
