<?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-2024, 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;

use Automattic\WooCommerce\Internal\ProductAttributesLookup\LookupDataStore;
use WC_Price_Calculator_Settings;

defined('ABSPATH') or exit;

/**
 * Updating product data lookup tables handler.
 *
 * @since 3.23.6
 */
class ProductDataLookup
{
	public function __construct()
	{
		$this->addHooks();
	}

	/**
	 * Adds action and filter hooks.
	 *
	 * @since 3.23.6
	 */
	protected function addHooks() : void
	{
		add_action(
			'woocommerce_run_product_attribute_lookup_update_callback',
			[$this, 'onRunningProductAttributeLookupUpdateCallback'],
			20,
			2
		);
	}

	/**
	 * On performing an update of the lookup table for a product.
	 *
	 * @since 3.23.6
	 *
	 * @param int $productId The product id to perform the update for.
	 * @param int $action The action to perform, one of the {@see LookupDataStore}::ACTION constants.
	 */
	public function onRunningProductAttributeLookupUpdateCallback(int $productId, int $action) : void
	{
		if (! $this->shouldHandleAction($action)) {
			return;
		}

		if (! $setting = $this->getCalculatorSettingsForProduct($productId)) {
			return;
		}

		$data = array_filter([
			'min_price' => (float) $setting->get_pricing_rules_minimum_price(),
			'max_price' => (float) $setting->get_pricing_rules_maximum_price(),
		]);

		// bail early, no prices to be updated.
		if (empty($data)) {
			return;
		}

		global $wpdb;

		$wpdb->update(
			$wpdb->wc_product_meta_lookup,
			$data,
			['product_id' => $productId],
			array_fill(0, count($data), '%f'),
			['%d']
		);
	}

	/**
	 * Determines if it should handle the action or not.
	 *
	 * @since 3.23.6
	 *
	 * @param int $action
	 *
	 * @return bool
	 */
	protected function shouldHandleAction(int $action) : bool
	{
		return in_array($action, [
			LookupDataStore::ACTION_INSERT,
			LookupDataStore::ACTION_UPDATE_STOCK,
		], true);
	}

	/**
	 * Gets the {@see WC_Price_Calculator_Settings} for the given product.
	 *
	 * @since 3.23.6
	 *
	 * @param int $productId
	 *
	 * @return WC_Price_Calculator_Settings|null returns `null` if given invalid or non-MPC product
	 */
	protected function getCalculatorSettingsForProduct(int $productId) : ?WC_Price_Calculator_Settings
	{
		if (! $product = wc_get_product($productId)) {
			return null;
		}

		$setting = WC_Price_Calculator_Settings::for($product);

		return $setting->is_calculator_enabled() ? $setting : null;
	}
}
