<?php
/**
 * Flavor Theme Compatibility
 *
 * Handles compatibility with Flavor theme and similar themes using AJAX cart popups.
 * Also, compatible with NASA theme which uses a similar cart system.
 *
 * @since   4.4.5
 * @package Extra_Product_Options_For_WooCommerce
 */

// Exit if accessed directly.
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * EPOFW Theme Flavor Compatibility Class
 *
 * @since   4.4.5
 *
 * Fixes cart subtotal refresh issues with Flavor theme's AJAX cart popup.
 */
class EPOFW_Theme_Flavor {

	/**
	 * Instance of this class.
	 *
	 * @since 4.4.5
	 *
	 * @var EPOFW_Theme_Flavor
	 */
	private static $instance = null;

	/**
	 * Constructor.
	 *
	 * @since 4.4.5
	 */
	private function __construct() {
		$this->init_hooks();
	}

	/**
	 * Initialize hooks.
	 *
	 * @since 4.4.5
	 */
	private function init_hooks() {
		// Add extra cart fragment data to ensure options are included.
		add_filter( 'woocommerce_add_to_cart_fragments', array( $this, 'add_cart_fragments' ), 20 );

		// Hook into AJAX add to cart to ensure proper response.
		add_action( 'woocommerce_ajax_added_to_cart', array( $this, 'after_ajax_add_to_cart' ), 20 );

		// Fix mini-cart price display - remove duplicate price since theme shows it separately.
		add_filter( 'woocommerce_widget_cart_item_quantity', array( $this, 'fix_widget_cart_item_quantity' ), 99, 3 );

		// Fix mini-cart addon display - include price in value like cart page.
		add_filter( 'woocommerce_get_item_data', array( $this, 'fix_mini_cart_item_data' ), 999, 2 );

		// Change addon totals hook priority to appear after theme's nasa-custom-fields (priority 25).
		add_filter( 'epofw_after_add_to_cart_button_priority', array( $this, 'adjust_addon_totals_priority' ) );

		// Force validation even without nonce for theme's custom AJAX add to cart.
		add_filter( 'epofw_force_validation_without_nonce', '__return_true' );

		// Add client-side validation script for immediate feedback.
		// Use wp_enqueue_scripts with late priority to ensure epofw-front is registered.
		add_action( 'wp_enqueue_scripts', array( $this, 'add_ajax_validation_script' ), 99 );

		// Decode HTML entities in file values (Elessi theme HTML-encodes JSON arrays).
		add_filter( 'epofw_file_value_before_parse', array( $this, 'decode_file_value_html_entities' ) );
	}

	/**
	 * Adjust the priority of addon totals to appear after theme's custom fields.
	 *
	 * Elessi/Flavor theme adds nasa-custom-fields at priority 25 on woocommerce_after_add_to_cart_button.
	 * We change our priority to 26 so addon totals appear after the theme's div.
	 *
	 * @since 4.4.5
	 *
	 * @param int $priority Current priority.
	 *
	 * @return int Adjusted priority.
	 */
	public function adjust_addon_totals_priority( $priority ) {
		return 26;
	}

	/**
	 * Decode HTML entities in file value before parsing.
	 *
	 * Elessi/Flavor theme HTML-encodes JSON arrays when storing file upload values.
	 * For example: [&quot;https://...&quot;] instead of ["https://..."]
	 * This prevents json_decode() from working correctly.
	 *
	 * @since 4.4.5
	 *
	 * @param string $value The raw file value.
	 *
	 * @return string The decoded file value.
	 */
	public function decode_file_value_html_entities( $value ) {
		if ( empty( $value ) ) {
			return $value;
		}

		// Check if value contains HTML entities (e.g., &quot;).
		if ( strpos( $value, '&' ) !== false ) {
			$value = html_entity_decode( $value, ENT_QUOTES, 'UTF-8' );
		}

		return $value;
	}

	/**
	 * Fix mini-cart widget item quantity display for themes that show quantity separately.
	 *
	 * The Elessi/Flavor themes show quantity with +/- buttons and total price separately,
	 * so we should hide this duplicate price display completely.
	 *
	 * @since 4.4.5
	 *
	 * @param string $html          The HTML output for quantity × price.
	 * @param array  $cart_item     Cart item data.
	 * @param string $cart_item_key Cart item key.
	 *
	 * @return string Empty string to hide duplicate price.
	 */
	public function fix_widget_cart_item_quantity( $html, $cart_item, $cart_item_key ) {
		// Return empty - theme already shows quantity selector and total price separately.
		return '';
	}

