<?php

/**
 * W2PShop Main Class
 *
 * @package W2PShop
 */


defined( 'ABSPATH' ) || exit;

final class W2PShop {
	/**
	 * Flag for admin new order email
	 * @var bool*
	 */
	private bool $is_admin_new_order_email = false;

	public function __construct() {
	}

	/**
	 * Init W2PShop Plugin
	 *
	 * @return void
	 */
	public function init(): void {
		$this->define_constants();
		$this->include_classes();
		$this->init_hooks();
	}

	/**
	 * Define all constants
	 *
	 * @return void
	 */
	private function define_constants(): void {
		define( 'W2PSHOP_PLUGIN_DIR', plugin_dir_path( W2PSHOP_PLUGIN_FILE ) );
		define( 'W2PSHOP_PLUGIN_URL', plugin_dir_url( W2PSHOP_PLUGIN_FILE ) );
		define( 'W2PSHOP_PLUGIN_BASENAME', plugin_basename( W2PSHOP_PLUGIN_FILE ) );
		define( 'W2PSHOP_BASE_STORAGE_DIR', trailingslashit( wp_upload_dir()['basedir'] ) . 'w2pshop/' ); //Changing this to go to upload/w2pshop rather than /w2pshop; as this is closer to WP standards
		define( 'W2PSHOP_BASE_STORAGE_URL', content_url() . '/web-to-print-shop-core/' );
	}

	/**
	 * Include all required classes
	 *
	 * @return void
	 */
	private function include_classes(): void {
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-util-class.php';
        require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-saving-util-class.php';
        require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-order-helper-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-woo-util-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-dbhelper-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-settings-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-ajax-helper-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-order-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-templates-table-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-saved-data-handler-class.php';
		require_once W2PSHOP_PLUGIN_DIR . 'includes/w2pshop-data-presets-handler-class.php';

		//initialize saved data handler
		( new W2PShopSavedDataHandler() )->init();

		//initialize data preset handler
		( new W2PShopDataPresetsHandler() )->init();
	}

