<?php
/**
 * Stock Manager
 *
 * @package WC_Composable_Product
 */

namespace WC_Composable_Product;

defined('ABSPATH') || exit;

/**
 * Stock Manager Class
 *
 * Handles stock management for composable products
 */
class Stock_Manager {
	/**
	 * Constructor
	 */
	public function __construct() {
		// Hook into order completion to reduce stock
		add_action('woocommerce_order_status_completed', [$this, 'reduce_stock_on_order_complete'], 10, 1);
		add_action('woocommerce_order_status_processing', [$this, 'reduce_stock_on_order_complete'], 10, 1);

		// Hook into order cancellation/refund to restore stock
		add_action('woocommerce_order_status_cancelled', [$this, 'restore_stock_on_order_cancel'], 10, 1);
		add_action('woocommerce_order_status_refunded', [$this, 'restore_stock_on_order_cancel'], 10, 1);

		// Prevent double stock reduction
		add_filter('woocommerce_can_reduce_order_stock', [$this, 'prevent_composable_stock_reduction'], 10, 2);
	}

	/**
	 * Validate stock availability for selected products
	 *
	 * @param array $selected_product_ids Array of product IDs
	 * @param int $quantity Quantity of composable product being added
	 * @return bool|string True if in stock, error message otherwise
	 */
	public function validate_stock_availability($selected_product_ids, $quantity = 1) {
		foreach ($selected_product_ids as $product_id) {
			$product = wc_get_product($product_id);

			if (!$product) {
				continue;
			}

			// Skip stock check if stock management is disabled for this product
			if (!$product->managing_stock()) {
				continue;
			}

			$stock_quantity = $product->get_stock_quantity();

			// Check if product is in stock
			if (!$product->is_in_stock()) {
				return sprintf(
					/* translators: %s: product name */
					__('"%s" is out of stock and cannot be selected.', 'wc-composable-product'),
					$product->get_name()
				);
			}

			// Check if enough stock is available
			if ($stock_quantity !== null && $stock_quantity < $quantity) {
				return sprintf(
					/* translators: 1: product name, 2: stock quantity */
					__('Only %2$d of "%1$s" are available in stock.', 'wc-composable-product'),
					$product->get_name(),
					$stock_quantity
				);
			}

			// Check for backorders
			if ($product->backorders_allowed()) {
				continue;
			}
		}

		return true;
	}

	/**
	 * Check if a product has sufficient stock
	 *
	 * @param int $product_id Product ID
	 * @param int $required_quantity Required quantity
	 * @return array Stock information [in_stock, stock_quantity, backorders_allowed]
	 */
	public function get_product_stock_info($product_id, $required_quantity = 1) {
		$product = wc_get_product($product_id);

		if (!$product) {
			return [
				'in_stock' => false,
				'stock_quantity' => 0,
				'backorders_allowed' => false,
				'stock_status' => 'outofstock',
			];
		}

		$stock_quantity = $product->get_stock_quantity();
		$managing_stock = $product->managing_stock();

		return [
			'in_stock' => $product->is_in_stock(),
			'stock_quantity' => $stock_quantity,
			'backorders_allowed' => $product->backorders_allowed(),
			'stock_status' => $product->get_stock_status(),
			'managing_stock' => $managing_stock,
			'has_enough_stock' => !$managing_stock || $stock_quantity === null || $stock_quantity >= $required_quantity,
		];
	}

	/**
	 * Reduce stock for composable products when order is completed
	 *
	 * @param int $order_id Order ID
	 */
	public function reduce_stock_on_order_complete($order_id) {
		$order = wc_get_order($order_id);

		if (!$order) {
			return;
		}

		// Check if stock has already been reduced
		if ($order->get_meta('_composable_stock_reduced', true)) {
			return;
		}

		foreach ($order->get_items() as $item) {
			$product = $item->get_product();

			if (!$product || $product->get_type() !== 'composable') {
				continue;
			}

			// Get selected products from order item meta
			$selected_products = $item->get_meta('_composable_products', true);

			if (empty($selected_products) || !is_array($selected_products)) {
				continue;
			}

			$quantity = $item->get_quantity();

			// Reduce stock for each selected product
			foreach ($selected_products as $product_id) {
				$selected_product = wc_get_product($product_id);

				if (!$selected_product || !$selected_product->managing_stock()) {
					continue;
				}

				$stock_quantity = $selected_product->get_stock_quantity();

				if ($stock_quantity !== null) {
					$new_stock = $stock_quantity - $quantity;
					$selected_product->set_stock_quantity($new_stock);
					$selected_product->save();

					// Add order note
					$order->add_order_note(
						sprintf(
							/* translators: 1: product name, 2: quantity, 3: remaining stock */
							__('Stock reduced for "%1$s": -%2$d (remaining: %3$d)', 'wc-composable-product'),
							$selected_product->get_name(),
							$quantity,
							$new_stock
						)
					);
				}
			}
		}

		// Mark stock as reduced
		$order->update_meta_data('_composable_stock_reduced', true);
		$order->save();
	}

	/**
	 * Restore stock when order is cancelled or refunded
	 *
	 * @param int $order_id Order ID
	 */
	public function restore_stock_on_order_cancel($order_id) {
		$order = wc_get_order($order_id);

		if (!$order) {
			return;
		}

		// Check if stock was reduced
		if (!$order->get_meta('_composable_stock_reduced', true)) {
			return;
		}

		foreach ($order->get_items() as $item) {
			$product = $item->get_product();

			if (!$product || $product->get_type() !== 'composable') {
				continue;
			}

			// Get selected products from order item meta
			$selected_products = $item->get_meta('_composable_products', true);

			if (empty($selected_products) || !is_array($selected_products)) {
				continue;
			}

			$quantity = $item->get_quantity();

			// Restore stock for each selected product
			foreach ($selected_products as $product_id) {
				$selected_product = wc_get_product($product_id);

				if (!$selected_product || !$selected_product->managing_stock()) {
					continue;
				}

				$stock_quantity = $selected_product->get_stock_quantity();

				if ($stock_quantity !== null) {
					$new_stock = $stock_quantity + $quantity;
					$selected_product->set_stock_quantity($new_stock);
					$selected_product->save();

					// Add order note
					$order->add_order_note(
						sprintf(
							/* translators: 1: product name, 2: quantity, 3: new stock */
							__('Stock restored for "%1$s": +%2$d (total: %3$d)', 'wc-composable-product'),
							$selected_product->get_name(),
							$quantity,
							$new_stock
						)
					);
				}
			}
		}

		// Mark stock as restored
		$order->update_meta_data('_composable_stock_reduced', false);
		$order->save();
	}

	/**
	 * Prevent WooCommerce from reducing stock for composable products
	 * We handle stock reduction manually for selected products
	 *
	 * @param bool $reduce_stock Whether to reduce stock
	 * @param \WC_Order $order Order object
	 * @return bool
	 */
	public function prevent_composable_stock_reduction($reduce_stock, $order) {
		foreach ($order->get_items() as $item) {
			$product = $item->get_product();

			if ($product && $product->get_type() === 'composable') {
				// We'll handle stock reduction manually
				return false;
			}
		}

		return $reduce_stock;
	}

	/**
	 * Store selected products in order item meta
	 *
	 * @param \WC_Order_Item_Product $item Order item
	 * @param string $cart_item_key Cart item key
	 * @param array $values Cart item values
	 */
	public function store_selected_products_in_order($item, $cart_item_key, $values) {
		if (isset($values['composable_products']) && !empty($values['composable_products'])) {
			$item->add_meta_data('_composable_products', $values['composable_products'], true);
		}
	}
}
