<?php
/**
 * Reusable product pricing module.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChangesWooCommerce\CoreCompat\WooCommerce\Pricing;

/** Owns price fields, sale-window validation, and launch templates. */
final class PricingModule {
	public const MODULE_ID = 'scheduled-changes-pricing';

	/** @return string[] */
	public function fieldKeys(): array {
		return array(
			'pricing.regular_price',
			'pricing.sale_price',
			'pricing.sale_start',
			'pricing.sale_end',
			'pricing.active_price',
		);
	}

	/**
	 * Validates pricing and sale-window invariants.
	 *
	 * @param mixed $value Canonical field value.
	 */
	public function validate( \WC_Product $product, string $key, $value ): void {
		if ( in_array( $key, array( 'pricing.regular_price', 'pricing.sale_price' ), true ) && null !== $value && (float) $value < 0 ) {
			throw new \InvalidArgumentException( 'Negative decimal values are not allowed.' );
		}

		if ( 'pricing.sale_price' === $key && null !== $value && '' !== $product->get_regular_price( 'edit' ) && (float) $value > (float) $product->get_regular_price( 'edit' ) ) {
			throw new \InvalidArgumentException( 'Sale price cannot exceed the regular price.' );
		}
		if ( 'pricing.regular_price' === $key && null !== $value && '' !== $product->get_sale_price( 'edit' ) && (float) $product->get_sale_price( 'edit' ) > (float) $value ) {
			throw new \InvalidArgumentException( 'Regular price cannot be lower than the sale price.' );
		}

		$other = 'pricing.sale_start' === $key ? $product->get_date_on_sale_to( 'edit' ) : $product->get_date_on_sale_from( 'edit' );
		if ( 'pricing.sale_start' === $key && null !== $value && $other instanceof \WC_DateTime && strtotime( (string) $value ) >= $other->getTimestamp() ) {
			throw new \InvalidArgumentException( 'Sale start must be earlier than sale end.' );
		}
		if ( 'pricing.sale_end' === $key && null !== $value && $other instanceof \WC_DateTime && strtotime( (string) $value ) <= $other->getTimestamp() ) {
			throw new \InvalidArgumentException( 'Sale end must be later than sale start.' );
		}
	}

	/** @return array<int,array<string,mixed>> */
	public function templates(): array {
		$field = static fn ( string $field_path, string $operation_type ): array => array(
			'provider_id'    => 'woocommerce-core',
			'target_type'    => 'product',
			'field_path'     => $field_path,
			'operation_type' => $operation_type,
		);

		return array(
			array(
				'schema_version' => 1,
				'id'             => 'flash-sale',
				'name'           => 'Flash sale',
				'description'    => 'Apply WooCommerce sale pricing for a campaign window.',
				'operations'     => array(
					$field( 'product.pricing.sale_price', 'set_price' ),
					$field( 'product.pricing.sale_start', 'set_field' ),
					$field( 'product.pricing.sale_end', 'set_field' ),
				),
			),
		);
	}
}
