<?php
/**
 * WooCommerce stock change monitor.
 *
 * Hooks into WooCommerce stock change events and triggers
 * back-in-stock notifications when products are restocked.
 *
 * @package Waitlytics
 */

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

/**
 * Class WTLY_Stock_Monitor
 */
class WTLY_Stock_Monitor {

	/**
	 * Initialize stock monitoring hooks.
	 */
	public function init() {
		// Stock quantity changes.
		add_action( 'woocommerce_product_set_stock', array( $this, 'on_stock_quantity_change' ), 10, 1 );
		add_action( 'woocommerce_variation_set_stock', array( $this, 'on_variation_stock_quantity_change' ), 10, 1 );

		// Stock status changes (manual in-stock toggle).
		add_action( 'woocommerce_product_set_stock_status', array( $this, 'on_stock_status_change' ), 10, 3 );
		add_action( 'woocommerce_variation_set_stock_status', array( $this, 'on_stock_status_change' ), 10, 3 );
	}

	/**
	 * Handle product stock quantity change.
	 *
	 * Fired when product stock quantity is updated via WooCommerce.
	 * Checks if the product went from out-of-stock to in-stock.
	 *
	 * @param WC_Product $product The product object.
	 */
	public function on_stock_quantity_change( $product ) {
		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		if ( ! $product->is_in_stock() ) {
			return;
		}

		$product_id = $product->get_id();

		// Avoid duplicate triggers within the same request.
		if ( $this->already_triggered( $product_id ) ) {
			return;
		}

		$this->trigger_notifications( $product_id );
	}

	/**
	 * Handle variation stock quantity change.
	 *
	 * @param WC_Product $variation The variation object.
	 */
	public function on_variation_stock_quantity_change( $variation ) {
		if ( ! $variation || ! is_a( $variation, 'WC_Product' ) ) {
			return;
		}

		if ( ! $variation->is_in_stock() ) {
			return;
		}

		$variation_id = $variation->get_id();
		$product_id   = $variation->get_parent_id();

		// Avoid duplicate triggers within the same request.
		$cache_key = $product_id . '_' . $variation_id;
		if ( $this->already_triggered( $cache_key ) ) {
			return;
		}

		$this->trigger_notifications( $product_id, $variation_id );
	}

	/**
	 * Handle explicit stock status change.
	 *
	 * Fires when admin manually sets stock status via product edit.
	 *
	 * @param int    $product_id  Product or variation ID.
	 * @param string $stock_status New stock status.
	 * @param object $product      The product object.
	 */
	public function on_stock_status_change( $product_id, $stock_status, $product ) {
		if ( 'instock' !== $stock_status ) {
			return;
		}

		if ( ! $product || ! is_a( $product, 'WC_Product' ) ) {
			return;
		}

		$variation_id = 0;
		$actual_product_id = $product_id;

		if ( $product->is_type( 'variation' ) ) {
			$variation_id      = $product_id;
			$actual_product_id = $product->get_parent_id();
		}

		// Avoid duplicate triggers within the same request.
		$cache_key = $actual_product_id . '_' . $variation_id;
		if ( $this->already_triggered( $cache_key ) ) {
			return;
		}

		$this->trigger_notifications( $actual_product_id, $variation_id );
	}

	/**
	 * Trigger back-in-stock notifications for a product.
	 *
	 * @param int $product_id   Product ID.
	 * @param int $variation_id Optional. Variation ID. Default 0.
	 */
	private function trigger_notifications( $product_id, $variation_id = 0 ) {
		$product_id   = absint( $product_id );
		$variation_id = absint( $variation_id );

		$settings = wtly_get_settings();

		if ( empty( $settings['enable_notifications'] ) ) {
			return;
		}

		// Mark as triggered for this request.
		$cache_key = $product_id . '_' . $variation_id;
		$this->mark_triggered( $cache_key );

		$notification = new WTLY_Notification();
		$notification->send_back_in_stock_notifications( $product_id, $variation_id );

		/**
		 * Fires after back-in-stock notification process is initiated.
		 *
		 * @param int $product_id   Product ID.
		 * @param int $variation_id Variation ID.
		 */
		do_action( 'wtly_stock_restored', $product_id, $variation_id );
	}

	/**
	 * Check if notifications were already triggered for this product in this request.
	 *
	 * Prevents duplicate notification sending when multiple stock hooks fire
	 * for the same product in a single request.
	 *
	 * @param string $cache_key Unique key for the product/variation.
	 * @return bool
	 */
	private function already_triggered( $cache_key ) {
		$triggered = wp_cache_get( 'wtly_triggered_' . $cache_key, 'wtly' );
		return ! empty( $triggered );
	}

	/**
	 * Mark a product as having triggered notifications in this request.
	 *
	 * @param string $cache_key Unique key for the product/variation.
	 */
	private function mark_triggered( $cache_key ) {
		wp_cache_set( 'wtly_triggered_' . $cache_key, true, 'wtly' );
	}
}
