<?php
/**
 * WooCommerce Measurement Price Calculator
 *
 * This source file is subject to the GNU General Public License v3.0
 * that is bundled with this package in the file license.txt.
 * It is also available through the world-wide-web at this URL:
 * http://www.gnu.org/licenses/gpl-3.0.html
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@skyverge.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade WooCommerce Measurement Price Calculator to newer
 * versions in the future. If you wish to customize WooCommerce Measurement Price Calculator for your
 * needs please refer to http://docs.woocommerce.com/document/measurement-price-calculator/ for more information.
 *
 * @author    SkyVerge
 * @copyright Copyright (c) 2012-2026, SkyVerge, Inc. (info@skyverge.com)
 * @license   http://www.gnu.org/licenses/gpl-3.0.html GNU General Public License v3.0
 */

namespace SkyVerge\WooCommerce\Measurement_Price_Calculator\Products\Adapters\JsonSerializers;

defined( 'ABSPATH' ) or exit;

/**
 * Serializes a pricing rule array to ability output shape.
 *
 * The plugin stores pricing rules as plain arrays (see {@see WC_Price_Calculator_Settings::get_pricing_rules()}),
 * so there is no domain object to attach a JsonSerializable to.
 *
 * @since 3.24.0
 */
class PricingRuleSerializer {

	/**
	 * Converts a pricing rule to an array.
	 *
	 * @since 3.24.0
	 *
	 * @param array<string, mixed> $rule
	 * @return array<string, mixed>
	 */
	public static function convert( array $rule ) : array
	{
		return [
			'range_start'   => static::toNullableFloat( $rule['range_start'] ?? null ),
			'range_end'     => static::toNullableFloat( $rule['range_end'] ?? null ),
			'price'         => static::toNullableFloat( $rule['price'] ?? null ),
			'regular_price' => static::toNullableFloat( $rule['regular_price'] ?? null ),
			'sale_price'    => static::toNullableFloat( $rule['sale_price'] ?? null ),
		];
	}

	/**
	 * Gets the JSON schema for a pricing rule.
	 *
	 * @since 3.24.0
	 *
	 * @return array<string, mixed>
	 */
	public static function getJsonSchema() : array
	{
		$numberOrNull = [ 'oneOf' => [ [ 'type' => 'null' ], [ 'type' => 'number' ] ] ];

		return [
			'type'       => 'object',
			'properties' => [
				'range_start'   => array_merge( $numberOrNull, [
					'description' => __( 'Inclusive lower bound of the measurement range, in the pricing unit.', 'woocommerce-measurement-price-calculator' ),
				] ),
				'range_end'     => array_merge( $numberOrNull, [
					'description' => __( 'Inclusive upper bound of the measurement range, in the pricing unit. Null if the range is open-ended.', 'woocommerce-measurement-price-calculator' ),
				] ),
				'price'         => array_merge( $numberOrNull, [
					'description' => __( 'The effective price for this range (sale price if active, otherwise regular price).', 'woocommerce-measurement-price-calculator' ),
				] ),
				'regular_price' => array_merge( $numberOrNull, [
					'description' => __( 'The regular price for this range.', 'woocommerce-measurement-price-calculator' ),
				] ),
				'sale_price'    => array_merge( $numberOrNull, [
					'description' => __( 'The sale price for this range, or null if no sale is configured.', 'woocommerce-measurement-price-calculator' ),
				] ),
			],
		];
	}

	/**
	 * Casts a value to float, treating empty strings as null.
	 *
	 * @param mixed $value
	 * @return float|null
	 */
	protected static function toNullableFloat( $value ) : ?float {
		if ( null === $value || '' === $value ) {
			return null;
		}

		return (float) $value;
	}
}