	/**
	 * Initialize hooks
	 *
	 * @return void
	 */
	private function init_hooks(): void {
		// Hook for the redirection logic
		add_action( 'admin_init', array( $this, 'redirect_after_activation' ) );

		// WordPress hooks
		add_action( 'init', array( $this, 'wp_init' ), 99 );
		add_action( 'plugins_loaded', array( $this, 'plugins_loaded' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ), 10 );
		add_action( 'wp_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );
		add_action( 'admin_enqueue_scripts', array( $this, 'wp_enqueue_scripts' ) );

		// Woocommerce hooks
		add_action( 'before_woocommerce_init', array( $this, 'w2pshop_declaring_hpos_compatibility' ) );

		// General Admin section
		add_filter( 'w2pshop_add_settings_tab', array( $this, 'w2pshop_add_settings_tab' ) );
		add_action( 'wp_ajax_activate_w2pshop_plugin', array( $this, 'activate_w2pshop_plugin' ) );

		// Add advanced settings content to settings page for W2PShop Core.
		add_action( 'w2pshop_handle_settings_tab', array( $this, 'w2pshop_handle_settings_tab' ), 50, 2 );
		add_filter( 'w2pshop_default_settings', array( $this, 'w2pshop_default_settings' ) );
		add_filter( 'w2pshop_settings_save', array( $this, 'w2pshop_settings_save' ), 10, 2 );
		add_filter( 'product_type_options', array( $this, 'product_type_options' ) );
		add_action( 'woocommerce_product_write_panel_tabs', array( $this, 'woocommerce_product_write_panel_tabs' ) );
		add_action( 'woocommerce_product_data_panels', array( $this, 'woocommerce_product_data_panels' ) );
		add_action( 'woocommerce_process_product_meta', array( $this, 'woocommerce_process_product_meta' ), 10, 2 );
		add_filter( 'plugin_action_links_' . plugin_basename( W2PSHOP_PLUGIN_FILE ), array( $this, 'w2pshop_add_settings_link' ) );

		// Order Admin section
		add_action( 'woocommerce_admin_order_item_headers', array( $this, 'woocommerce_admin_order_item_headers' ) );
		add_action( 'woocommerce_admin_order_item_values', array( $this, 'woocommerce_admin_order_item_values' ), 10, 3 );

		// Product Admin section
		add_filter( 'w2pshop_process_product_options', array( $this, 'w2pshop_core_product_options' ), 20, 2 );

		// Product section
		add_action( 'wp_head', array( $this, 'wp_head' ), 10 );
		add_action( 'woocommerce_before_single_product', array( $this, 'woocommerce_before_single_product' ), 15 );
		add_action( 'woocommerce_before_add_to_cart_button', array( $this, 'woocommerce_before_add_to_cart_button' ) );
		add_action( 'admin_bar_menu', array( $this, 'admin_bar_menu' ), 99 );

		// Cart section
		add_filter( 'woocommerce_add_cart_item_data', array( $this, 'woocommerce_add_cart_item_data' ), 10, 4 );
		add_filter( 'woocommerce_cart_item_thumbnail', array( $this, 'woocommerce_cart_item_thumbnail' ), 10, 3 );
		add_action( 'woocommerce_add_to_cart', array( $this, 'woocommerce_add_to_cart' ), 10, 6 );
		add_action( 'woocommerce_before_calculate_totals', array( $this, 'woocommerce_before_calculate_totals' ) );
		add_action( 'woocommerce_after_cart_item_name', array( $this, 'woocommerce_after_cart_item_name' ), 20, 2 );
		add_action( 'woocommerce_before_cart', array( $this, 'woocommerce_before_cart' ) );

		// Order section
		add_action( 'woocommerce_checkout_create_order_line_item', array( $this, 'woocommerce_checkout_create_order_line_item' ), 90, 4 );
		add_action( 'woocommerce_order_status_on-hold', array( $this, 'woocommerce_order_status_processing' ) );
		add_action( 'woocommerce_order_status_pending', array( $this, 'woocommerce_order_status_processing' ) );
		add_action( 'woocommerce_order_status_processing', array( $this, 'woocommerce_order_status_processing' ) );
		add_filter( 'woocommerce_order_item_name', array( $this, 'woocommerce_order_item_name' ), 10, 2 );
		add_filter( 'woocommerce_get_item_data', array( $this, 'woocommerce_get_item_data' ), 5, 2 );
		add_filter( 'woocommerce_order_again_cart_item_data', array( $this, 'woocommerce_order_again_cart_item_data' ), 10, 3 );

		// Add custom reorder button for each order item
		add_action( 'woocommerce_order_item_meta_end', array( $this, 'add_reorder_item_button' ), 10, 3);
		
		// Add AJAX handler for reordering W2PShop products
		add_action( 'wp_ajax_w2pshop_reorder_item', array( $this, 'w2pshop_reorder_item' ) );
		add_action( 'wp_ajax_nopriv_w2pshop_reorder_item', array( $this, 'w2pshop_reorder_item' ) );

		// Shop section
		add_filter( 'woocommerce_loop_add_to_cart_link', array( $this, 'woocommerce_loop_add_to_cart_link' ), 10, 3 );
		add_filter( 'woocommerce_product_is_visible', array( &$this, 'w2pshop_product_is_visible' ), 10, 2 );

		// Private Products Shortcode
		add_shortcode( 'w2pshop_private_templates', array( &$this, 'w2pshop_private_templates_shortcode' ) );

		// Email section
		add_action( 'woocommerce_email_before_order_table', array( $this, 'woocommerce_email_before_order_table' ), 10, 4 );
		add_action( 'woocommerce_email_after_order_table', array( $this, 'woocommerce_email_after_order_table' ), 10, 4 );
		add_action( 'woocommerce_order_item_meta_end', array( $this, 'woocommerce_order_item_meta_end' ), 10, 4 );

		// Ajax Hooks
		add_action( 'wp_ajax_w2pshop_get_customer_list', array( $this, 'w2pshop_get_customer_list' ), 10, 2 );

		// Rest API
		add_filter( 'woocommerce_rest_prepare_shop_order_object', array( $this, 'woocommerce_rest_prepare_shop_order' ), 10, 3 );
		add_filter( 'woocommerce_rest_prepare_shop_order', array( $this, 'woocommerce_rest_prepare_shop_order' ), 10, 3 );
		add_filter( 'woocommerce_rest_prepare_customer', array( $this, 'woocommerce_rest_prepare_customer' ), 10, 3 );

		// Duplicate Cart Item
		add_action( 'wp_ajax_w2pshop_duplicate_cart_design', array( $this, 'w2pshop_duplicate_cart_design' ) );
		add_action( 'wp_ajax_nopriv_w2pshop_duplicate_cart_design', array( $this, 'w2pshop_duplicate_cart_design' ) );

		// Add Private Templates EndPoint to My Accounts Page
		add_filter( 'woocommerce_account_menu_items', array( $this, 'add_private_templates_endpoint' ), 10, 1 );
		add_filter( 'woocommerce_get_query_vars', array( $this, 'woocommerce_private_templates_query_vars' ), 10, 1 );
		add_filter( 'woocommerce_endpoint_w2pshop-private-templates_title', array( $this, 'woocommerce_endpoint_private_templates_link_my_account' ), 10, 3 );
		add_action( 'woocommerce_account_w2pshop-private-templates_endpoint', array( $this, 'woocommerce_account_private_templates_content' ), 10, 1 );
	}

	/**
	 * WordPress Initialization Hook
	 *
	 * This function checks if PHP sessions are disabled and displays an error message if they are.
	 *
	 * @return void
	 */
	public function wp_init(): void {
		// Check if PHP sessions are disabled
		if ( PHP_SESSION_DISABLED === session_status() ) {
			// Display an error message
			?>
						<div class="notice notice-error">
				<h4>
					<strong><?php esc_attr_e( 'Important notice:', 'web-to-print-shop-core' ); ?></strong><br />
					<?php esc_attr_e( 'PHP Sessions are disabled, please enable sessions or contact support', 'web-to-print-shop-core' ); ?>
				</h4>
			</div>
			<?php
		} elseif ( ! headers_sent() && '' == session_id() ) {
			// Start the session
			session_start( array( 'read_and_close' => true ) );
		}
	}

	/**
	 * Called when the 'plugins_loaded' action is fired.
	 * This function loads the necessary files and triggers the 'w2pshop_loaded' action.
	 *
	 * @return void
	 */
	public function plugins_loaded(): void {
		// Include the upgrade.php file from the wp-admin directory
		require_once ABSPATH . 'wp-admin/includes/upgrade.php';

		// Trigger the 'w2pshop_loaded' action and pass $this as the argument
		do_action( 'w2pshop_loaded', $this );
	}

	/**
	 * Include common JS files in the footer of all pages
	 *
	 * @return void
	 */
	public function wp_enqueue_scripts(): void {
		wp_register_script( 'w2pshop_swal2_js', W2PSHOP_PLUGIN_URL . 'assets/sweetalert2/sweetalert2.min.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_swal2_js' );

		wp_register_style( 'w2pshop_swal2_css', W2PSHOP_PLUGIN_URL . 'assets/sweetalert2/sweetalert2.min.css', array(), W2PSHOPCORE_VERSION );
        wp_enqueue_style( 'w2pshop_swal2_css' );
        
        // Register and enqueue frontend CSS
        wp_register_style( 'w2pshop_frontend_css', W2PSHOP_PLUGIN_URL . 'assets/css/w2pshop-frontend.css', array(), W2PSHOPCORE_VERSION );
        wp_enqueue_style( 'w2pshop_frontend_css' );

		// Register common JS
		wp_register_script( 'w2pshop_common_js', W2PSHOP_PLUGIN_URL . 'assets/js/w2pshop-common.js', array( 'jquery', 'w2pshop_swal2_js' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_common_js' );

		// Always localize the nonce, not just on cart page
		wp_localize_script(
			'w2pshop_common_js',
			'w2pshop_nonce',
			array( wp_create_nonce( 'w2pshop_cart_action' ) )
		);

		wp_localize_script( 'w2pshop_common_js', 'w2pshop_common_data', array( 'ajaxurl' => admin_url( 'admin-ajax.php' ) ) );
		
		// Add reorder functionality for W2PShop products
		wp_register_script( 'w2pshop_reorder_js', W2PSHOP_PLUGIN_URL . 'assets/js/w2pshop-reorder.js', array( 'jquery', 'w2pshop_swal2_js' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_reorder_js' );
		
		// Localize the reorder script with nonce
		wp_localize_script( 'w2pshop_reorder_js', 'w2pshop_reorder_data', array( 
			'ajaxurl' => admin_url( 'admin-ajax.php' ),
			'nonce' => wp_create_nonce( 'w2pshop_reorder_nonce' )
		) );
	}

	/**
	 * Create the admin menu items for the plugin.
	 *
	 * @return void
	 */
	public function admin_menu(): void {
		$icon_base64 = 'PHN2ZyB3aWR0aD0iMjU5Ljc1IiBoZWlnaHQ9IjIzMi45NiIgdmVyc2lvbj0iMS4xIiB2aWV3Qm94PSIwIDAgNjguNzI2IDYxLjYzNyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtNjUuNDY3IC0xNTQuMjkpIj48cGF0aCBkPSJtODUuMjAyIDIxNC45OGMwLjExNzAyLTAuNTM4NjkgMi40OTYyLTkuNDM1OSA1Ljc0MTctMjEuNDcyIDAuNzQzNzgtMi43NTgzIDEuNDA3My01LjA3MDEgMS40NzQ1LTUuMTM3MyAwLjA2NzIxLTAuMDY3MiAwLjEyNDg5IDAuNDAzNjUgMC4xMjgxNiAxLjA0NjQgMC4wMDMzIDAuNjQyNzIgMC4wNjExNCAyLjI5OTcgMC4xMjg1OCAzLjY4MjEgMC4wNjc0NCAxLjM4MjQgMC4xOTY1IDQuNTA3OCAwLjI4Njc5IDYuOTQ1MyAwLjA5MDI5IDIuNDM3NSAwLjI0NzU5IDQuNDMxOCAwLjM0OTU1IDQuNDMxOCAwLjQ3ODA4IDAgMTguMzIxIDMuNDMgMTguODA4IDMuNjE1NiAwLjIxODI4IDAuMDgzMS0xLjUwODEgMC42NTk4Ni0zLjgzNjUgMS4yODE3LTIuMzI4MyAwLjYyMTc5LTguMTAyOSAyLjE2MTktMTIuODMyIDMuNDIyNC00LjcyOTQgMS4yNjA2LTguOTk4NiAyLjM5ODUtOS40ODcxIDIuNTI4OC0wLjgyODA2IDAuMjIwOTEtMC44Nzk2IDAuMTk3NTgtMC43NjE3Ny0wLjM0NDg0em0yMy43NDMtMTEuNzQ2Yy01LjQ1Ny01LjQyMzktOS44MTY1LTkuODYzNi05LjY4NzgtOS44NjYxIDAuMjE1NTItNGUtMyAxMC41NTEgNS4zNjQgMTMuMDA0IDYuNzU0M2wxLjA2NzUgMC42MDUgMi4xMTk5LTIuNDI1MmMxLjE2NTktMS4zMzM4IDQuMDY0My00LjY1NzYgNi40NDA4LTcuMzg2MSAyLjM3NjUtMi43Mjg1IDQuMzYxNS00Ljk2MDkgNC40MTExLTQuOTYwOXMwLjAzNTUgMC4xNDg4My0wLjAzMTQgMC4zMzA3My0wLjcwNzE4IDIuNTMzNC0xLjQyMjkgNS4yMjU1Yy0wLjcxNTcxIDIuNjkyMS0yLjAzNyA3LjYzMzItMi45MzYyIDEwLjk4cy0xLjg1ODUgNi45NTIxLTIuMTMxOCA4LjAxMTNjLTAuMjczMjcgMS4wNTkyLTAuNTkwMTQgMi4wNzU5LTAuNzA0MTYgMi4yNTkzLTAuMTQyMTIgMC4yMjg2MS0zLjMyNjktMi43NjcyLTEwLjEyOS05LjUyODF6bS0zMi45MjktNS44OTA1LTEwLjAxOS0xMC4wMjIgMS4xNjc1LTAuMzA1ODNjMS4zNjk2LTAuMzU4NzcgMTQuMTItMy43NzQ0IDIwLjIxOC01LjQxNTggNi42NjMyLTEuNzkzOCA2LjYyNjctMS44NjMzIDAuOTI2MDQgMS43NjM0LTIuODM3NyAxLjgwNTMtNS45MDM1IDMuNzM5Mi02LjgxMyA0LjI5NzYtMC45MDk1IDAuNTU4MzgtMS42NTM2IDEuMTA5Ni0xLjY1MzYgMS4yMjUgMCAwLjExNTM3IDAuMTMxNzkgMC41NDQ5MyAwLjI5Mjg4IDAuOTU0NTggMC4yNTk3NiAwLjY2MDYyIDMuMTcxOCA5LjAxNTIgNS4yNzk4IDE1LjE0OCAwLjQyMTk3IDEuMjI3NiAwLjczNDQ5IDIuMjY0NyAwLjY5NDQ4IDIuMzA0Ny0wLjA0MDAxIDAuMDQtNC41ODE1LTQuNDM3Mi0xMC4wOTItOS45NDkyem0zMC45NTgtNy42MzgzYzAuMzUxMzEtMC4zMDU0OSAyLjM3NjItMS41OTg4IDguMTIyNy01LjE4ODIgMi43Mjg1LTEuNzA0MyA0Ljk2MDktMy4yNDMzIDQuOTYwOS0zLjQyIDAtMC4xNzY3My0wLjM3MjY5LTEuMzg4NC0wLjgyODItMi42OTI2cy0xLjgyMzEtNS4yNjcyLTMuMDM5LTguODA2N2MtMS4yMTYtMy41Mzk1LTIuMjc5LTYuNTQ1OC0yLjM2MjQtNi42ODA3LTAuNjYxODUtMS4wNzA5IDEuNTc5OSAxLjA1NTggMTAuMTY4IDkuNjQ2MiA1LjQzODggNS40NDAzIDkuODE1MyAxMC4wMSA5LjcyNTQgMTAuMTU2LTAuMDg5OSAwLjE0NTQ3LTAuNDkyMzQgMC4zMjA4Mi0wLjg5NDMxIDAuMzg5NjUtMC40MDE5NiAwLjA2ODgtNC42MDA0IDEuMTY0Ni05LjMyOTggMi40MzUxLTQuNzI5NCAxLjI3MDUtOS40MzI0IDIuNTI3LTEwLjQ1MSAyLjc5MjQtMS4wMTg2IDAuMjY1MzQtMi43NzI2IDAuNzMxMS0zLjg5NzcgMS4wMzUtMi4yNjM2IDAuNjExNDItMi41NDI4IDAuNjU0MzEtMi4xNzQ0IDAuMzM0em0tMzIuMzk2LTguNjQ1YzAuNDM1OTItMS42MDA3IDEuMDE0LTMuNzQzOCAxLjI4NDYtNC43NjI1IDAuMjcwNjItMS4wMTg2IDEuMjI4Ny00LjU5MDUgMi4xMjktNy45Mzc1czEuOTI4NS03LjIxMjIgMi4yODQ5LTguNTg5NGMwLjM1NjM4LTEuMzc3MiAwLjcwNjUyLTIuNTYyNiAwLjc3ODEtMi42MzQxIDAuMDcxNTgtMC4wNzE2IDQuNDY2NiA0LjIwNTEgOS43NjY3IDkuNTAzOCA1LjMwMDEgNS4yOTg2IDkuNTk5OSA5LjY3MDYgOS41NTUgOS43MTU0LTAuMDQ0OSAwLjA0NDktMy4xNTkxLTEuNTQyMi02LjkyMDYtMy41MjY4bC02LjgzOS0zLjYwODMtMC41NDM1OCAwLjY2NDA5Yy0wLjg4Nzc0IDEuMDg0NS0xMC4yNSAxMS44NjEtMTEuMzExIDEzLjAxOWwtMC45NzczNCAxLjA2NzF6bTMyLjk2LTAuNTI5MTZjLTAuMDg5NS0wLjU4MjA5LTAuMjQyLTQuMTMzMi0wLjMzODk1LTcuODkxMy0wLjE3MTI5LTYuNjM5NS0wLjE5MjE0LTYuODM4Ny0wLjczNjMtNy4wMzYtMC4zMDgwMi0wLjExMTY2LTQuNTQ4Ni0wLjk1NjY4LTkuNDIzNi0xLjg3NzgtNC44NzQ5LTAuOTIxMTQtOC45NTQ3LTEuNzUxMy05LjA2Ni0xLjg0NDgtMC4xMTEzOC0wLjA5MzUgMi44MDU3LTAuOTY3MzIgNi40ODIzLTEuOTQxOCAzLjY3NjYtMC45NzQ0NyA5LjcyMDktMi41ODQ5IDEzLjQzMi0zLjU3ODggNC42NDE0LTEuMjQzMSA2Ljc3MTItMS43MDg0IDYuODI0OS0xLjQ5MSAwLjA0MjkgMC4xNzM3OC0wLjY1MjQ4IDMuMDQyMi0xLjU0NTQgNi4zNzQyLTMuMTggMTEuODY3LTQuMTgxOSAxNS42MTEtNC43MzY3IDE3LjctMC4zMDkyMSAxLjE2NDItMC41OTk3OSAyLjIzNTctMC42NDU3MyAyLjM4MTItMC4wNDU5IDAuMTQ1NTItMC4xNTY3My0wLjIxMTY3LTAuMjQ2Mi0wLjc5Mzc1eiIgZmlsbD0iI2IzYjNiMyIgc3Ryb2tlLXdpZHRoPSIuMjY0NTgiLz48L2c+PC9zdmc+';

		add_menu_page(
			'Web To Print Shop',
			'Web To Print',
			'manage_options',
			'w2pshop',
			array( $this, 'template_admin_about' ),
			'data:image/svg+xml;base64,' . $icon_base64,
			59.5
		);

		//Home page
		add_submenu_page(
			'w2pshop',
			__( 'Web To Print Shop', 'web-to-print-shop-core' ),
			__( 'Home', 'web-to-print-shop-core' ),
			'manage_options',
			'w2pshop',
			'',
			10
		);

		// Action for inserting extra menu items.
		do_action( 'w2pshop_add_menu_pages' );

		$otherPluginPresent = false;
		$otherW2PPlugins    = array(
			'Web To Print Shop : GoEpower',
			'Web To Print Shop : GoSendEx',
			'Web To Print Shop : PDF Editor',
			'Web To Print Shop : Pricematrix',
			'Web To Print Shop : Sinalite',
			'Web To Print Shop : uDraw Designer',
			'Web To Print Shop : Docket Manager Integration',
			'Web To Print Shop : PDF Editor (Identilam UI)',
		);
		$currentPlugins     = W2PShopUtil::getActivePlugins();
		foreach ( $otherW2PPlugins as $plugin ) {
			if ( array_key_exists( $plugin, $currentPlugins ) && $currentPlugins[ $plugin ] == 'Active' ) {
				$otherPluginPresent = true;
				break;
			}
		}

		//Plugin Settings
		if ( $otherPluginPresent ) {
			add_submenu_page(
				'w2pshop',
				__( 'Settings', 'web-to-print-shop-core' ),
				__( 'Settings', 'web-to-print-shop-core' ),
				'manage_options',
				'edit_w2pshop_settings',
				array( $this, 'template_admin_settings' ),
				20
			);
		}
	}

	public function template_admin_about(): void {
		require_once W2PSHOP_PLUGIN_DIR . '/templates/admin/about.php';
	}

	public function template_admin_settings(): void {
		if ( is_user_logged_in() && current_user_can( 'manage_options' ) ) {
			$this->register_styles();
			$this->register_scripts();
			$this->register_admin_assets();

			require_once W2PSHOP_PLUGIN_DIR . '/templates/admin/settings.php';
		}
	}

	/**
	 * TODO: Remove this function in future release.
	 * @deprecated
	 * @return void
	 */
	public function register_bootstrap(): void {
		wp_register_script( 'w2pshop_bootstrap_js', W2PSHOP_PLUGIN_URL . '/assets/bootstrap-5.3.6/js/bootstrap.bundle.min.js', array(), W2PSHOPCORE_VERSION, true );
		wp_register_style( 'w2pshop_bootstrap_css', W2PSHOP_PLUGIN_URL . '/assets/bootstrap-5.3.6/css/bootstrap.min.css', array(), W2PSHOPCORE_VERSION );

		wp_enqueue_script( 'w2pshop_bootstrap_js' );
		wp_enqueue_style( 'w2pshop_bootstrap_css' );
	}

	public function register_jquery_tagsinput(): void {
		wp_register_style( 'w2pshop_jquery_tagsinput_css', W2PSHOP_PLUGIN_URL . '/assets/jquery-tagsinput/jquery.tagsinput.css', array(), W2PSHOPCORE_VERSION );
		wp_register_script( 'w2pshop_jquery_tagsinput_js', W2PSHOP_PLUGIN_URL . '/assets/jquery-tagsinput/jquery.tagsinput.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );

		wp_enqueue_style( 'w2pshop_jquery_tagsinput_css' );
		wp_enqueue_script( 'w2pshop_jquery_tagsinput_js' );
	}

	public function register_proofing_assets(): void {
		wp_register_style( 'w2pshop_proofing_css', W2PSHOP_PLUGIN_URL . '/assets/css/w2pshop-proofing-styles.css?v=1', array(), W2PSHOPCORE_VERSION );
		wp_enqueue_style( 'w2pshop_proofing_css' );

		wp_register_script( 'w2pshop_proofing_js', W2PSHOP_PLUGIN_URL . '/assets/js/w2pshop-proofing.js?v=1', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_proofing_js' );
	}

	public function register_styles(): void {
				wp_enqueue_style( 'select2' );
	}

	public function register_scripts(): void {
		wp_register_script( 'w2pshop_ace_js', W2PSHOP_PLUGIN_URL . '/assets/ace-1.7.1/ace.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_ace_js' );

		wp_enqueue_script( 'selectWoo' );
	}

	public function register_jquery_ui(): void {
		wp_enqueue_script( 'jquery' );
		wp_enqueue_script( 'jquery-ui-core' );
		wp_enqueue_script( 'jquery-ui-sortable' );
		wp_enqueue_script( 'jquery-ui-selectable' );
		wp_enqueue_script( 'jquery-ui-widget' );
		wp_enqueue_script( 'jquery-ui-accordion' );
		wp_enqueue_script( 'jquery-ui-autocomplete' );
		wp_enqueue_script( 'jquery-ui-button' );
		wp_enqueue_script( 'jquery-ui-datepicker' );
		wp_enqueue_script( 'jquery-ui-dialog' );
		wp_enqueue_script( 'jquery-ui-draggable' );
		wp_enqueue_script( 'jquery-ui-droppable' );
		wp_enqueue_script( 'jquery-ui-menu' );
		wp_enqueue_script( 'jquery-ui-mouse' );
		wp_enqueue_script( 'jquery-ui-position' );
		wp_enqueue_script( 'jquery-ui-progressbar' );
		wp_enqueue_script( 'jquery-ui-resizable' );
		wp_enqueue_script( 'jquery-ui-selectmenu' );
		wp_enqueue_script( 'jquery-ui-slider' );
		wp_enqueue_script( 'jquery-ui-tooltip' );
		wp_enqueue_script( 'jquery-ui-tabs' );
	}

	public function register_base64_js(): void {
		wp_register_script( 'w2pshop_base64_js', W2PSHOP_PLUGIN_URL . '/assets/base64/webtoolkit.base64.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_base64_js' );
	}

	public function register_product_page_js(): void {
		wp_register_script( 'w2pshop_product_page_js', W2PSHOP_PLUGIN_URL . 'assets/js/w2pshop-product-page.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_product_page_js' );
	}

	public function register_admin_assets(): void {
		wp_register_style( 'w2pshop_admin_settings_css', W2PSHOP_PLUGIN_URL . '/assets/css/w2pshop-admin-settings.css', array(), W2PSHOPCORE_VERSION );
		wp_enqueue_style( 'w2pshop_admin_settings_css' );

		wp_register_script( 'w2pshop_admin_settings_js', W2PSHOP_PLUGIN_URL . '/assets/js/w2pshop-admin-settings.js', array( 'jquery' ), W2PSHOPCORE_VERSION, true );
		wp_enqueue_script( 'w2pshop_admin_settings_js' );
	}


	/**
	 * Add settings tab to main w2pshop settings page.
	 *
	 * @param $tabs
	 *
	 * @return array
	 */
	public function w2pshop_add_settings_tab( $tabs ): array {
		$otherPluginPresent = false;
		$otherW2PPlugins    = array( 'Web To Print Shop : PDF Editor', 'Web To Print Shop : uDraw Designer' );
		$currentPlugins     = W2PShopUtil::getActivePlugins();
		foreach ( $otherW2PPlugins as $plugin ) {
			if ( array_key_exists( $plugin, $currentPlugins ) && $currentPlugins[ $plugin ] == 'Active' ) {
				$otherPluginPresent = true;
				break;
			}
		}
		if ( $otherPluginPresent ) {
			$tabs['advanced'] = __( 'Advanced Settings', 'web-to-print-shop-core' );
		}
		return $tabs;
	}



	/**
	 * Add settings content to settings page for W2PSHOP core.
	 *
	 * @param $w2pshop_settings
	 * @param $current_tab
	 *
	 * @return void
	 */
	public function w2pshop_handle_settings_tab( $w2pshop_settings, $current_tab ): void {
		require_once W2PSHOP_PLUGIN_DIR . 'templates/admin/advanced-settings.php';
	}


	/**
	 * Define default settings for W2PSHOP core.
	 *
	 * @param $default_settings array default settings
	 *
	 * @return array
	 */
	public function w2pshop_default_settings( array $default_settings ): array {
		$default_settings['w2pshop_core_saved_data']            = false;
		$default_settings['w2pshop_core_saved_historical_data'] = false;
		$default_settings['w2pshop_core_proofing']              = false;
		$default_settings['w2pshop_confirmation_label']         = '';
		$default_settings['w2pshop_proofing_confirmation_text'] = '';
		return $default_settings;
	}



	/**
	 * Save settings for W2PSHOP core.
	 *
	 * @param $w2pshop_settings
	 * @param $current_tab
	 *
	 * @return mixed
	 */
	public function w2pshop_settings_save( $w2pshop_settings, $current_tab ): mixed {
		if ( 'advanced' !== $current_tab ) {
			return $w2pshop_settings;
		}
		if ( ! isset( $_REQUEST['w2pshop_settings_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_settings_nonce'] ) ), 'save_w2pshop_settings' ) ) {
			return $w2pshop_settings;
		}

        $text_fields = [
            'w2pshop_confirmation_label',
        ];
        foreach ($text_fields as $field) {
            W2PShopSaverUtil::save_text_field( $w2pshop_settings, $field );
        }

        $false_fields = [
            'w2pshop_core_saved_data',
            'w2pshop_core_saved_historical_data',
            'w2pshop_core_proofing',
        ];
        foreach ($false_fields as $field) {
            W2PShopSaverUtil::save_default_false( $w2pshop_settings, $field );
        }

		if ( isset( $_REQUEST['w2pshop_proofing_confirmation_text'] ) ) {
			$w2pshop_settings['w2pshop_proofing_confirmation_text'] = wp_kses( wp_unslash( $_REQUEST['w2pshop_proofing_confirmation_text'] ), W2PShop::get_html_design_tags() );
		}

		return $w2pshop_settings;
	}



	public function product_type_options( $types ): array {
		$types['w2pshop_product'] = array(
			'id'            => '_w2pshop_product',
			'wrapper_class' => 'show_if_w2pshop_product hide_if_grouped hide_if_external hide',
			'label'         => __( 'W2PShop Product', 'web-to-print-shop-core' ),
			'default'       => 'yes',
			'description'   => __( 'Select if you want to designate this product as a W2PShop product.', 'web-to-print-shop-core' ),
		);

		return $types;
	}

	public function woocommerce_product_data_panels(): void {
		$this->register_jquery_ui();
		$this->register_styles();
		$this->register_scripts();
		$this->register_admin_assets();

		require_once W2PSHOP_PLUGIN_DIR . '/templates/admin/woo-product-panel.php';
	}

	public function woocommerce_product_write_panel_tabs(): void {
		echo '<li class="w2pshop_product_tab w2pshop_product_options hide_if_grouped hide_if_external hide_if_virtual hide_if_downloadable">';
		echo '<a href="#w2pshop_product_data" style="padding:10px;"><span style="margin-left: 7px;">W2PShop options</span></a>';
		echo '</li>';
	}

	public function get_products(): array {
		$wp_query = new WP_Query(
			array(
				'post_type'      => 'product',
				'posts_per_page' => 9999,
				'meta_query'     => array(
					array(
						'key' => '_w2pshop_product',
					),
				),
			)
		);

		return $wp_query->posts;
	}

	/**
	 * Action for processing product meta when a product is saved.
	 * It will also set the _w2pshop_product meta field with the W2PShop product options.
	 *
	 * @param $post_id int The ID of the post being saved
	 * @param $post WP_Post The post being saved
	 *
	 * @return void
	 */

	public function woocommerce_process_product_meta( int $post_id, WP_Post $post ): void {
		$w2pshop_product_options = array();

		// Default to false.  Any plugin that uses this should set this to true to enable it.
		$w2pshop_product_options['is_enabled'] = false;
		$w2pshop_product_options               = apply_filters(
			'w2pshop_process_product_options',
			$w2pshop_product_options,
			$post_id,
		);
		update_post_meta( $post_id, '_w2pshop_product', $w2pshop_product_options );
	}


	/**
	 * Add settings link to w2pshop Core settings tab
	 * @param array $links
	 *
	 * @return array
	 */
	public function w2pshop_add_settings_link( array $links ): array {
		$url           = get_admin_url() . 'admin.php?page=edit_w2pshop_settings';
		$settings_link = '<a href="' . $url . '">' . __( 'Settings', 'web-to-print-shop-core' ) . '</a>';
		array_unshift( $links, $settings_link );
		return $links;
	}

	/**
	 * Processes the product options in the admin section when creating/updating a product.
	 * This will get called when the product is being saved.
	 *
	 * @param $w2pshop_product_options array W2PShop product options
	 *
	 * @param int|null                                              $post_id int post id
	 *
	 * @return array $w2pshop_product_options
	 */
	public function w2pshop_core_product_options( array $w2pshop_product_options, ?int $post_id = null ): array {
		if ( ! isset( $_REQUEST['w2pshop_product_settings_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_product_settings_nonce'] ) ), 'save_w2pshop_product_settings' ) ) {
			return $w2pshop_product_options;
		}

		$w2pshop_product_options['is_enabled']                 = true;
		$w2pshop_product_options['w2pshop_is_private_product'] =
			( ! empty( $_REQUEST['w2pshop_is_private_product'] ) ) ?
				sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_is_private_product'] ) ) :
			false;

		if ( isset( $_REQUEST['w2pshop_private_users'] ) ) {
			$w2pshop_product_options['w2pshop_private_users'] = sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_private_users'] ) );
			if ( is_array( $w2pshop_product_options['w2pshop_private_users'] ) ) {
				$w2pshop_product_options['w2pshop_private_users'] =
					array_map(
						function ( $value ) {
							return intval( $value );
						},
						$w2pshop_product_options['w2pshop_private_users']
					);
			}
		}

		$w2pshop_product_options['w2pshop_bypass_design_and_upload'] =
			( ! empty( $_REQUEST['w2pshop_bypass_design_and_upload'] ) ) ?
			sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_bypass_design_and_upload'] ) ) :
			false;

		return $w2pshop_product_options;
	}

	/**
	 * Allow any W2PShop product to inject any additional html to the header of the page if needed.
	 * Will trigger 'w2pshop_wp_head_product' only if the product is a W2PShop product.
	 *
	 * @return void
	 */
	public function wp_head(): void {
		if ( is_product() ) {
			global $post, $product;

			if ( W2PShopSettings::is_w2pshop_product( $post->ID ) ) {
				do_action( 'w2pshop_wp_head_product', $post, $product );
			}
		}
	}

    private function performCartOperation($cart_item_key, $w2pshop_product_raw): void {
	    global $post, $product;
	    // Stop early if required data is missing
	    if ( ! $cart_item_key || ! $w2pshop_product_raw ) {
		    return;
	    }

	    // Decode JSON to validate structure
	    $decoded = json_decode( html_entity_decode( $w2pshop_product_raw ) );
	    if ( json_last_error() !== JSON_ERROR_NONE || ( ! is_array( $decoded ) && ! is_object( $decoded ) ) ) {
		    return;
	    }

	    $w2pshop_product = $w2pshop_product_raw;

	    // Remove old cart item if it exists
	    global $woocommerce;
	    if ( array_key_exists( $cart_item_key, $woocommerce->cart->get_cart() ) ) {
		    $woocommerce->cart->remove_cart_item( $cart_item_key );
	    }

	    do_action( 'w2pshop_after_remove_cart_item', $post, $product, $cart_item_key, $w2pshop_product );
    }

	/**
	 * Action for loading a product page when a product is set as a W2PShop product.
	 *
	 * If the product is a W2PShop product, it will fire action 'w2pshop_before_single_product'
	 *
	 * @return void
	 */
	public function woocommerce_before_single_product(): void {
		global $post, $product;

		if ( W2PShopSettings::is_w2pshop_product( $post->ID ) ) {
			do_action( 'w2pshop_before_single_product', $post, $product );
		}

		// Below routine will run only when an existing W2PShop product is being updated.
		$request_method = isset( $_SERVER['REQUEST_METHOD'] ) ? sanitize_text_field( wp_unslash( $_SERVER['REQUEST_METHOD'] ) ) : '';
		if ( 'POST' === $request_method ) {
			$nonce = isset( $_REQUEST['w2pshop_product_page_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_product_page_nonce'] ) ) : '';
			if ( wp_verify_nonce( $nonce, 'w2pshop_product_actions' ) ) {
				$cart_item_key = isset( $_POST['cart_item_key'] ) ? sanitize_text_field( wp_unslash( $_POST['cart_item_key'] ) ) : '';
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Data is validated as JSON and sanitized in performCartOperation method
				$w2pshop_product_raw = isset( $_POST['w2pshop_product'] ) ? wp_unslash( $_POST['w2pshop_product'] ) : '';
				$this->performCartOperation( $cart_item_key, $w2pshop_product_raw );
			}
		}

		require_once W2PSHOP_PLUGIN_DIR . 'templates/frontend/product-page-core.php';
	}

	/**
	 * Custom form data for the add to cart button if the product is a W2PShop product.
	 *
	 * @return void
	 */
	public function woocommerce_before_add_to_cart_button(): void {
		global $post, $product;
		if ( W2PShopSettings::is_w2pshop_product( $post->ID ) ) {
			// Removed Bootstrap requirement
			// TODO: Remove this from future release.
			// $this->register_bootstrap();

			// Register W2PShop Product Page JS
			$this->register_product_page_js();

			// Register Proofing assets ( css and js ) if enabled
			if ( ! empty( W2PShopSettings::get_setting( 'w2pshop_core_proofing' ) ) ) {
				$this->register_proofing_assets();
			}

			$w2pshop_product_data = '"[]"';
			$nonce = isset( $_REQUEST['w2pshop_product_page_nonce'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_product_page_nonce'] ) ) : '';
			if ( isset( $_REQUEST['cart_item_key'] ) && wp_verify_nonce( $nonce, 'w2pshop_product_actions' ) ) {
				$cart_item_key = sanitize_text_field( wp_unslash( $_REQUEST['cart_item_key'] ) );
				$w2pshop_product = W2PShopWooUtil::get_woocommerce_cart_data( $cart_item_key );
				if ( ! is_null( $w2pshop_product ) ) {
					$w2pshop_product_data = str_replace( ' ', '&nbsp;', json_encode( $w2pshop_product, JSON_UNESCAPED_UNICODE | JSON_HEX_QUOT | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS ) );
				}
			}

			$w2pshop_product_data = esc_attr( $w2pshop_product_data ); // Sanitize the value for attribute context

			$allowed_html = array(
				'input' => array(
					'type'  => true,
					'id'    => true,
					'name'  => true,
					'value' => true,
				),
			);

			echo wp_kses(
				'<input type="hidden" id="w2pshop_product" name="w2pshop_product" value="' . $w2pshop_product_data . '" />',
				$allowed_html
			);
			
			// Add cart_item_key as hidden field if it exists in the request
			if ( isset( $_REQUEST['cart_item_key'] ) ) {
				$cart_item_key = sanitize_text_field( wp_unslash( $_REQUEST['cart_item_key'] ) );
				echo wp_kses(
					'<input type="hidden" name="cart_item_key" value="' . esc_attr( $cart_item_key ) . '" />',
					$allowed_html
				);
			}
			
			wp_nonce_field( 'w2pshop_product_actions', 'w2pshop_product_page_nonce' );
			do_action( 'w2pshop_before_add_to_cart_button', $post, $product );
		}
	}

	/**
	 * Custom admin bar menu if the product is a W2PShop product.
	 *
	 * @return void
	 */

	public function admin_bar_menu(): void {
		global $wp_admin_bar, $post, $product;
		//ensure the hook is called only on the frontend
		if ( ! is_admin() && W2PShopSettings::is_w2pshop_product( $post->ID ) ) {
			do_action( 'w2pshop_admin_bar_menu', $wp_admin_bar, $post, $product );
		}
	}


	/**
	 * Inject data when product is added to the cart if it's a W2PShop product.
	 *
	 * @param array $cart_item_data Cart item data
	 * @param int $product_id Product ID
	 * @param int $variation_id Variation ID
	 * @param int $quantity  Quantity
	 *
	 * @return array Cart item data
	 */
	public function woocommerce_add_cart_item_data( array $cart_item_data, int $product_id, int $variation_id, int $quantity ): array {
		// Check if this is an uDraw Apparel product first
		if ( metadata_exists( 'post', $product_id, '_udraw_apparel_product' ) &&
			get_post_meta( $product_id, '_udraw_apparel_product', true ) === 'yes' ) {
			// This is an uDraw Apparel product, don't modify the cart data
			return $cart_item_data;
		}

		if ( ! isset( $_REQUEST['w2pshop_product_page_nonce'] ) || ! wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_product_page_nonce'] ) ), 'w2pshop_product_actions' ) ) {
			return $cart_item_data;
		}
		if ( W2PShopSettings::is_w2pshop_product( $product_id ) ) {
			if ( isset( $_REQUEST['w2pshop_product'] ) ) {
				// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Data is validated as JSON below and sanitized when used
				$w2pshop_product_raw = wp_unslash( $_REQUEST['w2pshop_product'] );
				
				// Decode to validate JSON structure.
				$decoded = json_decode( html_entity_decode( $w2pshop_product_raw ), true );
				
				// Only save if it's valid JSON array.
				if ( JSON_ERROR_NONE === json_last_error() && is_array( $decoded ) ) {
					$cart_item_data['w2pshop_product'] = $w2pshop_product_raw;
				}
			}
		}
		return $cart_item_data;
	}

	/**
	 * Updates the cart item thumbnail if the product is a W2PShop product.
	 *
	 * @param $cart_item_thumbnail string Default cart item thumbnail
	 * @param $cart_item array Cart item data
	 * @param $cart_item_key string Cart item key
	 *
	 * @return string
	 */
	public function woocommerce_cart_item_thumbnail( string $cart_item_thumbnail, array $cart_item, string $cart_item_key ): string {
		if ( W2PShopSettings::is_w2pshop_product( $cart_item['product_id'] ) ) {

			$w2pshop_product_data = json_decode( html_entity_decode( $cart_item['w2pshop_product'] ), true );

			if (! is_array( $w2pshop_product_data ) ) {
				return $cart_item_thumbnail; // No W2PShop product or invalid data
			}

			$url_params = array();
			// Support for variations
			if ( count( $cart_item['variation'] ) > 0 ) {
				if ( is_array( $cart_item['variation'] ) ) {
					$url_params = $cart_item['variation'];
				} else {
					$url_params[] = $cart_item['variation'];
				}
			}

			// Add cart item key to url for thumbnail link.
			$url_params[] = array( 'cart_item_key' => $cart_item_key );

			$cart_item_thumbnail = apply_filters(
				'w2pshop_cart_item_thumbnail',
				$cart_item_thumbnail,
				$w2pshop_product_data,
				$url_params,
				$cart_item,
				$cart_item_key
			);
		}

		return $cart_item_thumbnail;
	}

	/**
	 * This action gets called by WooCommerce when a product is added to the cart.
	 *
	 * @param string $cart_item_key
	 * @param int $product_id
	 * @param int $quantity
	 * @param int $variation_id
	 * @param array $variation
	 * @param array $cart_item_data
	 *
	 * @return void
	 */
	public function woocommerce_add_to_cart(
		string $cart_item_key,
		int $product_id,
		int $quantity,
		int $variation_id,
		array $variation,
		array $cart_item_data
	): void {

		if ( array_key_exists( 'w2pshop_product', $cart_item_data ) ) {
			$w2pshop_product_data         = json_decode( html_entity_decode( $cart_item_data['w2pshop_product'] ), true );
			$w2pshop_data_presets_handler = new W2PShopDataPresetsHandler();

			do_action( 'w2pshop_add_to_cart', $cart_item_key, $product_id, $quantity, $cart_item_data, $w2pshop_product_data );

			// If AI data presets based on historical data setting is enabled, then trigger save data function on add to cart for logged in users.
			if ( is_user_logged_in() ) {
				if ( $w2pshop_data_presets_handler->is_enabled() ) {
					$w2pshop_data_presets_handler->save_historical_data_from_order_details( $w2pshop_product_data );
				}
			}
		}
	}

	/**
	 * Action that runs before WooCommerce calculate totals.
	 *
	 * @param $cart
	 *
	 * @return void
	 */
	public function woocommerce_before_calculate_totals( $cart ): void {
		foreach ( $cart->get_cart() as $value ) {
			if ( array_key_exists( 'w2pshop_product', $value ) ) {
				$w2pshop_product_data = json_decode( html_entity_decode( $value['w2pshop_product'] ), true );
				do_action( 'w2pshop_before_calculate_totals', $cart, $value, $w2pshop_product_data );
			}
		}

		if ( is_cart() ) {
			if ( isset( $_REQUEST['cart_updated'] ) && isset( $_REQUEST['w2pshop_cart_nonce'] ) && wp_verify_nonce( sanitize_text_field( wp_unslash( $_REQUEST['w2pshop_cart_nonce'] ) ), 'w2pshop_cart_actions' ) ) {
				wc_add_notice( __( 'Your cart has been updated', 'web-to-print-shop-core' ) );
			}
		}
	}


	/**
	 * Action to add data after the cart item name.
	 *
	 * @param $cart_item
	 * @param $cart_item_key
	 *
	 * @return void
	 */
	public function woocommerce_after_cart_item_name( $cart_item, $cart_item_key ): void {
		if ( array_key_exists( 'w2pshop_product', $cart_item ) ) {
			$w2pshop_product_data = json_decode( html_entity_decode( $cart_item['w2pshop_product'] ), true );
			do_action( 'w2pshop_after_cart_item_name', $cart_item, $cart_item_key, $w2pshop_product_data );
		}
	}


	/**
	 * Inject W2PShop product cart data into the order line item if the product is a W2PShop product.
	 *
	 * @param WC_Order_item $item
	 * @param string $cart_item_key
	 * @param array $values
	 * @param WC_Order $order
	 *
	 * @return void
	 */
	public function woocommerce_checkout_create_order_line_item( WC_Order_item $item, string $cart_item_key, array $values, WC_Order $order ): void {
		if ( key_exists( 'w2pshop_product', $values ) ) {
			$w2pshop_product_data = json_decode( html_entity_decode( $values['w2pshop_product'] ), true );
			$item->add_meta_data( '_w2pshop_product', $w2pshop_product_data, true );
			do_action( 'w2pshop_checkout_create_order_line_item', $item, $cart_item_key, $values, $order, $w2pshop_product_data );
		}
	}

	/***
	 * This action gets called when order is placed and order status is either pending or processing.
	 * We will mark the order as processed just in case the status changes back and forth.
	 *
	 * @param $order_id
	 * @return void
	 */
	public function woocommerce_order_status_processing( $order_id ): void {
		$order = wc_get_order( $order_id );

		// Sanity Check
		if ( ! $order ) {
			return;
		}

		// Check to see if we have processed this order before.
		if ( ! empty( $order->get_meta( '_w2pshop_order_processed' ) ) ) {
			return;
		}

		// Add metadata to the order so that we can mark it as processed.
		$order->add_meta_data( '_w2pshop_order_processed', $order_id );
		$order->save();  // Save the order to persist the metadata

		foreach ( $order->get_items() as $item ) {
			$w2pshop_product_data = $item->get_meta( '_w2pshop_product' );
			if ( ! is_array( $w2pshop_product_data ) ) {
				continue;
			}

			// Log for debugging
			//error_log( 'W2PShop Core: Processing order item ' . ' with ' . count( $w2pshop_product_data ) . ' data entries' );

			// Trigger action for new order only if the order item contains a W2PShop product.
			do_action( 'w2pshop_new_order_item', $order_id, $order, $item, $w2pshop_product_data );
			
            //Verify data was properly saved back after processing
            //$updated_data = $item->get_meta( '_w2pshop_product' );
            //if ( $updated_data !== $w2pshop_product_data ) {
            //  error_log( 'W2PShop Core: Order item ' . $item_id . ' data was updated during processing' );
            //}
		}

		$w2pshop_order = ( new W2PShopOrder() )->prepare_order_info( $order_id );
		do_action( 'w2pshop_new_order', $order_id, $order, $w2pshop_order );
	}

	public function woocommerce_email_before_order_table( $order, $sent_to_admin, $plain_text, $email ): void {
		// Flag only for admin "New Order" email; reset for all other emails.
		$this->is_admin_new_order_email = ( $sent_to_admin && $email instanceof WC_Email && 'new_order' === $email->id );
	}

	public function woocommerce_email_after_order_table( $order, $sent_to_admin, $plain_text, $email ): void {
		// Reset after the email finishes rendering.
		$this->is_admin_new_order_email = false;
	}

	public function woocommerce_order_item_meta_end( $item_id, $item, $order, $plain_text ): void {

		if ( ! empty( $item->get_meta( '_w2pshop_product' ) ) ) {
			// Trigger action only if item contains a W2PShop product.

			$w2pshop_product_item_data = $item->get_meta( '_w2pshop_product' );

			if ( is_array( $w2pshop_product_item_data ) ) {
				do_action(
					'w2pshop_order_item_meta_end',
					$item_id,
					$item,
					$order,
					$plain_text,
					$item->get_meta( '_w2pshop_product' ),
					$this->is_admin_new_order_email
				);
			}
		}
	}

	/**
	 * Filter to override the order item name if the product is a W2PShop product.
	 *
	 * @param string $default
	 * @param WC_Order_Item $item
	 *
	 * @return string
	 */
	public function woocommerce_order_item_name( string $default, WC_Order_Item $item ): string {
		$w2pshop_product_item_data = $item->get_meta( '_w2pshop_product' );
		if ( ! empty( $w2pshop_product_item_data ) && is_array( $w2pshop_product_item_data ) ) {
			return apply_filters( 'w2pshop_order_item_name', $default, $item, $w2pshop_product_item_data );
		}
		return $default;
	}

	/** Filter to get the item data for the order item.
	 * @param $item_data
	 * @param $cart_item
	 *
	 * @return array
	 */

	public function woocommerce_get_item_data( $item_data, $cart_item ): array {
		if ( array_key_exists( 'w2pshop_product', $cart_item ) ) {
			$w2pshop_product_data = json_decode( html_entity_decode( $cart_item['w2pshop_product'] ), true );
			$item_data            = apply_filters( 'w2pshop_get_item_data', $item_data, $cart_item, $w2pshop_product_data );
		}
		return $item_data;
	}

	/** Filter for cart item data when customer wants to re-order their previous order.
	 * @param array $cart_item_meta
	 * @param WC_Order_Item $item
	 * @param WC_Order $order
	 * @return array
	 */
	public function woocommerce_order_again_cart_item_data( array $cart_item_meta, WC_Order_Item $item, WC_Order $order ): array {
		$w2pshop_product_data = (array) $item->get_meta( '_w2pshop_product' );

		// This will force the system to generate a new file.
		// Previously the same file was being carried over ignoring any changes in the design after product has been re-added to cart from a past order.
		foreach ( $w2pshop_product_data as $product_data_item ) {
			if ( $product_data_item->key === 'pdfeditor_pdf' || $product_data_item->key === 'udraw_designer_pdf' ) {
				$product_data_item->value = '';
			}
		}

		if ( ! empty( $w2pshop_product_data ) ) {
			$cart_item_meta['w2pshop_product'] = json_encode( $w2pshop_product_data );
		}

		return $cart_item_meta;
	}

	/**
	 * Add a reorder button for individual order items in the My Account order details page.
	 * 
	 * This function displays a "Reorder Item" button for each order item, allowing customers
	 * to easily reorder specific products from their previous orders. The button only appears
	 * when viewing order details on the My Account page.
	 * 
	 * @param int $item_id The order item ID
	 * @param WC_Order_Item $item The order item object
	 * @param WC_Order $order The order object
	 * 
	 * @return void
	 * 
	 * @since 1.0.0
	 * @hook woocommerce_order_item_meta_end
	 */
	public function add_reorder_item_button( int $item_id, WC_Order_Item $item, WC_Order $order ): void {
		// Check if the order is in a valid status (not 'pending' or 'failed')
		if ( in_array( $order->get_status(), array( 'pending', 'failed' ) ) ) {
			return;
		}
	
		// Get the product safely
		$product = $item->get_product();
		if ( ! $product ) {
			return;
		}
	
		// Only add the button for physical products (optional check)
		if ( $product->is_virtual() || $product->is_downloadable() ) {
			return;
		}
	
		// Ensure we're on the 'My Account' page (order details view)
		if ( is_account_page() ) {
			// Get the product ID
			$product_id = absint( $product->get_id() );
			
			// Check if this is a W2PShop product
			if ( W2PShopSettings::is_w2pshop_product( $product_id ) ) {
				// For W2PShop products, use AJAX to reorder with all custom data
				$w2pshop_data = $item->get_meta( '_w2pshop_product' );
				if ( ! empty( $w2pshop_data ) ) {
					// Create a data attribute with the W2PShop data
					$w2pshop_data_json = esc_attr( json_encode( $w2pshop_data ) );
					$button_html = sprintf(
						'<button type="button" class="button reorder-item-button w2pshop-reorder-btn" style="margin-top: 10px;" data-product-id="%s" data-w2pshop-data="%s" data-item-id="%s" data-order-id="%s">%s</button>',
						esc_attr( $product_id ),
						$w2pshop_data_json,
						esc_attr( $item_id ),
						esc_attr( $order->get_id() ),
						esc_html__( 'Reorder Item', 'web-to-print-shop-core' )
					);
					echo wp_kses(
						$button_html,
						array(
							'button' => array(
								'type' => true,
								'class' => true,
								'style' => true,
								'data-product-id' => true,
								'data-w2pshop-data' => true,
								'data-item-id' => true,
								'data-order-id' => true,
							),
						)
					);
				} else {
					// Fallback to product page if no W2PShop data
					$reorder_url = esc_url( get_permalink( $product_id ) );
					$link_html = sprintf(
						'<a href="%s" class="button reorder-item-button" style="margin-top: 10px;">%s</a>',
						$reorder_url,
						esc_html__( 'Reorder Item', 'web-to-print-shop-core' )
					);
					echo wp_kses(
						$link_html,
						array(
							'a' => array(
								'href' => true,
								'class' => true,
								'style' => true,
							),
						)
					);
				}
			} else {
				// For regular products, use the standard add to cart
				$reorder_url = esc_url( wc_get_cart_url() . '?add-to-cart=' . absint( $product_id ) );
					$link_html = sprintf(
						'<a href="%s" class="button reorder-item-button" style="margin-top: 10px;">%s</a>',
						$reorder_url,
						esc_html__( 'Reorder Item', 'web-to-print-shop-core' )
					);
					echo wp_kses(
						$link_html,
						array(
							'a' => array(
								'href' => true,
								'class' => true,
								'style' => true,
							),
						)
					);
			}
		}
	}

    private function getCleanW2PData($w2pshop_data): array|string {
	    if ( is_string( $w2pshop_data ) ) {
		    $decoded       = json_decode( html_entity_decode( $w2pshop_data ), true );
		    $w2pshop_data  = is_array( $decoded ) ? $decoded : array();
	    } elseif ( ! is_array( $w2pshop_data ) ) {
		    $w2pshop_data = array();
	    }
	    if ( empty( $w2pshop_data ) || ! is_array( $w2pshop_data ) ) {
		    wp_send_json_error( array( 'message' => 'Invalid W2PShop data format' ) );
	    }
	    return wc_clean( $w2pshop_data );
    }
    private function validateProduct($product): void {
	    if ( ! $product ) {
		    wp_send_json_error( array( 'message' => 'Product not found' ) );
	    }
    }
    private function validateData($data): void {
	    if ( empty( $data ) || ! is_array( $data ) ) {
		    wp_send_json_error( array( 'message' => __( 'Invalid W2PShop product data', 'web-to-print-shop-core' ) ) );
	    }
    }
    private function validateProductIsPurchasable($product_id): void {
        $product = wc_get_product( $product_id );
	    if ( 'publish' !== get_post_status( $product_id ) || ! $product->is_purchasable() || ! $product->is_in_stock() ) {
		    wp_send_json_error( array(
			    'message'  => __( 'Uh oh! Looks like this product is not available to reorder.', 'web-to-print-shop-core' ),
			    'type'     => 'product_unavailable',
			    'shop_url' => wc_get_page_permalink( 'shop' ),
		    ) );
	    }
    }

	/**
	 * AJAX handler for reordering W2PShop products with all custom data.
	 *
	 * This function processes the reorder request and adds the product to cart
	 * with all the W2PShop customizations from the original order.
	 *
	 * @return void
	 *
	 * @hook wp_ajax_w2pshop_reorder_item
	 * @throws Exception
	 */
	public function w2pshop_reorder_item(): void {
		// Verify nonce for security
		$nonce = isset( $_POST['nonce'] ) ? sanitize_text_field( wp_unslash( $_POST['nonce'] ) ) : '';
		if ( ! wp_verify_nonce( $nonce, 'w2pshop_reorder_nonce' ) ) {
			wp_send_json_error( array( 'message' => 'Security check failed' ) );
		}

		$product_id = isset( $_POST['product_id'] ) ? absint( wp_unslash( $_POST['product_id'] ) ) : 0;
		
		// Handle W2PShop data properly - it might be a string or already an array
		// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.InputNotValidated, WordPress.Security.NonceVerification.Missing -- Nonce verified above; data is decoded and sanitized via wc_clean() below.
		$w2pshop_data = isset( $_POST['w2pshop_data'] ) ? wp_unslash( $_POST['w2pshop_data'] ) : array();
		$w2pshop_data = $this->getCleanW2PData($w2pshop_data);

		// Validate product exists
		$this->validateProduct(wc_get_product( $product_id ));

		// Validate W2PShop data
        $this->validateData($w2pshop_data);

		// Ensure product can be purchased again
		$this->validateProductIsPurchasable($product_id);

		// Add to cart with W2PShop data
		$cart_item_data = array(
			'w2pshop_product' => json_encode( $w2pshop_data )
		);

		// Add to cart
		$cart_item_key = WC()->cart->add_to_cart( $product_id, 1, 0, array(), $cart_item_data );

		if ( $cart_item_key ) {
			// Success - redirect to product page with cart item reference
			$product_url = get_permalink( $product_id );
			
			// Check if product URL exists and is valid
			if ( ! $product_url || $product_url === get_permalink( 0 ) ) {
				wp_send_json_error( array( 
					'message' => 'Uh oh! Looks like this product is not available to reorder.',
					'type' => 'product_unavailable',
					'shop_url' => wc_get_page_permalink( 'shop' )
				) );
			}
			
			$redirect_url = add_query_arg( array(
				'display-options' => 'true',
				'cart_item_key' => $cart_item_key
			), $product_url );
			
			wp_send_json_success( array( 
				'message' => 'Product added to cart successfully',
				'redirect_url' => $redirect_url
			) );
		} else {
			wp_send_json_error( array(
				'message'  => __( 'Uh oh! Looks like this product is not available to reorder.', 'web-to-print-shop-core' ),
				'type'     => 'product_unavailable',
				'shop_url' => wc_get_page_permalink( 'shop' ),
			) );
		}
	}

	/** Filter to change the add to cart link from the shop page if the product is a W2PShop product.
	 *
	 * @param $class
	 * @param $product
	 * @param array $args
	 *
	 * @return  string
	 */
	public function woocommerce_loop_add_to_cart_link( $class, $product, array $args = array() ): string {
		global $post;
		if ( W2PShopSettings::is_w2pshop_product( $post->ID ) ) {
			$product_url = get_permalink( $product->get_id() );
			$args        = wp_parse_args(
				$args,
				array(
					'class' => 'button',
					'style' => 'border: 1px solid #000;',
				)
			);

			// Return the modified button HTML
			return sprintf(
				'<a href="%s" class="%s" style="%s">%s</a>',
				esc_url( $product_url ),
				esc_attr( $args['class'] ),
				esc_attr( $args['style'] ),
				esc_html__( 'Shop Now', 'web-to-print-shop-core' )
			);
		}
		return $class; //return non modified button
	}

	/**
	 * Hide Products from catalog if set as private
	 */
	public function w2pshop_product_is_visible( $visible, $product_id ) {
		$is_product_private = W2PShopSettings::get_product_option( $product_id, 'w2pshop_is_private_product' );

		if ( $is_product_private === 'yes' ) {
			$visible = false;
		}
		return $visible;
	}

	/**
	 * Generates a shortcode for displaying private products assigned to a logged in user.
	 *
	 * @param mixed $atts array of attributes for the shortcode. Default is an empty array.
	 * @param string|null $content The content inside the shortcode tags. Default is null.
	 * @param string $tag The name of the shortcode. Default is an empty string.
	 *
	 * @return string Shortcode output.
	 */
	public function w2pshop_private_templates_shortcode( mixed $atts, string $content = null, string $tag = '' ): string {
		// normalize attribute keys, lowercase
		$atts = array_change_key_case( (array) $atts, CASE_LOWER );
        // Earliest possible exit after transformation
        if ( ! is_user_logged_in() ) {
            return '<div class="w2pshop-private-templates">You must be logged in to view this page.</div>';
        }

        // override default attributes with user attributes
		$w2pshop_atts = shortcode_atts(
			array(
				'title' => 'Private Templates',
				'type'  => 'all',
			),
			$atts,
			$tag
		);

		$current_user      = wp_get_current_user();
		$private_templates = $this->get_private_templates( $current_user->ID );
		return $this->display_private_templates( $private_templates );
	}

	/**
	 * Retrieves all products that are set to be private products/ templates.
	 */
	public function get_private_templates( $customer_id ): string {
		$products         = wc_get_products(
			array(
				'status' => 'publish',
				'limit'  => -1,
			)
		);
		$private_products = array();

		foreach ( $products as $product ) {
			$product_id         = $product->get_id();
			$is_product_private = W2PShopSettings::get_product_option( $product_id, 'w2pshop_is_private_product' );
			if ( $is_product_private == 'yes' ) {
				$get_private_users = W2PShopSettings::get_product_option( $product_id, 'w2pshop_private_users' );

				if ( is_array( $get_private_users ) ) {
					if ( in_array( $customer_id, $get_private_users ) ) {
						$private_products[] = $product_id;
					}
				}
			}
		}

		return implode( ',', $private_products );
	}

	/**
	 * Display all private products/ templates.
	 */
	private function display_private_templates( $private_template_ids ): string {
		return do_shortcode( '[products ids="' . $private_template_ids . '"  visibility="hidden" paginate="true"]' );
	}

	/**
	 * Get a list of all users that matches the search criteria.
	 */
	public function w2pshop_get_customer_list( string $search_str ) {
		// Check user capability
		check_ajax_referer( 'w2pshop_search_nonce', 'security' );
		if ( ! current_user_can( 'manage_options' ) ) {
			return array();
		}

		// Retrieve search string from request if not provided
		$search_str = empty( $search_str ) && isset( $_REQUEST['search_str'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search_str'] ) ) : $search_str;

		$search_str = sanitize_text_field( wp_unslash( $search_str ) );

		if ( empty( $search_str ) ) {
			return array();
		}

		// Setup user query arguments
		$args = array(
			//'search'         => '*' . esc_attr( $search_str ) . '*',
			'search'         => esc_attr( $search_str ) . '*',
			'search_columns' => array( 'user_email' ),
			'number'         => 100,
			'role__in'       => array( 'customer' ),
			'fields'         => array( 'ID', 'user_email' ), // Limit the fields to reduce memory usage
		);

		// Get users
		$user_query = new WP_User_Query( $args );
		$users      = $user_query->get_results();

		if ( is_ajax() ) {
			header( 'Content-Type: application/json' );
			wp_send_json( $users );
        }
        return $users;
    }

	public function add_private_templates_endpoint( $items ): array {
		$menu_item = array( 'w2pshop-private-templates' => __( 'Private Templates', 'web-to-print-shop-core' ) );

		// Find the position of the key
		$position = array_search( 'orders', array_keys( $items ), true );

		// Check if the key was found
		if ( false !== $position ) {

			// Split the array into two parts and add the new item in between
			return array_merge(
				array_slice( $items, 0, $position + 1 ),
				$menu_item,
				array_slice( $items, $position + 1 )
			);
		} else {
			$items[] = $menu_item;
			return $items;
		}
	}

	/**
	 * Adds a new query variable to the list of WooCommerce query variables.
	 *
	 * @param array $vars The list of WooCommerce query variables.
	 *
	 * @return array The updated list of WooCommerce query variables.
	 */
	public function woocommerce_private_templates_query_vars( array $vars ): array {
		$vars['w2pshop-private-templates'] = 'w2pshop-private-templates';
		return $vars;
	}

	/**
	 * Modifies the title of the WooCommerce endpoint for Private Templates.
	 *
	 * @param string $title The original title.
	 * @param string $endpoint The endpoint being accessed.
	 * @param string $action The action being performed.
	 *
	 * @return string The modified title.
	 */
	public function woocommerce_endpoint_private_templates_link_my_account( string $title, string $endpoint, string $action ): string {
		// Check if the main query is for the endpoint and in the main loop
		if ( is_wc_endpoint_url( 'w2pshop-private-templates' ) && in_the_loop() ) {
			$title = __( 'Private Templates', 'web-to-print-shop-core' );
		}
		return $title;
	}

	/**
	 * Renders the content for the private template's endpoint.
	 *
	 * @return void
	 */
	public function woocommerce_account_private_templates_content(): void {
		echo do_shortcode( '[w2pshop_private_templates]' );
	}

	public function w2pshop_duplicate_cart_design( $design_key = '', $customer_cart_item_key = '', $cart_design_type = '' ): void {
		check_ajax_referer( 'w2pshop_cart_action', 'security' );
		$design_key             = ( empty( $_REQUEST['design_key'] ) ) ? $design_key : sanitize_text_field( wp_unslash( $_REQUEST['design_key'] ) );
		$customer_cart_item_key = ( empty( $_REQUEST['customer_cart_item_key'] ) ) ? $customer_cart_item_key : sanitize_text_field( wp_unslash( $_REQUEST['customer_cart_item_key'] ) );
		$cart_design_type       = ( empty( $_REQUEST['cart_design_type'] ) ) ? $cart_design_type : sanitize_text_field( wp_unslash( $_REQUEST['cart_design_type'] ) );

        $add_to_cart = null;
		if ( 'udraw' === $cart_design_type ) {
			$add_to_cart = apply_filters( 'w2pshop_duplicate_cart_udraw_design', $design_key, $customer_cart_item_key );
		} elseif ( 'pdf' === $cart_design_type ) {
			$add_to_cart = apply_filters( 'w2pshop_duplicate_cart_pdflib_design', $design_key, $customer_cart_item_key );
		}

		if ( $add_to_cart ) {
			wp_send_json( array( 'success' => true ) );
		} else {
			wp_send_json( array( 'success' => false ) );
		}

		wp_die();
	}

	/**
	 * Displays a table header for the order item if the product is a W2PShop product.
	 *
	 * @param $order
	 *
	 * @return void
	 */
	public function woocommerce_admin_order_item_headers( $order ): void {
		foreach ( $order->get_items() as $item ) {
			if ( ! empty( $item->get_meta( '_w2pshop_product', true ) ) ) {
				// Include W2PShop Admin Order Page JS
				wp_register_script(
					'w2pshop_admin_order_page_js',
					W2PSHOP_PLUGIN_URL . '/assets/js/w2pshop-admin-order-page.js',
					array( 'jquery' ),
					W2PSHOPCORE_VERSION,
					true
				);
				wp_enqueue_script( 'w2pshop_admin_order_page_js' );

				// TODO: Add action so that other W2PShop plugins can potentially inject their own JS.

				// Add thickbox support
				add_thickbox();

				echo '<div id="w2pshop-order-item-preview-container" class="w2pshop-order-item-preview" style="display: none;"></div>';
				echo '<th class="w2pshop-product-heading" style="min-width:260px; text-align:center;">W2P Shop</th>';
				break;
			}
		}
	}

	/**
	 * Calls action 'w2pshop_admin_order_item_values' if the product is a W2PShop product.
	 *
	 * @param WC_Product|null $product
	 * @param $item
	 * @param int $item_id
	 *
	 * @return void
	 */
	public function woocommerce_admin_order_item_values( ?WC_Product $product, $item, int $item_id ): void {
		// Convert false or invalid products to null
		if ( ! $product instanceof WC_Product ) {
			$product = null;
		}

		if ( ! $item instanceof WC_Order_Item ) {
			return;
		}

		$w2pshop_product_item_data = $item->get_meta( '_w2pshop_product' );
		if ( ! empty( $w2pshop_product_item_data ) && is_array( $w2pshop_product_item_data ) ) {
			echo '<td class="udraw-product" style="width:150px; text-align:center;">';
			do_action( 'w2pshop_admin_order_item_values', $product, $item, $item_id, $w2pshop_product_item_data );
			echo '</td>';
		}
	}

	public function woocommerce_rest_prepare_shop_order( $response, $post, $request ) {
		// Early return if response data is empty
		if ( empty( $response->data ) ) {
			return $response;
		}

		$order_data = W2PShopUtil::normalize_rest_country_code( $response );

		// Check if line items exist
		$line_items = $order_data['line_items'] ?? [];
		if ( ! is_array( $line_items ) ) {
			return $response;
		}

		// Iterate over line items
		foreach ( $line_items as &$order_item ) {
			$meta_data_items = $order_item['meta_data'] ?? [];
			if ( ! is_array( $meta_data_items ) ) {
				continue;
			}

			foreach ( $meta_data_items as &$meta_data ) {
				if ( '_w2pshop_product' !== ($meta_data['key'] ?? '') ) {
					continue;
				}

				$w2pshop_product_item_data = $meta_data['value'] ?? null;

				// Filter to allow modification
				$w2pshop_product_line_meta_data = apply_filters(
					'w2pshop_rest_prepare_shop_order',
					$w2pshop_product_item_data,
					$order_item,
					$order_data
				);

				if ( empty( $w2pshop_product_line_meta_data ) ) {
					continue;
				}

				// Convert array to comma-separated string
				if ( is_array( $w2pshop_product_line_meta_data ) ) {
					$w2pshop_product_line_meta_data = implode( ', ', $w2pshop_product_line_meta_data );
				}

				$w2pshop_product_line_meta_data = rtrim( $w2pshop_product_line_meta_data, ', ' );

				$meta_data['value']         = $w2pshop_product_line_meta_data;
				$meta_data['display_value'] = $w2pshop_product_line_meta_data;
			}
		}

		// Update the response data
		$order_data['line_items'] = $line_items;
		$response->data          = $order_data;

		return $response;
	}

	public function woocommerce_rest_prepare_customer( $response, $user_data, $request ) {
		// Extract customer data
		$customer_data = W2PShopUtil::normalize_rest_country_code( $response );

		// Update the response data
		$response->data = $customer_data;

		return $response;
	}

	/**
	 * Declare High-Performance Order Storage (HPOS) compatibility
	 *
	 * @see https://github.com/woocommerce/woocommerce/wiki/High-Performance-Order-Storage-Upgrade-Recipe-Book#declaring-extension-incompatibility
	 *
	 * @return void
	 */
	public function w2pshop_declaring_hpos_compatibility(): void {
		if ( class_exists( '\Automattic\WooCommerce\Utilities\FeaturesUtil' ) ) {
			\Automattic\WooCommerce\Utilities\FeaturesUtil::declare_compatibility( 'custom_order_tables', 'web-to-print-shop-core/web-to-print-shop-core.php' );
		}
	}

	// Static method to handle plugin activation
	public static function activate(): void {
		update_option( 'w2pshop_do_activation_redirect', true );
	}
	public function redirect_after_activation(): void {
		if ( get_option( 'w2pshop_do_activation_redirect' ) ) {
			delete_option( 'w2pshop_do_activation_redirect' );
			if ( ! is_network_admin() ) {
				wp_safe_redirect( admin_url( 'admin.php?page=w2pshop' ) );
				exit;
			}
		}
	}

	public function activate_w2pshop_plugin(): void {
		check_ajax_referer( 'w2pshop_activate_plugin_nonce', 'security' );
		$allowed_plugins = array(
			'GOePOWER'      => 'GOePOWER',
			'GoSendEx'      => 'GoSendEx',
			'PDFEditor'     => 'PDFEditor',
			'Pricematrix'   => 'Pricematrix',
			'Sinalite'      => 'Sinalite',
			'uDrawDesigner' => 'uDraw',
		);
		$requested       = isset( $_POST['pluginName'] ) ? sanitize_text_field( wp_unslash( $_POST['pluginName'] ) ) : '';
		if ( ! isset( $allowed_plugins[ $requested ] ) ) {
			wp_send_json_error( array( 'message' => 'Invalid plugin key' ) );
			return;
		}
		wp_send_json_success( array( 'redirect' => 'plugins.php?s=' . $allowed_plugins[ $requested ] ) );
	}

	/**
	 * Add nonce to cart page
	 *
	 * @return void
	 */
	public function woocommerce_before_cart(): void {
		wp_nonce_field( 'w2pshop_cart_actions', 'w2pshop_cart_nonce' );
	}

	public static function get_html_design_tags(): array {
		return array(
			'div'    => array(
				'class' => true,
				'id'    => true,
				'style' => true,
			),
			'p'      => array(
				'class' => true,
				'style' => true,
			),
			'img'    => array(
				'src'    => true,
				'alt'    => true,
				'width'  => true,
				'height' => true,
				'class'  => true,
				'style'  => true,
			),
			'span'   => array(
				'class' => true,
				'style' => true,
			),
			'br'     => array(),
			'ul'     => array(
				'class' => true,
				'style' => true,
			),
			'ol'     => array(
				'class' => true,
				'style' => true,
			),
			'li'     => array(
				'class' => true,
				'style' => true,
			),
			'a'      => array(
				'href'   => true,
				'title'  => true,
				'target' => true,
				'rel'    => true,
				'class'  => true,
				'style'  => true,
				'id'     => true,
			),
			'strong' => array(),
		);
	}
}