	/**
	 * Fix mini-cart addon item data display to include price like cart page.
	 *
	 * Some themes only display the 'value' field without the 'name' field that contains the price.
	 * This modifies the item data to include the price in the display value.
	 *
	 * @since 4.4.5
	 *
	 * @param array $item_data Array of item data.
	 * @param array $cart_item Cart item data.
	 *
	 * @return array Modified item data.
	 */
	public function fix_mini_cart_item_data( $item_data, $cart_item ) {
		// Only modify if we have epofw_data.
		if ( ! isset( $cart_item['epofw_data'] ) || empty( $cart_item['epofw_data'] ) ) {
			return $item_data;
		}

		// Loop through item data and add price to display value if available.
		foreach ( $item_data as $key => $data ) {
			// Check if this is an EPOFW addon item by looking for price in 'name'.
			if ( isset( $data['name'] ) && isset( $data['value'] ) ) {
				// Extract price from 'name' if it contains a price pattern like "(€40.00)" or "($40.00)".
				if ( preg_match( '/\([^)]*[\d.,]+[^)]*\)/', $data['name'], $matches ) ) {
					$price_part = $matches[0];

					// Get the label from 'key' or extract from 'name'.
					$label = isset( $data['key'] ) ? $data['key'] : '';

					// If 'name' has label + price, extract just the label.
					if ( ! empty( $label ) ) {
						// Build new display: "value (price)".
						$display_value = $data['value'];

						// Only add price if not already in value.
						if ( strpos( $display_value, $price_part ) === false ) {
							$display_value .= ' ' . $price_part;
						}

						$item_data[ $key ]['value']   = $display_value;
						$item_data[ $key ]['display'] = $display_value;
					}
				}
			}
		}

		return $item_data;
	}

	/**
	 * Get instance of this class.
	 *
	 * @since 4.4.5
	 *
	 * @return EPOFW_Theme_Flavor
	 */
	public static function instance() {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Add extra cart fragments for proper subtotal display.
	 *
	 * @since 4.4.5
	 *
	 * @param array $fragments Cart fragments.
	 *
	 * @return array Modified fragments.
	 */
	public function add_cart_fragments( $fragments ) {
		// Add cart subtotal fragment for Flavor theme selectors.
		if ( WC()->cart ) {
			$cart_subtotal = WC()->cart->get_cart_subtotal();

			// Common Flavor theme cart total selectors.
			$theme_fragments = array(
				'.nasa-cart-total'      => '<span class="nasa-cart-total">' . $cart_subtotal . '</span>',
				'.cart-total'           => '<span class="cart-total">' . $cart_subtotal . '</span>',
				'.mini-cart-total'      => '<span class="mini-cart-total">' . $cart_subtotal . '</span>',
				'.header-cart-total'    => '<span class="header-cart-total">' . $cart_subtotal . '</span>',
				'.cart-subtotal-amount' => '<span class="cart-subtotal-amount">' . $cart_subtotal . '</span>',
			);

			// Cart count.
			$cart_count                        = WC()->cart->get_cart_contents_count();
			$theme_fragments['.cart-count']    = '<span class="cart-count">' . $cart_count . '</span>';
			$theme_fragments['.nasa-cart-num'] = '<span class="nasa-cart-num">' . $cart_count . '</span>';

			/**
			 * Filter theme-specific cart fragments.
			 *
			 * @since 4.4.5
			 *
			 * @param array  $theme_fragments Array of cart fragment selectors and HTML.
			 * @param string $cart_subtotal   The formatted cart subtotal.
			 * @param int    $cart_count      The cart contents count.
			 */
			$theme_fragments = apply_filters( 'epofw_theme_flavor_cart_fragments', $theme_fragments, $cart_subtotal, $cart_count );

			$fragments = array_merge( $fragments, $theme_fragments );
		}

		return $fragments;
	}

	/**
	 * After AJAX adds to cart - ensure fragments are properly updated.
	 *
	 * @since 4.4.5
	 *
	 * @param int $product_id Product ID that was added.
	 */
	public function after_ajax_add_to_cart( $product_id ) {
		// Force cart to recalculate totals.
		if ( WC()->cart ) {
			WC()->cart->calculate_totals();
		}
	}

	/**
	 * Add client-side validation script for theme's AJAX add to cart.
	 *
	 * This provides immediate feedback before the AJAX request is sent.
	 * Also ensures file upload fields are properly included in AJAX data.
	 * Uses wp_add_inline_script for proper WordPress script handling.
	 *
	 * @since 4.4.5
	 */
	public function add_ajax_validation_script() {
		// Only on single product pages.
		if ( ! is_product() ) {
			return;
		}

		// Add an inline script attached to the main EPOFW frontend script.
		$script = '(function($) {
			"use strict";
		
			function validateEpofwFields($form) {
				if (!$form || !$form.length) {
					$form = $("form.cart");
				}
		
				var $epofwFields = $form.find(".epofw_fields_table");
				if (!$epofwFields.length) {
					return true;
				}
		
				if (typeof EPOFW_Validation !== "undefined" && EPOFW_Validation.validateAllFields) {
					var epofwPass = EPOFW_Validation.validateAllFields($form);
		
					if ($.inArray(false, epofwPass) !== -1) {
						var $firstError = $form.find(".epofw_error").first();
						if ($firstError.length) {
							$("html, body").animate({
								scrollTop: $firstError.offset().top - 100
							}, 300);
						}
						return false;
					}
				}
		
				return true;
			}
		
			$(document).ready(function() {
				document.addEventListener("click", function(e) {
					var $target = $(e.target);
					var $btn = $target.closest(".single_add_to_cart_button, button[type=submit], input[type=submit], .nasa-add-to-cart, .add-to-cart-btn");
		
					if (!$btn.length) {
						return;
					}
		
					var $form = $btn.closest("form.cart");
					if (!$form.length) {
						return;
					}
		
					if (!validateEpofwFields($form)) {
						e.preventDefault();
						e.stopPropagation();
						e.stopImmediatePropagation();
						return false;
					}
				}, true);
			});
		})(jQuery);';

		wp_add_inline_script( 'epofw-front-js', $script );
	}
}

// Initialize the compatibility class.
EPOFW_Theme_Flavor::instance();
