<?php
/**
 * Коллектор изменений цен текущего запроса (core).
 *
 * @package E2W_Price_Change_Alerts
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Class E2W_Price_Change_Alerts_Change_Collector
 */
class E2W_Price_Change_Alerts_Change_Collector {

	/**
	 * Изменения запроса. Ключ: "{product_id}:{price_type}".
	 *
	 * @var array
	 */
	private $changes = array();

	/**
	 * Регистрация хуков.
	 */
	public function __construct() {
		add_action( 'e2w_price_change_alerts_price_changed', array( $this, 'collect' ) );
		add_action( 'shutdown', array( $this, 'flush' ), 20 );
	}

	/**
	 * Принять изменение. Повторная смена той же цены в этом же запросе
	 * схлопывается: первое old, последнее new.
	 *
	 * @param array $change Изменение (product_id, price_type, old, new).
	 */
	public function collect( $change ) {
		// Публичный хук — не доверяем форме payload от сторонних вызовов.
		if ( ! is_array( $change ) || ! isset( $change['product_id'], $change['price_type'], $change['old'], $change['new'] ) ) {
			return;
		}

		$key = $change['product_id'] . ':' . $change['price_type'];

		if ( isset( $this->changes[ $key ] ) ) {
			$this->changes[ $key ]['new'] = $change['new'];
		} else {
			$this->changes[ $key ] = $change;
		}
	}

	/**
	 * Отдать накопленную пачку в отправку.
	 */
	public function flush() {
		$batch = array();

		foreach ( $this->changes as $change ) {
			$old = $change['old'];
			$new = $change['new'];

			if ( $old === $new ) {
				continue;
			}

			if ( is_numeric( $old ) && is_numeric( $new ) && (float) $old === (float) $new ) {
				continue;
			}

			$batch[] = $change;
		}

		$this->changes = array();

		if ( empty( $batch ) ) {
			return;
		}

		// Точка расширения: premium может обогатить пачку (например, пометить
		// подозрительные изменения) до раздачи всем каналам доставки.
		$batch = apply_filters( 'e2w_price_change_alerts_batch', $batch );

		if ( ! is_array( $batch ) ) {
			return;
		}

		// После стороннего фильтра заново гарантируем контракт формы записей.
		$batch = array_values(
			array_filter(
				$batch,
				static function ( $change ) {
					return is_array( $change ) && isset( $change['product_id'], $change['price_type'], $change['old'], $change['new'] );
				}
			)
		);

		if ( empty( $batch ) ) {
			return;
		}

		do_action( 'e2w_price_change_alerts_send_batch', $batch );
	}
}
