<?php // phpcs:ignore WordPress.Files.FileName.NotHyphenatedLowercase, WordPress.Files.FileName.InvalidClassFileName
/**
 * Value object for wholesale requirements validation results.
 *
 * @package Autoship\Domain\WholesalePricing
 * @since   2.13.0
 */

namespace Autoship\Domain\WholesalePricing;

/**
 * Immutable result of checking wholesale requirements against actual values.
 *
 * Use the static factory methods pass() and fail() to create instances.
 * This object has no side effects and can be safely used in any context.
 *
 * @package Autoship\Domain\WholesalePricing
 * @since   2.13.0
 */
final class WholesaleValidationResult {

	/**
	 * Whether the requirements were met.
	 *
	 * @var bool
	 */
	private bool $passed;

	/**
	 * The type of failure: 'min_qty', 'min_price', 'min_qty_and_price', or null.
	 *
	 * @var string|null
	 */
	private ?string $failure_type;

	/**
	 * The actual quantity provided.
	 *
	 * @var int
	 */
	private int $actual_qty;

	/**
	 * The actual total price provided.
	 *
	 * @var float
	 */
	private float $actual_total;

	/**
	 * The requirements that were checked.
	 *
	 * @var WholesaleRequirements
	 */
	private WholesaleRequirements $requirements;

	/**
	 * Constructor.
	 *
	 * @param bool                  $passed       Whether requirements were met.
	 * @param string|null           $failure_type The type of failure.
	 * @param int                   $actual_qty   The actual quantity.
	 * @param float                 $actual_total The actual total price.
	 * @param WholesaleRequirements $requirements The requirements checked.
	 */
	private function __construct(
		bool $passed,
		?string $failure_type,
		int $actual_qty,
		float $actual_total,
		WholesaleRequirements $requirements
	) {
		$this->passed       = $passed;
		$this->failure_type = $failure_type;
		$this->actual_qty   = $actual_qty;
		$this->actual_total = $actual_total;
		$this->requirements = $requirements;
	}

	/**
	 * Create a passing result.
	 *
	 * @param int                   $qty          The actual quantity.
	 * @param float                 $total        The actual total price.
	 * @param WholesaleRequirements $requirements The requirements checked.
	 *
	 * @return self
	 */
	public static function pass( int $qty, float $total, WholesaleRequirements $requirements ): self {
		return new self( true, null, $qty, $total, $requirements );
	}

	/**
	 * Create a failing result.
	 *
	 * @param string                $failure_type The type of failure.
	 * @param int                   $qty          The actual quantity.
	 * @param float                 $total        The actual total price.
	 * @param WholesaleRequirements $requirements The requirements checked.
	 *
	 * @return self
	 */
	public static function fail( string $failure_type, int $qty, float $total, WholesaleRequirements $requirements ): self {
		return new self( false, $failure_type, $qty, $total, $requirements );
	}

	/**
	 * Check if the validation passed.
	 *
	 * @return bool
	 */
	public function passed(): bool {
		return $this->passed;
	}

	/**
	 * Get the failure type.
	 *
	 * @return string|null
	 */
	public function get_failure_type(): ?string {
		return $this->failure_type;
	}

	/**
	 * Get the actual quantity.
	 *
	 * @return int
	 */
	public function get_actual_qty(): int {
		return $this->actual_qty;
	}

	/**
	 * Get the actual total price.
	 *
	 * @return float
	 */
	public function get_actual_total(): float {
		return $this->actual_total;
	}

	/**
	 * Get the requirements that were checked.
	 *
	 * @return WholesaleRequirements
	 */
	public function get_requirements(): WholesaleRequirements {
		return $this->requirements;
	}
}
