<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * TrackFree plugin bootstrap + main hooks.
 *
 * This wraps the legacy function-based implementation behind a class, while
 * keeping a small set of global wrapper functions for backward compatibility
 * (other included files call them).
 */
final class TrackFree_WooCommerce_Tracking_Plugin {
	/** @var self|null */
	private static $instance = null;

	/** @var string */
	private $plugin_file;

	private function __construct( $plugin_file ) {
		$this->plugin_file = $plugin_file;
	}

	/**
	 * Singleton.
	 *
	 * @param string|null $plugin_file Pass the main plugin file path on first call.
	 */
	public static function instance( $plugin_file = null ) {
		if ( null === self::$instance ) {
			if ( ! is_string( $plugin_file ) || $plugin_file === '' ) {
				throw new RuntimeException( 'TrackFree plugin file path is required for initialization.' );
			}
			self::$instance = new self( $plugin_file );
		}
		return self::$instance;
	}

	public static function is_woocommerce_active() {
		return in_array(
			'woocommerce/woocommerce.php',
			(array) apply_filters( 'active_plugins', (array) get_option( 'active_plugins' ) ),
			true
		);
	}

	public function trackfree_url() {
		return 'https://trackfree.io';
	}

	public function boot() {
		if ( ! self::is_woocommerce_active() ) {
			return;
		}

		add_action( 'admin_init', array( $this, 'admin_init' ) );
		add_action( 'init', array( $this, 'init' ) );
		add_action( 'in_admin_header', array( $this, 'suppress_external_admin_notices' ), 0 );
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
		add_action( 'activated_plugin', array( $this, 'activated_plugin' ) );

		add_shortcode( 'tfree-track-page', array( $this, 'shortcode_track_page' ) );

		add_action( 'wp_ajax_get_shipment_data', array( $this, 'ajax_get_shipment_data' ) );
		add_action( 'wp_ajax_nopriv_get_shipment_data', array( $this, 'ajax_get_shipment_data' ) );

		add_action( 'rest_api_init', array( $this, 'register_rest_coupon_generate' ) );
		add_action( 'rest_api_init', array( $this, 'register_rest_get_order_data' ) );
		add_action( 'rest_api_init', array( $this, 'register_rest_update_tracking' ) );
		add_action( 'rest_api_init', array( $this, 'register_rest_theme_styles' ) );

		add_action( 'plugins_loaded', array( $this, 'load_textdomain' ) );
		add_action( 'trackfree_send_theme_capture', array( $this, 'send_scheduled_theme_capture' ) );
		add_action( 'wp_footer', array( $this, 'render_theme_capture_script' ), 99 );

		add_filter( 'admin_footer_text', array( $this, 'admin_footer_text' ), 1 );
		add_filter( 'admin_body_class', array( $this, 'admin_body_class' ) );
		add_action( 'admin_menu', array( $this, 'admin_menu' ) );

		add_action( 'wp_ajax_tfree_update_shipment', array( $this, 'ajax_update_shipment' ) );
		add_action( 'wp_ajax_add_new_shipment', array( $this, 'ajax_add_new_shipment' ) );
		add_action( 'add_meta_boxes', 'trackfree_meta_box_add' ); // defined in included legacy files.
		add_action( 'wp_ajax_tracking_delete_action', array( $this, 'ajax_tracking_delete' ) );

		$this->include_legacy_files();

		if ( (int) get_option( 'trackfree_shipment_status_in_orders' ) === 1 ) {
			add_filter( 'manage_woocommerce_page_wc-orders_columns', array( $this, 'add_shipment_status_column' ) );
			add_filter( 'manage_edit-shop_order_columns', array( $this, 'add_shipment_status_column' ), 20 );

			add_action( 'manage_woocommerce_page_wc-orders_custom_column', array( $this, 'render_order_list_custom_column_hpos' ), 10, 2 );
			add_action( 'manage_shop_order_posts_custom_column', array( $this, 'render_order_list_custom_column_legacy' ), 20, 2 );
		}
	}

	private function include_legacy_files() {
		require_once $this->plugin_dir() . 'settings.php';
		require_once $this->plugin_dir() . 'includes/trackfree-home.php';
		require_once $this->plugin_dir() . 'includes/trackfree-tracking-page.php';
		require_once $this->plugin_dir() . 'includes/trackfree-shipments.php';
		require_once $this->plugin_dir() . 'includes/tf-order-details-page.php';
		require_once $this->plugin_dir() . 'includes/trackfree-shipment-overview.php';
		require_once $this->plugin_dir() . 'includes/trackfree-shipment-details.php';
		require_once $this->plugin_dir() . 'includes/trackfree-wc-order-summary.php';
		require_once $this->plugin_dir() . 'includes/tf-tracking-details.php';
	}

	private function plugin_dir() {
		return plugin_dir_path( $this->plugin_file );
	}

	private function plugin_url( $path ) {
		return plugins_url( $path, $this->plugin_file );
	}

	private function normalize_order_notes_for_payload( $order_notes ) {
		$normalized_notes = array();

		foreach ( (array) $order_notes as $order_note ) {
			if ( ! is_object( $order_note ) || ! method_exists( $order_note, 'get_id' ) ) {
				continue;
			}

			$note_date = '';
			if ( method_exists( $order_note, 'get_date_created' ) ) {
				$created_at = $order_note->get_date_created();
				if ( $created_at instanceof WC_DateTime ) {
					$note_date = $created_at->date( 'Y-m-d H:i:s' );
				}
			}

			$normalized_notes[] = array(
				'id'            => $order_note->get_id(),
				'content'       => method_exists( $order_note, 'get_content' ) ? $order_note->get_content() : '',
				'customer_note' => method_exists( $order_note, 'is_customer_note' ) ? (int) $order_note->is_customer_note() : 0,
				'added_by_user' => method_exists( $order_note, 'get_added_by' ) ? $order_note->get_added_by() : '',
				'date_created'  => $note_date,
			);
		}

		return $normalized_notes;
	}

	public function admin_init() {
		wp_register_style( 'trackfree-admin', $this->plugin_url( '/assets/css/trackfree.css' ), array(), TRACKFREE_VERSION );

		if ( isset( $_GET['page'] ) && $_GET['page'] === 'trackfree-getting-started' ) {
			$api_key = get_option( 'trackfree_account_api_key' );
			$verify  = get_option( 'trackfree_account_verify' );
			if ( $api_key && (int) $verify === 1 ) {
				$this->send_theme_capture_once( 'admin_connected' );
				wp_safe_redirect( admin_url( 'admin.php?page=trackfree' ) );
				exit;
			}
		}

		$api_key = get_option( 'trackfree_account_api_key' );
		$verify  = get_option( 'trackfree_account_verify' );
		if ( $api_key && (int) $verify === 1 ) {
			$this->send_theme_capture_once( 'admin_connected' );
		}
	}

	private function is_trackfree_admin_page() {
		if ( ! is_admin() ) {
			return false;
		}

		$page = isset( $_GET['page'] ) ? sanitize_key( wp_unslash( $_GET['page'] ) ) : '';

		return in_array( $page, array( 'trackfree', 'trackfree-getting-started' ), true );
	}

	public function suppress_external_admin_notices() {
		if ( ! $this->is_trackfree_admin_page() ) {
			return;
		}

		remove_all_actions( 'admin_notices' );
		remove_all_actions( 'all_admin_notices' );
		remove_all_actions( 'network_admin_notices' );
		remove_all_actions( 'user_admin_notices' );
	}

	public function init() {
		wp_register_style( 'trackfree-codemirror', $this->plugin_url( '/assets/plugins/codemirror/theme/material-darker.css' ) );

		wp_register_style( 'trackfree-user-track', $this->plugin_url( '/assets/css/tfree-user-track.css' ), array(), TRACKFREE_VERSION );
		wp_register_style( 'trackfree-leaflet', $this->plugin_url( '/assets/plugins/leaflet/leaflet.css' ), array(), '1.8.0' );

		wp_register_script( 'trackfree-leaflet', $this->plugin_url( '/assets/plugins/leaflet/leaflet.js' ), array(), '1.8.0' );
		wp_register_script( 'trackfree-user-track', $this->plugin_url( '/assets/js/tfree-user-track.js' ), array( 'jquery', 'trackfree-leaflet' ), TRACKFREE_VERSION );
	}

	private function enqueue_select2_assets() {
		$script_handle = '';
		if ( wp_script_is( 'wc-select2', 'registered' ) ) {
			$script_handle = 'wc-select2';
		} elseif ( wp_script_is( 'selectWoo', 'registered' ) ) {
			$script_handle = 'selectWoo';
		} elseif ( wp_script_is( 'select2', 'registered' ) ) {
			$script_handle = 'select2';
		}

		if ( $script_handle && ! wp_script_is( $script_handle, 'enqueued' ) ) {
			wp_enqueue_script( $script_handle );
		}

		$style_handle = '';
		if ( wp_style_is( 'wc-select2', 'registered' ) ) {
			$style_handle = 'wc-select2';
		} elseif ( wp_style_is( 'select2', 'registered' ) ) {
			$style_handle = 'select2';
		}

		if ( $style_handle && ! wp_style_is( $style_handle, 'enqueued' ) ) {
			wp_enqueue_style( $style_handle );
		}
	}

	public function admin_enqueue_scripts( $hook ) {
		$screen    = function_exists( 'get_current_screen' ) ? get_current_screen() : null;
		$screen_id = $screen ? $screen->id : '';

		wp_enqueue_style( 'trackfree-admin' );
		wp_enqueue_script( 'jquery' );

		if ( $hook === 'toplevel_page_trackfree' ) {
			wp_enqueue_style(
				'trackfree-react-app-css',
				plugin_dir_url( $this->plugin_file ) . 'dist/static/css/main.5aab0800.css',
				array(),
				TRACKFREE_VERSION
			);

			wp_enqueue_script(
				'trackfree-react-app-js',
				plugin_dir_url( $this->plugin_file ) . 'dist/static/js/main.4cdc7297.js',
				array(),
				TRACKFREE_VERSION,
				true
			);

			$api_key = get_option( 'trackfree_account_api_key' );

			wp_localize_script(
				'trackfree-react-app-js',
				'tfreePluginData',
				array(
					'trackfree_account_api_key' => $api_key,
					'home_url'                 => home_url(),
					'plugins_url'              => plugins_url(),
					'admin_url'                => admin_url(),
					'trackfree_url'            => $this->trackfree_url(),
					'trackfree_api_url'        => $this->trackfree_url() . '/api/',
					'track_page_url'           => trackfree_track_page_url(),
					'track_page_preview_url'   => trackfree_track_page_url( '', true ),
					'tracking_domain_url'      => get_option( 'trackfree_tracking_domain' ),
					'preferred_couriers'       => get_option( 'trackfree_preferred_couriers' ),
					'hide_quick_start_info'    => get_option( 'trackfree_hide_quick_start_info' ) == 1 ? true : false,
					'ajax_url'                 => admin_url( 'admin-ajax.php' ),
					'nonce'                    => wp_create_nonce( 'tfree_nonce' ),
					'locale'                   => get_locale(),
					'is_custom_track_url'      => get_option( 'trackfree_is_custom_track_url' ) == 1 ? true : false,
					'custom_track_link'        => get_option( 'trackfree_internal_email_link' ),
				)
			);
		}

			if ( $screen_id === 'toplevel_page_trackfree' || ( $screen && ( 'shop_order' === $screen->post_type || 'woocommerce_page_wc-orders' === $screen->base ) ) ) {
				$this->enqueue_select2_assets();
				wp_enqueue_script( 'trackfree-admin-setting', $this->plugin_url( '/assets/js/trackfree-settings.js' ), array( 'jquery' ), TRACKFREE_VERSION );
					wp_localize_script(
						'trackfree-admin-setting',
						'ajax_object',
					array(
						'ajax_url'           => admin_url( 'admin-ajax.php' ),
						'admin_url'          => admin_url(),
						'plugins_url'        => plugins_url(),
						'nonce'              => wp_create_nonce( 'tfree_nonce' ),
						'store_name'         => get_bloginfo( 'name' ),
						'admin_email'        => get_option( 'admin_email' ),
						'preferred_couriers' => get_option( 'trackfree_preferred_couriers' ),
						'auto_order_status_update' => (int) get_option( 'trackfree_auto_order_status_update' ),
						'shipment_status_in_orders' => (int) get_option( 'trackfree_shipment_status_in_orders' ),
						'sync_this_page_label' => __( 'Sync Shipment Statuses (This Page)', 'trackfree-woocommerce-tracking' ),
						'no_orders_on_page_message' => __( 'No orders found on this page.', 'trackfree-woocommerce-tracking' ),
						'syncing_label' => __( 'Syncing...', 'trackfree-woocommerce-tracking' ),
						'sync_in_progress_message' => __( 'Sync in progress...', 'trackfree-woocommerce-tracking' ),
						'sync_failed_message' => __( 'Sync failed.', 'trackfree-woocommerce-tracking' ),
						'sync_complete_message' => __( 'Sync complete.', 'trackfree-woocommerce-tracking' ),
						'sync_partial_error_message' => __( 'Some orders could not be synced.', 'trackfree-woocommerce-tracking' ),
						'sync_retry_message' => __( 'Sync failed. Please try again.', 'trackfree-woocommerce-tracking' ),
						'sync_busy_fallback_message' => __( 'Shipment status sync is already running. Please retry in a few seconds.', 'trackfree-woocommerce-tracking' ),
					)
				);

			$cm_css_settings  = wp_enqueue_code_editor( array( 'type' => 'text/css' ) );
			$cm_html_settings = wp_enqueue_code_editor( array( 'type' => 'text/html' ) );

			wp_localize_script( 'jquery', 'cm_css_settings', $cm_css_settings );
			wp_localize_script( 'jquery', 'cm_html_settings', $cm_html_settings );

			wp_enqueue_style( 'wp-codemirror' );
			wp_enqueue_style( 'trackfree-codemirror' );
		}

		if ( ! get_option( 'trackfree_track_page_id' ) ) {
			$this->ensure_track_page_exists();
		}

		if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'trackfree-getting-started', 'trackfree' ), true ) ) {
			add_action( 'admin_head', array( $this, 'add_freshworks_widget_code' ) );
		}
	}

	public function add_freshworks_widget_code() {
		?>
			<script>
				window.fwSettings = { widget_id: 153000002433 };
				(function() {
					if (typeof window.FreshworksWidget === 'function' && !window.FreshworksWidget.q) {
						return;
				}

				var loading = false;
				var loaded = false;
				var readyResolve;
				var readyReject;
				var readyPromise = new Promise(function(resolve, reject) { readyResolve = resolve; readyReject = reject; });

				function loadFreshworks() {
					if (loaded || loading) return;
					loading = true;
					var s = document.createElement('script');
					s.type = 'text/javascript';
					s.src = 'https://widget.freshworks.com/widgets/153000002433.js';
					s.async = true;
					s.defer = true;
					s.onload = function() { loaded = true; loading = false; readyResolve(true); };
					s.onerror = function() { loading = false; readyReject(new Error('Failed to load Freshworks widget')); };
					(document.head || document.getElementsByTagName('head')[0]).appendChild(s);
				}

				var n = function() {
					n.q.push(arguments);
					loadFreshworks();
				};
				n.q = [];
				window.FreshworksWidget = n;
				window.tfreeLoadFreshworksWidget = loadFreshworks;
				window.tfreeFreshworksReady = function() { loadFreshworks(); return readyPromise; };
			})();
		</script>
		<?php
	}

	public function activated_plugin( $filename ) {
		if ( '/trackfree-woocommerce-tracking.php' !== substr( $filename, -35 ) ) {
			return;
		}
		$this->ensure_track_page_exists();
	}

	private function ensure_track_page_exists() {
		$track_page_id = get_option( 'trackfree_track_page_id' );

		$page_name = 'trackfree';
		$shortcode = '[tfree-track-page]';

		$page_info = $track_page_id ? get_post( $track_page_id ) : null;
		if ( ! empty( $page_info ) && false !== strpos( $page_info->post_content, $shortcode ) ) {
			return;
		}

		global $wpdb;

		$sql  = $wpdb->prepare( "SELECT ID FROM {$wpdb->posts} WHERE post_name = %s AND post_type = 'page'", $page_name );
		$page = $wpdb->get_var( $sql );

		$page_id = 0;
		if ( $page ) {
			$page_det = get_post( $page );
			$page_id  = $page_det->ID ?? 0;
		}

		if ( empty( $page_id ) ) {
			$tf_page = array(
				'post_title'   => 'Track Order Status',
				'post_name'    => $page_name,
				'post_content' => $shortcode,
				'post_status'  => 'publish',
				'post_type'    => 'page',
				'post_author'  => 1,
			);
			$page_id = wp_insert_post( $tf_page );
		}

		if ( $track_page_id != $page_id ) {
			update_option( 'trackfree_track_page_id', $page_id );
		}
	}

	public function update_order_status( $shipment_details, $order_id ) {
		$statuses = array();
		foreach ( (array) $shipment_details as $shipment_values ) {
			$status     = isset( $shipment_values['status'] ) ? (string) $shipment_values['status'] : '';
			$statuses[] = strtolower( trim( $status ) );
		}

		if ( empty( $statuses ) ) {
			return;
		}

		$order = wc_get_order( $order_id );
		if ( ! $order ) {
			return;
		}

		$all_delivered = true;
		foreach ( $statuses as $status ) {
			if ( $status !== 'delivered' ) {
				$all_delivered = false;
				break;
			}
		}

		if ( $all_delivered && $order->get_status() !== 'completed' ) {
			$order->update_status( 'completed' );
		}
	}

	public function track_page_url( $tracking_num = '', $preview = false ) {
		$track_page_id  = get_option( 'trackfree_track_page_id' );
		$track_page_url = ! empty( $track_page_id ) ? get_page_link( $track_page_id ) : 'Unknown';
		$separate       = strpos( $track_page_url, '?' ) ? '&' : '?';

		if ( $preview ) {
			return "{$track_page_url}{$separate}tracking_num=9405516901479381873433&preview=trackfree";
		}

		if ( $tracking_num ) {
			return "{$track_page_url}{$separate}tracking_num=$tracking_num";
		}

		return $track_page_url;
	}

	public function shortcode_track_page() {
		wp_enqueue_style( 'trackfree-user-track' );
		wp_enqueue_script( 'trackfree-user-track' );
		wp_enqueue_style( 'trackfree-leaflet' );

		wp_localize_script(
			'trackfree-user-track',
			'ajax_object',
			array(
				'ajax_url'    => admin_url( 'admin-ajax.php' ),
				'admin_url'   => admin_url(),
				'plugins_url' => plugins_url(),
			)
		);

			ob_start();
			wc_get_template( 'user-tracking.php', array(), '', $this->plugin_dir() . 'templates/' );
			return (string) ob_get_clean();
		}

	public function ajax_get_shipment_data() {
		$api_key = get_option( 'trackfree_account_api_key' );

			$post_data = array(
				'tracking_number' => isset( $_POST['tfree_tracking_number'] ) ? sanitize_text_field( wp_unslash( $_POST['tfree_tracking_number'] ) ) : '',
				'order_number'    => isset( $_POST['tfree_order_number'] ) ? sanitize_text_field( wp_unslash( $_POST['tfree_order_number'] ) ) : '',
				'email'           => isset( $_POST['tfree_email'] ) ? sanitize_email( wp_unslash( $_POST['tfree_email'] ) ) : '',
			'preview'         => isset( $_POST['preview'] ) ? sanitize_text_field( wp_unslash( $_POST['preview'] ) ) : '',
		);

		$response = wp_remote_post(
			$this->trackfree_url() . '/api/wc_get_shipment_data?key=' . $api_key,
			array(
				'sslverify' => tfree_sslverify(),
				'timeout'   => 15,
				'body'      => $post_data,
			)
		);
		$response_data = json_decode( wp_remote_retrieve_body( $response ), true );

		$cont_width        = 1200;
		$width_type        = 'pixel';
		$pg_bar_color      = '#017501';
		$by_ord_num_email  = 1;
		$by_tk_num         = 1;
		$show_cr_nm        = 1;
		$show_track_num    = 1;
		$show_track_info   = 1;
		$show_product_info = 1;
		$show_map          = 1;
		$show_rec_prds     = 1;

		$cont_order           = 'Order';
		$cont_shipment        = 'Shipment';
		$cont_status          = 'Status';
		$cont_carrier         = 'Carrier';
		$cont_product         = 'Product';
		$cont_tracking_number = 'Tracking Number';
		$cont_ordered         = 'Ordered';
		$cont_order_ready     = 'Order Ready';
		$cont_in_transit      = 'In Transit';
		$cont_out_for_delivery = 'Out for Delivery';
		$cont_delivered        = 'Delivered';
		$cont_may_like         = 'You may also like...';
		$cont_order_not_found  = 'Order Not Found';

		$date_format = 1;
		$time_format = 1;

		$tf_dis_opt = get_option( 'trackfree_display_options' );
		if ( $tf_dis_opt ) {
			$cont_width        = isset( $tf_dis_opt['cont_width'] ) ? $tf_dis_opt['cont_width'] : 1200;
			$width_type        = isset( $tf_dis_opt['width_type'] ) ? $tf_dis_opt['width_type'] : 'pixel';
			$pg_bar_color      = isset( $tf_dis_opt['pg_bar_color'] ) ? $tf_dis_opt['pg_bar_color'] : '#017501';
			$by_ord_num_email  = isset( $tf_dis_opt['by_ord_num_email'] ) ? $tf_dis_opt['by_ord_num_email'] : 1;
			$by_tk_num         = isset( $tf_dis_opt['by_tk_num'] ) ? $tf_dis_opt['by_tk_num'] : 1;
			$show_cr_nm        = isset( $tf_dis_opt['show_cr_nm'] ) ? $tf_dis_opt['show_cr_nm'] : 1;
			$show_track_num    = isset( $tf_dis_opt['show_track_num'] ) ? $tf_dis_opt['show_track_num'] : 1;
			$show_track_info   = isset( $tf_dis_opt['show_track_info'] ) ? $tf_dis_opt['show_track_info'] : 1;
			$show_product_info = isset( $tf_dis_opt['show_product_info'] ) ? $tf_dis_opt['show_product_info'] : 1;
			$show_map          = isset( $tf_dis_opt['show_map'] ) ? $tf_dis_opt['show_map'] : '';
			$show_rec_prds     = isset( $tf_dis_opt['show_rec_prds'] ) ? $tf_dis_opt['show_rec_prds'] : 1;
		}

		$tf_tns_str = get_option( 'trackfree_trans_strings' );
		if ( $tf_tns_str ) {
			$cont_order            = isset( $tf_tns_str['order'] ) ? $tf_tns_str['order'] : 'Order';
			$cont_shipment         = isset( $tf_tns_str['shipment'] ) ? $tf_tns_str['shipment'] : 'Shipment';
			$cont_status           = isset( $tf_tns_str['status'] ) ? $tf_tns_str['status'] : 'Status';
			$cont_carrier          = isset( $tf_tns_str['carrier'] ) ? $tf_tns_str['carrier'] : 'Carrier';
			$cont_product          = isset( $tf_tns_str['product'] ) ? $tf_tns_str['product'] : 'Product';
			$cont_tracking_number  = isset( $tf_tns_str['tracking_number'] ) ? $tf_tns_str['tracking_number'] : 'Tracking Number';
			$cont_ordered          = isset( $tf_tns_str['ordered'] ) ? $tf_tns_str['ordered'] : 'Ordered';
			$cont_order_ready      = isset( $tf_tns_str['order_ready'] ) ? $tf_tns_str['order_ready'] : 'Order Ready';
			$cont_in_transit       = isset( $tf_tns_str['in_transit'] ) ? $tf_tns_str['in_transit'] : 'In Transit';
			$cont_out_for_delivery = isset( $tf_tns_str['out_for_delivery'] ) ? $tf_tns_str['out_for_delivery'] : 'Out for Delivery';
			$cont_delivered        = isset( $tf_tns_str['delivered'] ) ? $tf_tns_str['delivered'] : 'Delivered';
			$cont_may_like         = isset( $tf_tns_str['may_like'] ) ? $tf_tns_str['may_like'] : 'You may also like...';
			$cont_order_not_found  = isset( $tf_tns_str['order_not_found'] ) ? $tf_tns_str['order_not_found'] : 'Order Not Found';
		}

		$tf_dtm_fms = get_option( 'trackfree_date_time_formats' );
		if ( $tf_dtm_fms ) {
			$date_format = isset( $tf_dtm_fms['date_format'] ) ? $tf_dtm_fms['date_format'] : 1;
			$time_format = isset( $tf_dtm_fms['time_format'] ) ? $tf_dtm_fms['time_format'] : 1;
		}

		$tracking_settings = array(
			'cont_width'          => $cont_width,
			'width_type'          => $width_type,
			'pg_bar_color'        => $pg_bar_color,
			'by_ord_num_email'    => $by_ord_num_email,
			'by_tk_num'           => $by_tk_num,
			'show_cr_nm'          => $show_cr_nm,
			'show_track_num'      => $show_track_num,
			'show_track_info'     => $show_track_info,
			'show_product_info'   => $show_product_info,
			'show_map'            => $show_map,
			'show_rec_prds'       => $show_rec_prds,
			'cont_order'          => $cont_order,
			'cont_shipment'       => $cont_shipment,
			'cont_status'         => $cont_status,
			'cont_carrier'        => $cont_carrier,
			'cont_product'        => $cont_product,
			'cont_tracking_number' => $cont_tracking_number,
			'cont_ordered'        => $cont_ordered,
			'cont_order_ready'    => $cont_order_ready,
			'cont_in_transit'     => $cont_in_transit,
			'cont_out_for_delivery' => $cont_out_for_delivery,
			'cont_delivered'      => $cont_delivered,
			'cont_may_like'       => $cont_may_like,
			'cont_order_not_found' => $cont_order_not_found,
			'date_format'         => $date_format,
			'time_format'         => $time_format,
		);

		if ( is_array( $response_data ) && isset( $response_data['status'] ) && $response_data['status'] === 'success' && isset( $response_data['multi_tracking'] ) ) {
			$order_id            = $response_data['order_id'];
			$recommend_products  = $order_id ? get_recommend_products( $order_id ) : array();
			show_multi_tracking_details( $order_id, $response_data['data'], $tracking_settings, $recommend_products );
		} elseif ( is_array( $response_data ) && isset( $response_data['status'] ) && $response_data['status'] === 'success' ) {
			$order_id           = $response_data['data']['orderId'];
			$recommend_products = $order_id ? get_recommend_products( $order_id ) : array();
			show_tracking_details( $response_data['data'], $tracking_settings, $recommend_products );
		} else {
			$order_id = $post_data['order_number'];
			$order    = wc_get_order( $order_id );
			if ( ! empty( $order ) ) {
				$order_data = $order->get_data();
				if ( isset( $order_data['billing']['email'] ) && $order_data['billing']['email'] === $post_data['email'] ) {
					$recommend_products = $order_id ? get_recommend_products( $order_id ) : array();
					show_trackfree_order_details( $order_data, $tracking_settings, $recommend_products );
				} else {
					echo '<div style="margin: 32px"><h1>' . $tracking_settings['cont_order_not_found'] . '</h1></div>';
				}
			} else {
				echo '<div style="margin: 32px"><h1>' . $tracking_settings['cont_order_not_found'] . '</h1></div>';
			}
		}

		wp_die();
	}

	public function register_rest_coupon_generate() {
		register_rest_route(
			'trackfree-wc/v1',
			'coupon-generate',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'rest_create_auto_coupon' ),
				'permission_callback' => array( $this, 'rest_permission_api_key' ),
			)
		);
	}

	/**
	 * REST permission callback: validate TrackFree API key.
	 *
	 * @param WP_REST_Request $request
	 * @return true|WP_Error
	 */
	public function rest_permission_api_key( $request ) {
		$stored_key = (string) get_option( 'trackfree_account_api_key' );
		$req_key    = (string) $request->get_param( 'api_key' );

		if ( $stored_key === '' || $req_key === '' ) {
			return new WP_Error(
				'trackfree_invalid_auth',
				__( 'Invalid authentication', 'trackfree-woocommerce-tracking' ),
				array( 'status' => 401 )
			);
		}

		$valid = function_exists( 'hash_equals' ) ? hash_equals( $stored_key, $req_key ) : ( $stored_key === $req_key );
		if ( $valid ) {
			return true;
		}

		return new WP_Error(
			'trackfree_invalid_auth',
			__( 'Invalid authentication', 'trackfree-woocommerce-tracking' ),
			array( 'status' => 401 )
		);
	}

	public function rest_create_auto_coupon( $data ) {
		$trackfree_account_api_key = get_option( 'trackfree_account_api_key' );
		$request_api_key           = $data['api_key'];
		$coupon_code               = $data['coupon_code'];

		if ( $trackfree_account_api_key == $request_api_key ) {
			$coupon_amount     = $data['coupon_amount'];
			$discount_type     = $data['coupon_type'];
			$coupon_expires    = $data['coupon_expires'];
			$min_order_amount  = $data['min_order_amount'];
			$email             = $data['email'];

			$coupon = new WC_Coupon();
			$coupon->set_code( $coupon_code );
			$coupon->set_discount_type( $discount_type );
			$coupon->set_amount( $coupon_amount );
			$coupon->set_description( 'TrackFree promotional coupon' );

			if ( (int) $coupon_expires > 0 ) {
				$date_expires = date( 'Y-m-d', strtotime( '+' . (int) $coupon_expires . ' days' ) );
				$coupon->set_date_expires( $date_expires );
			}

			$coupon->set_usage_limit( 1 );
			$coupon->set_usage_limit_per_user( 1 );
			$coupon->set_email_restrictions( $email );

			if ( (float) $min_order_amount > 0 ) {
				$coupon->set_minimum_amount( $min_order_amount );
			}

			$coupon->save();
			return 'success';
		}

		return null;
	}

	public function register_rest_get_order_data() {
		register_rest_route(
			'trackfree-wc/v1',
			'get-order-data/(?P<order_id>\\d+)',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'rest_get_order_details' ),
				'permission_callback' => array( $this, 'rest_permission_api_key' ),
			)
		);
	}

	public function rest_get_order_details( $data ) {
		$order_id      = $data['order_id'];
		$request_api_key = $data['api_key'];
		$trackfree_account_api_key = get_option( 'trackfree_account_api_key' );

		if ( $trackfree_account_api_key == $request_api_key ) {
			$order      = wc_get_order( $order_id );
			$order_data = $order ? $order->get_data() : array();

			if ( isset( $order_data['billing']['email'] ) && $order_data['billing']['email'] == $data['email'] ) {
				$first_name = $order_data['shipping']['first_name'] ? $order_data['shipping']['first_name'] : $order_data['billing']['first_name'];
				$last_name  = $order_data['shipping']['last_name'] ? $order_data['shipping']['last_name'] : $order_data['billing']['last_name'];

				// Refund.
				$refund_amount = 0;
				$order_refunds = $order->get_refunds();
				if ( $order_refunds ) {
					foreach ( $order_refunds as $refund ) {
						$refund_amount += $refund->amount;
					}
				}

				$order_items = array();
				foreach ( $order->get_items() as $item_values ) {
					$item_data    = $item_values->get_data();
					$product_data = wc_get_product( $item_data['product_id'] );
					if ( ! empty( $product_data ) ) {
						$product_attribute_name = '';
						$variation_image_url    = '';
						if ( $item_data['variation_id'] ) {
							list( $variation_image_url, $product_attribute_name ) = tfree_get_variation_context( $item_data['variation_id'], 'full' );
						}

						$order_items[] = array(
							'product_id'    => $item_data['product_id'],
							'variation_id'  => $item_data['variation_id'],
							'name'          => $item_data['name'],
							'price'         => wc_format_decimal( $item_data['subtotal'] / $item_data['quantity'], 2 ),
							'sku'           => $product_data->get_sku(),
							'quantity'      => $item_data['quantity'],
							'slug'          => $product_data->get_slug() . $product_attribute_name,
							'line_total'    => wc_format_decimal( $item_data['subtotal'], 2 ),
							'image'         => $variation_image_url ? $variation_image_url : tfree_get_product_image_url( $product_data, 'full', true ),
						);
					}
				}

				$shipping_address = array(
					'shipping_first_name' => $order_data['shipping']['first_name'],
					'shipping_last_name'  => $order_data['shipping']['last_name'],
					'shipping_company'    => $order_data['shipping']['company'],
					'shipping_address_1'  => $order_data['shipping']['address_1'],
					'shipping_address_2'  => $order_data['shipping']['address_2'],
					'shipping_city'       => $order_data['shipping']['city'],
					'shipping_state'      => $order_data['shipping']['state'],
					'shipping_postcode'   => $order_data['shipping']['postcode'],
					'shipping_country'    => $order_data['shipping']['country'],
				);

				// Order fees.
				$order_fee = array();
				foreach ( $order->get_fees() as $fee ) {
					if ( $fee['name'] ) {
						$order_fee[] = array(
							'name'  => $fee['name'],
							'total' => $fee['total'],
						);
					}
				}

				$coupon_details     = array();
				$order_coupon_items = $order->get_items( 'coupon' );
				foreach ( $order_coupon_items as $item ) {
					$coupon_data      = $item->get_data();
					$coupon_details[] = array(
						'coupon_code'   => $coupon_data['code'],
						'coupon_amount' => $coupon_data['discount'],
					);
				}

				$order_notes = wc_get_order_notes(
					array(
						'order_id' => $order_data['id'],
					)
				);
				$order_notes = $this->normalize_order_notes_for_payload( $order_notes );

				$order_details = array(
					'key'              => $trackfree_account_api_key,
					'order_id'         => $order_data['id'],
					'order_number'     => $order_data['number'],
					'order_created_at' => $order_data['date_created'] ? $order_data['date_created']->date( 'Y-m-d H:i:s' ) : '',
					'order_status'     => $order_data['status'],
					'order_currency'   => $order_data['currency'],
					'order_total'      => wc_format_decimal( $order_data['total'], 2 ),
					'payment_method'   => $order_data['payment_method_title'],
					'transaction_id'   => $order_data['transaction_id'] ? $order_data['transaction_id'] : '',
					'customer_name'    => $last_name ? $first_name . ' ' . $last_name : $first_name,
					'customer_email'   => $order_data['billing']['email'],
					'customer_phone'   => $order_data['billing']['phone'],
					'customer_country' => $order_data['billing']['country'],
					'order_items'      => $order_items,
					'site_url'         => home_url(),
					'shipping_address' => $shipping_address,
					'shipping_method'  => $order->get_shipping_method(),
					'sub_total'        => wc_format_decimal( $order->get_subtotal(), 2 ),
					'total_discount'   => wc_format_decimal( $order->get_total_discount(), 2 ),
					'total_shipping'   => wc_format_decimal( $order->get_total_shipping(), 2 ),
					'total_tax'        => wc_format_decimal( $order->get_total_tax(), 2 ),
					'refund_total'     => wc_format_decimal( $refund_amount, 2 ),
					'shipment_details' => get_post_meta( $order_id, '_trackfree_shipment_details', true ),
					'customer_note'    => $order_notes,
					'order_fee'        => $order_fee,
					'coupon_details'   => $coupon_details,
				);

				return array(
					'status'        => 'success',
					'order_details' => $order_details,
				);
			}
		}

		return null;
	}

	public function register_rest_update_tracking() {
		register_rest_route(
			'trackfree-wc/v1',
			'order/(?P<order_id>\\d+)',
			array(
				'methods'             => 'POST',
				'callback'            => array( $this, 'rest_update_tracking_details' ),
				'permission_callback' => array( $this, 'rest_permission_api_key' ),
			)
		);
	}

	public function rest_update_tracking_details( $data ) {
		$order_id          = $data['order_id'];
		$request_api_key   = $data['api_key'];
		$tracking_number   = $data['tracking_number'];
		$tracking_status   = $data['tracking_status'];
		$estimated_delivery = $data['estimated_delivery'];
		$delivered_date    = $data['delivered_date'];

		$shipment_details          = get_post_meta( $order_id, '_trackfree_shipment_details', true );
		$trackfree_account_api_key = get_option( 'trackfree_account_api_key' );

		if ( $trackfree_account_api_key == $request_api_key ) {
			if ( $shipment_details ) {
				$track_details = array();
				foreach ( $shipment_details as $key => $shipment_values ) {
					if ( $shipment_values['tracking_num'] == $tracking_number ) {
						$track_details[ $key ] = array(
							'tracking_num'       => $shipment_values['tracking_num'],
							'courier_name'       => $shipment_values['courier_name'],
							'status'             => $tracking_status ? $tracking_status : $shipment_values['status'],
							'estimated_delivery' => $estimated_delivery,
							'delivered_date'     => $delivered_date,
							'fulfilment_items'   => $shipment_values['fulfilment_items'],
						);
					} else {
						$track_details[ $key ] = array(
							'tracking_num'       => $shipment_values['tracking_num'],
							'courier_name'       => $shipment_values['courier_name'],
							'status'             => $shipment_values['status'],
							'estimated_delivery' => $shipment_values['estimated_delivery'],
							'delivered_date'     => $shipment_values['delivered_date'],
							'fulfilment_items'   => $shipment_values['fulfilment_items'],
						);
					}
				}

				update_post_meta( $order_id, '_trackfree_shipment_details', wc_clean( $track_details ) );

				if ( get_option( 'trackfree_auto_order_status_update' ) == 1 ) {
					trackfree_update_order_status( $track_details, $order_id );
				}
			}
		}

		return null;
	}

	public function register_rest_theme_styles() {
		register_rest_route(
			'trackfree-wc/v1',
			'theme-styles',
			array(
				array(
					'methods'             => 'GET',
					'callback'            => array( $this, 'rest_get_theme_styles' ),
					'permission_callback' => '__return_true',
				),
				array(
					'methods'             => 'POST',
					'callback'            => array( $this, 'rest_update_theme_styles' ),
					'permission_callback' => '__return_true',
				),
			)
		);
	}

	public function rest_get_theme_styles() {
		return rest_ensure_response( $this->capture_theme_details( 'rest' ) );
	}

	public function rest_update_theme_styles( $request ) {
		$params   = $request->get_json_params();
		$computed = isset( $params['computed'] ) && is_array( $params['computed'] ) ? $params['computed'] : array();
		$stored   = $this->sanitize_computed_theme_styles( $computed );

		update_option( 'trackfree_theme_capture_computed_styles', $stored, false );
		update_option( 'trackfree_theme_capture_computed_styles_captured_at', current_time( 'mysql' ), false );

		return rest_ensure_response(
			array(
				'status'   => 'success',
				'computed' => $stored,
			)
		);
	}

	public function activation() {
		$api_key = get_option( 'trackfree_account_api_key' );
		if ( $api_key ) {
			$this->notify_remote_activation( true );
			$this->send_theme_capture( 'activation', false );
		}
	}

	private function notify_remote_activation( $blocking = false ) {
		$api_key = get_option( 'trackfree_account_api_key' );
		if ( ! $api_key ) {
			return false;
		}

		if ( get_option( 'trackfree_remote_activation_sent' ) ) {
			return true;
		}

		$response = wp_remote_post(
			$this->trackfree_url() . '/api/wc_plugin_activation?key=' . $api_key,
			array(
				'sslverify' => tfree_sslverify(),
				'timeout'   => $blocking ? 12 : 3,
				'blocking'  => (bool) $blocking,
			)
		);

		if ( ! is_wp_error( $response ) ) {
			update_option( 'trackfree_remote_activation_sent', 1, false );
			return true;
		}

		return false;
	}

	private function send_theme_capture_once( $reason ) {
		if ( get_option( 'trackfree_theme_capture_confirmed' ) ) {
			return;
		}

		$last_attempt = (int) get_option( 'trackfree_theme_capture_last_attempt' );
		if ( $last_attempt && $last_attempt > time() - HOUR_IN_SECONDS ) {
			return;
		}

		$this->send_theme_capture( $reason, true );
	}

	public function send_scheduled_theme_capture( $reason = 'scheduled' ) {
		$this->send_theme_capture( $reason, false );
	}

	public function send_theme_capture_now( $reason = 'manual', $force_apply = false ) {
		$this->send_theme_capture( $reason, true, $force_apply );
	}

	private function send_theme_capture( $reason = 'manual', $blocking = false, $force_apply = false ) {
		$api_key = get_option( 'trackfree_account_api_key' );
		if ( ! $api_key ) {
			return;
		}

		$this->notify_remote_activation( (bool) $blocking );

		$payload        = $this->capture_theme_details( $reason );
		$payload['key'] = $api_key;
		$payload['force_apply'] = $force_apply ? 1 : 0;
		update_option( 'trackfree_theme_capture_last_attempt', time(), false );

		$response = wp_remote_post(
			$this->trackfree_url() . '/api/wc_theme_capture',
			array(
				'sslverify' => tfree_sslverify(),
				'timeout'   => $blocking ? 12 : 5,
				'blocking'  => (bool) $blocking,
				'headers'   => array(
					'Content-Type' => 'application/json',
					'Accept'       => 'application/json',
				),
				'body'      => wp_json_encode( $payload ),
			)
		);

		if ( $blocking && ! is_wp_error( $response ) ) {
			$response_data = json_decode( wp_remote_retrieve_body( $response ), true );
			if ( is_array( $response_data ) && isset( $response_data['status'] ) && $response_data['status'] === 'success' ) {
				update_option( 'trackfree_theme_capture_sent', current_time( 'mysql' ), false );
				update_option( 'trackfree_theme_capture_confirmed', 1, false );
			}
		}
	}

	private function capture_theme_details( $reason ) {
		$wp_theme = wp_get_theme();

		return array(
			'reason'    => sanitize_key( $reason ),
			'captured_at' => current_time( 'mysql' ),
			'store'     => array(
				'name'     => get_bloginfo( 'name' ),
				'url'      => home_url( '/' ),
				'language' => get_locale(),
			),
			'wordpress' => array(
				'theme_name'    => $wp_theme ? $wp_theme->get( 'Name' ) : '',
				'theme_version' => $wp_theme ? $wp_theme->get( 'Version' ) : '',
				'theme_slug'    => $wp_theme ? $wp_theme->get_stylesheet() : '',
				'wp_version'    => get_bloginfo( 'version' ),
				'wc_version'    => defined( 'WC_VERSION' ) ? WC_VERSION : '',
			),
			'assets'    => array(
				'logo_url'    => $this->get_site_logo_url(),
				'favicon_url' => $this->get_site_favicon_url(),
			),
			'theme'     => array(
				'colors' => array(
					'palette'     => $this->get_theme_json_palette(),
					'customizer'  => $this->get_theme_mod_color_candidates(),
					'woocommerce' => $this->get_woocommerce_color_candidates(),
				),
				'fonts'  => $this->get_theme_font_candidates(),
			),
			'computed'  => $this->get_computed_theme_styles(),
		);
	}

	private function get_computed_theme_styles() {
		$computed = get_option( 'trackfree_theme_capture_computed_styles', array() );
		return is_array( $computed ) ? $computed : array();
	}

	private function sanitize_computed_theme_styles( $computed ) {
		$allowed_sections = array( 'body', 'header', 'primaryCta' );
		$allowed_keys     = array(
			'text',
			'backgroundColor',
			'color',
			'headingColor',
			'mainHeadingColor',
			'borderColor',
			'borderRadius',
			'fontFamily',
			'fontSize',
		);
		$sanitized        = array();

		foreach ( $allowed_sections as $section ) {
			if ( empty( $computed[ $section ] ) || ! is_array( $computed[ $section ] ) ) {
				continue;
			}

			$sanitized[ $section ] = array();
			foreach ( $allowed_keys as $key ) {
				if ( ! isset( $computed[ $section ][ $key ] ) ) {
					continue;
				}
				$sanitized[ $section ][ $key ] = sanitize_text_field( (string) $computed[ $section ][ $key ] );
			}
		}

		return $sanitized;
	}

	public function render_theme_capture_script() {
		if ( is_admin() || wp_doing_ajax() || ! get_option( 'trackfree_account_api_key' ) || (int) get_option( 'trackfree_account_verify' ) !== 1 ) {
			return;
		}
		?>
		<script>
			(function () {
				if (window.__trackfreeThemeCaptureLoaded) return;
				window.__trackfreeThemeCaptureLoaded = true;

				const endpoint = <?php echo wp_json_encode( rest_url( 'trackfree-wc/v1/theme-styles' ) ); ?>;
				const normalize = (value) => (value || '').toString().trim();
				const getStyle = (el) => el ? window.getComputedStyle(el) : null;
				const getText = (el) => normalize(el && el.textContent);
				const isTransparentColor = (value) => {
					const color = normalize(value).toLowerCase();
					return !color || color === 'transparent' || color === 'rgba(0, 0, 0, 0)' || color === 'rgba(0,0,0,0)';
				};
				const firstVisible = (selectors, predicate) => {
					for (const selector of selectors) {
						const nodes = document.querySelectorAll(selector);
						for (const node of nodes) {
							const rect = node.getBoundingClientRect();
							const style = getStyle(node);
							if (!style || style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity) === 0) continue;
							if (rect.width < 40 || rect.height < 20) continue;
							if (predicate && !predicate(node, style, rect)) continue;
							return node;
						}
					}
					return null;
				};

				const pickPrimaryCta = () => {
					const isLikelyPrimaryCta = (node, style, rect) => {
						if (!node || !style || !rect) return false;
						if (rect.width < 80 || rect.height < 28) return false;
						if (normalize(node.textContent).length < 3) return false;
						if (node.closest('header, nav, [role="banner"], [role="navigation"], .site-header, .header, #header')) return false;
						if (isTransparentColor(style.backgroundColor)) return false;
						return true;
					};

					const wooSelectors = [
						'.single-product form.cart .single_add_to_cart_button',
						'.single-product .summary button.single_add_to_cart_button',
						'.woocommerce div.product form.cart .button.alt',
						'.woocommerce-page div.product form.cart .button.alt',
						'main .single_add_to_cart_button',
						'main .add_to_cart_button',
						'main .button.alt'
					];
					const wooButton = firstVisible(wooSelectors, isLikelyPrimaryCta);
					if (wooButton) return wooButton;

					const heroSelectors = [
						'.wp-block-cover .wp-block-button__link',
						'.wp-block-group .wp-block-button__link',
						'main .wp-element-button',
						'main .wp-block-button__link',
						'main .button',
						'main .btn',
						'main button',
						'main a[role="button"]'
					];
					const heroButton = firstVisible(heroSelectors, isLikelyPrimaryCta);
					if (heroButton) return heroButton;

					return firstVisible([
						'.wp-block-button__link',
						'.wp-element-button',
						'.button',
						'.btn',
						'button',
						'a[role="button"]'
					], isLikelyPrimaryCta);
				};

				const collect = () => {
					const body = document.body;
					const header = firstVisible(['header', '[role="banner"]', '.site-header', '.header', '#header', 'nav.navigation', 'nav']);
					const primaryCta = pickPrimaryCta();
					const findHeading = () => {
						const selectors = [
							'main h1',
							'main .entry-title',
							'main .page-title',
							'#primary h1',
							'#content h1',
							'.site-main h1',
							'.content-area h1',
							'.entry-title',
							'.page-title',
							'main h2',
							'.wp-block-heading',
							'h1',
							'h2'
						];

						for (const selector of selectors) {
							const nodes = document.querySelectorAll(selector);
							for (const node of nodes) {
								if (!node || (header && header.contains(node))) continue;
								const rect = node.getBoundingClientRect();
								const style = getStyle(node);
								if (!style || style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity) === 0) continue;
								if (rect.width < 60 || rect.height < 24) continue;
								if (rect.top > window.innerHeight * 0.9) continue;
								return node;
							}
						}

						return null;
					};
					const heading = findHeading();

					const pick = (el) => {
						const style = getStyle(el);
						if (!style) return null;
						return {
							text: getText(el),
							backgroundColor: normalize(style.backgroundColor),
							color: normalize(style.color),
							borderColor: normalize(style.borderColor),
							borderRadius: normalize(style.borderRadius),
							fontFamily: normalize(style.fontFamily),
							fontSize: normalize(style.fontSize),
						};
					};

					const bodyStyles = pick(body) || {};
					if (heading) {
						const headingStyle = getStyle(heading);
						if (headingStyle) {
							const headingColor = normalize(headingStyle.color);
							const bodyBackground = normalize(getStyle(body)?.backgroundColor);
							if (headingColor && headingColor !== bodyBackground && headingColor !== 'rgb(255, 255, 255)') {
								bodyStyles.headingColor = headingColor;
								bodyStyles.mainHeadingColor = headingColor;
							}
						}
					}

					return {
						computed: {
							body: bodyStyles,
							header: pick(header),
							primaryCta: pick(primaryCta)
						}
					};
				};

				const send = () => {
					const payload = collect();
					fetch(endpoint, {
						method: 'POST',
						credentials: 'same-origin',
						headers: {
							'Content-Type': 'application/json'
						},
						body: JSON.stringify(payload)
					}).catch(function () {});
				};

				const run = function () {
					const fontsReady = document.fonts && document.fonts.ready ? document.fonts.ready.catch(function () {}) : Promise.resolve();
					fontsReady.finally(function () {
						window.setTimeout(send, 800);
					});
				};

				if (document.readyState === 'complete') {
					run();
				} else {
					window.addEventListener('load', run, { once: true });
				}
			}());
		</script>
		<?php
	}

	private function get_site_logo_url() {
		$custom_logo_id = (int) get_theme_mod( 'custom_logo' );
		if ( $custom_logo_id ) {
			$logo_url = wp_get_attachment_image_url( $custom_logo_id, 'full' );
			if ( $logo_url ) {
				return esc_url_raw( $logo_url );
			}
		}

		$theme_mods = get_theme_mods();
		if ( is_array( $theme_mods ) ) {
			foreach ( array( 'site_logo', 'logo', 'custom_logo_url' ) as $key ) {
				if ( empty( $theme_mods[ $key ] ) ) {
					continue;
				}
				if ( is_numeric( $theme_mods[ $key ] ) ) {
					$logo_url = wp_get_attachment_image_url( (int) $theme_mods[ $key ], 'full' );
					if ( $logo_url ) {
						return esc_url_raw( $logo_url );
					}
				}
				if ( is_string( $theme_mods[ $key ] ) && filter_var( $theme_mods[ $key ], FILTER_VALIDATE_URL ) ) {
					return esc_url_raw( $theme_mods[ $key ] );
				}
			}
		}

		return '';
	}

	private function get_site_favicon_url() {
		$favicon_url = function_exists( 'get_site_icon_url' ) ? get_site_icon_url( 512 ) : '';
		return $favicon_url ? esc_url_raw( $favicon_url ) : '';
	}

	private function get_theme_json_palette() {
		if ( ! function_exists( 'wp_get_global_settings' ) ) {
			return array();
		}

		$settings = wp_get_global_settings();
		$palette  = array();
		if ( isset( $settings['color']['palette']['theme'] ) && is_array( $settings['color']['palette']['theme'] ) ) {
			$palette = $settings['color']['palette']['theme'];
		} elseif ( isset( $settings['color']['palette']['default'] ) && is_array( $settings['color']['palette']['default'] ) ) {
			$palette = $settings['color']['palette']['default'];
		}

		return array_values(
			array_filter(
				array_map(
					function ( $item ) {
						if ( ! is_array( $item ) || empty( $item['color'] ) ) {
							return null;
						}
						return array(
							'name'  => isset( $item['name'] ) ? sanitize_text_field( $item['name'] ) : '',
							'slug'  => isset( $item['slug'] ) ? sanitize_key( $item['slug'] ) : '',
							'color' => sanitize_text_field( $item['color'] ),
						);
					},
					$palette
				)
			)
		);
	}

	private function get_theme_mod_color_candidates() {
		$theme_mods = get_theme_mods();
		if ( ! is_array( $theme_mods ) ) {
			return array();
		}

		$colors = array();
		foreach ( $theme_mods as $key => $value ) {
			if ( ! is_scalar( $value ) ) {
				continue;
			}
			$key_string = (string) $key;
			if ( stripos( $key_string, 'color' ) === false && stripos( $key_string, 'background' ) === false ) {
				continue;
			}
			$value = trim( (string) $value );
			if ( $value === '' ) {
				continue;
			}
			if ( preg_match( '/^[0-9a-f]{3,6}$/i', $value ) ) {
				$value = '#' . $value;
			}
			if ( preg_match( '/^#([0-9a-f]{3}|[0-9a-f]{6})$/i', $value ) || preg_match( '/^rgba?\(/i', $value ) ) {
				$colors[ sanitize_key( $key_string ) ] = sanitize_text_field( $value );
			}
		}

		return $colors;
	}

	private function get_woocommerce_color_candidates() {
		$keys   = array(
			'woocommerce_primary',
			'woocommerce_secondary',
			'woocommerce_highlight',
			'woocommerce_content_bg',
			'woocommerce_subtext',
		);
		$colors = array();

		foreach ( $keys as $key ) {
			$value = get_option( $key );
			if ( ! is_string( $value ) || $value === '' ) {
				continue;
			}
			$colors[ $key ] = sanitize_text_field( $value );
		}

		return $colors;
	}

	private function get_theme_font_candidates() {
		$fonts = array(
			'body'    => '',
			'heading' => '',
		);

		$theme_mods = get_theme_mods();
		if ( is_array( $theme_mods ) ) {
			foreach ( $theme_mods as $key => $value ) {
				if ( ! is_scalar( $value ) || trim( (string) $value ) === '' ) {
					continue;
				}
				$key_string = strtolower( (string) $key );
				if ( $fonts['body'] === '' && ( strpos( $key_string, 'body_font' ) !== false || strpos( $key_string, 'base_font' ) !== false ) ) {
					$fonts['body'] = sanitize_text_field( (string) $value );
				}
				if ( $fonts['heading'] === '' && ( strpos( $key_string, 'heading_font' ) !== false || strpos( $key_string, 'header_font' ) !== false ) ) {
					$fonts['heading'] = sanitize_text_field( (string) $value );
				}
			}
		}

		if ( function_exists( 'wp_get_global_settings' ) ) {
			$settings = wp_get_global_settings();
			if ( isset( $settings['typography']['fontFamilies']['theme'] ) && is_array( $settings['typography']['fontFamilies']['theme'] ) ) {
				foreach ( $settings['typography']['fontFamilies']['theme'] as $font_family ) {
					if ( ! is_array( $font_family ) || empty( $font_family['fontFamily'] ) ) {
						continue;
					}
					if ( $fonts['body'] === '' ) {
						$fonts['body'] = sanitize_text_field( $font_family['fontFamily'] );
					}
					if ( $fonts['heading'] === '' ) {
						$fonts['heading'] = sanitize_text_field( $font_family['fontFamily'] );
					}
					break;
				}
			}
		}

		return $fonts;
	}

	public function uninstall() {
		$api_key = get_option( 'trackfree_account_api_key' );
		if ( $api_key ) {
			wp_remote_post(
					$this->trackfree_url() . '/api/wc_plugin_uninstall?key=' . $api_key,
					array(
						'sslverify' => tfree_sslverify(),
						'timeout'   => 3,
						'blocking'  => false,
					)
				);
			}

			delete_option( 'trackfree_account_api_key' );
			delete_option( 'trackfree_account_verify' );
			delete_option( 'trackfree_preferred_couriers' );
			delete_option( 'trackfree_tracking_domain' );
			delete_option( 'trackfree_shipment_status_in_orders' );
			delete_option( 'trackfree_shipment_details_in_order_details' );
			delete_option( 'trackfree_auto_order_status_update' );
			delete_option( 'trackfree_show_intransit_badge' );
			delete_option( 'trackfree_track_page_id' );
			delete_option( 'trackfree_hide_quick_start_info' );
			delete_option( 'trackfree_is_custom_track_url' );
			delete_option( 'trackfree_internal_email_link' );
			delete_option( 'trackfree_theme_capture_last_attempt' );
			delete_option( 'trackfree_theme_capture_sent' );
			delete_option( 'trackfree_theme_capture_confirmed' );
			delete_option( 'trackfree_theme_capture_computed_styles' );
			delete_option( 'trackfree_theme_capture_computed_styles_captured_at' );
			delete_option( 'trackfree_remote_activation_sent' );

			delete_option( 'trackfree_display_options' );
			delete_option( 'trackfree_trans_strings' );
			delete_option( 'trackfree_date_time_formats' );
			delete_option( 'trackfree_translate_strings' );
			delete_option( 'trackfree_additional_texts' );
			delete_option( 'trackfree_custom_css_and_html' );

			delete_option( 'trackfree_option_name' );

			delete_transient( 'trackfree_shipment_count' );
		}

	public function load_textdomain() {
		load_plugin_textdomain( 'trackfree-woocommerce-tracking', false, basename( dirname( $this->plugin_file ) ) . '/languages/' );
	}

	public function admin_footer_text( $text ) {
		if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'trackfree-getting-started', 'trackfree' ), true ) ) {
			return 'Thank you for using TrackFree!';
		}
		return $text;
	}

	public function admin_body_class( $classes ) {
		if ( isset( $_GET['page'] ) && in_array( $_GET['page'], array( 'trackfree-getting-started', 'trackfree' ), true ) ) {
			$classes .= ' trackfree-admin-body trackfree-admin-wrap';
		}
		return $classes;
	}

	public function admin_menu() {
		$trackfree_icon = '<svg width="83" height="75" viewBox="0 0 83 75" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M42.3221 6.00889C39.0566 5.93791 35.8977 6.29284 32.8807 7.03821L32.8686 7.07354C18.1216 10.7281 6.98279 23.6116 6.06174 39.4193C6.03844 39.7951 6.02205 40.1713 6.01357 40.5475L6.01179 40.6154L6.01049 40.6796C5.85557 46.9769 7.42037 53.2094 10.4699 58.7015C10.6582 59.0409 10.8522 59.3775 11.0519 59.711C13.7317 64.1478 18.2838 66.4194 22.8314 66.4726C22.9735 66.4743 23.1156 66.4738 23.2577 66.4711C27.3129 66.395 31.3179 64.5519 33.9402 60.9042C29.5982 53.5706 24.6775 44.1526 24.6775 39.1365C24.6775 30.0502 32.0652 22.6584 41.1451 22.6584L41.1452 22.6585C50.2256 22.6585 57.6127 30.0508 57.6105 39.1343C57.6105 44.0346 52.9118 53.1389 48.646 60.395C54.0089 68.7618 66.4242 68.5458 71.6753 60.1015C73.6431 56.9243 75.09 53.4631 75.9682 49.8545L76.0057 49.8437C76.6446 47.2172 76.964 44.5197 76.9998 41.7866C77.0173 36.9802 76.0752 32.382 74.3534 28.1781C69.1458 15.4629 56.8064 6.35566 42.3221 6.00889ZM33.7422 39.1359C33.7422 43.2197 37.0641 46.5436 41.1451 46.5436C45.2285 46.5436 48.5502 43.22 48.548 39.1342C48.548 35.0504 45.2283 31.7266 41.1451 31.7266C37.0639 31.7266 33.7422 35.0501 33.7422 39.1359Z" fill="url(#paint0_linear)"/><defs><linearGradient id="paint0_linear" x1="35.0196" y1="62.6697" x2="3.94619" y2="36.4729" gradientUnits="userSpaceOnUse"><stop stop-color="#EDF3FB"/><stop offset="1" stop-color="#EDF3FB"/></linearGradient></defs></svg>';

		$api_key = get_option( 'trackfree_account_api_key' );
		$verify  = get_option( 'trackfree_account_verify' );

		if ( $api_key && (int) $verify === 1 ) {
			$badge = '';
			if ( get_option( 'trackfree_show_intransit_badge' ) === '1' ) {
				$shipment_count = $this->get_shipment_count();
				$badge          = $shipment_count > 0 ? " <span class='update-plugins count-{$shipment_count}'><span class='plugin-count'>" . esc_html( $shipment_count > 99 ? '99+' : $shipment_count ) . '</span></span>' : '';
			}

			add_menu_page(
				'TrackFree',
				'TrackFree' . $badge,
				'manage_options',
				'trackfree',
				array( $this, 'render_admin_root' ),
				'data:image/svg+xml;base64,' . base64_encode( $trackfree_icon ),
				25
			);

			add_submenu_page( 'trackfree', 'Home - TrackFree', 'Home', 'manage_options', 'trackfree#/home', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', 'Tracking Page - TrackFree', 'Tracking Page', 'manage_options', 'trackfree#/tracking-page', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', 'Shipments - TrackFree', 'Shipments', 'manage_options', 'trackfree#/shipments', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', 'Settings - TrackFree', 'Settings', 'manage_options', 'trackfree#/settings', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', 'Analytics - TrackFree', 'Analytics', 'manage_options', 'trackfree#/analytics', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', 'Account - TrackFree', 'Billing', 'manage_options', 'trackfree#/account', array( $this, 'render_admin_root' ) );

			remove_submenu_page( 'trackfree', 'trackfree' );
		} else {
			add_menu_page( 'TrackFree', 'TrackFree', 'manage_options', 'trackfree-getting-started', 'trackfree_settings_page', 'data:image/svg+xml;base64,' . base64_encode( $trackfree_icon ), 25 );
		}
	}

	private function get_shipment_count() {
		$transient_key = 'trackfree_shipment_count';
		$current_page  = isset( $_GET['page'] ) ? sanitize_text_field( wp_unslash( $_GET['page'] ) ) : '';

		if ( $current_page === 'trackfree' ) {
			delete_transient( $transient_key );
			$this->fetch_and_store_shipment_count();
		}

		$count = get_transient( $transient_key );

		if ( $count === false ) {
			$this->fetch_and_store_shipment_count();
			$count = get_transient( $transient_key );
		}

		return (int) $count;
	}

	private function fetch_and_store_shipment_count() {
		$api_key = get_option( 'trackfree_account_api_key' );
		if ( ! $api_key ) {
			return;
		}

		$response = wp_remote_get(
			$this->trackfree_url() . '/api/wc_active_shipments?key=' . $api_key,
			array(
				'sslverify' => tfree_sslverify(),
				'timeout'   => 15,
			)
		);

		$shipment_data = json_decode( wp_remote_retrieve_body( $response ), true );
		if ( isset( $shipment_data['status'] ) && $shipment_data['status'] === 'success' ) {
			set_transient( 'trackfree_shipment_count', (int) $shipment_data['count'], 30 * MINUTE_IN_SECONDS );
		}
	}

	public function render_admin_root() {
		echo '<div id="root"></div>';
	}

	public function get_category_by_id( $category_id ) {
		$term = get_term_by( 'id', $category_id, 'product_cat', 'ARRAY_A' );
		return $term['name'] ?? '';
	}

	private function verify_admin_ajax_request() {
		$allowed = current_user_can( 'manage_woocommerce' ) || current_user_can( 'manage_options' );
		if ( ! $allowed ) {
			wp_die( '', '', array( 'response' => 403 ) );
		}

		$nonce = '';
		if ( isset( $_SERVER['HTTP_X_WP_NONCE'] ) ) {
			$nonce = wp_unslash( $_SERVER['HTTP_X_WP_NONCE'] );
		} elseif ( isset( $_REQUEST['_wpnonce'] ) ) {
			$nonce = wp_unslash( $_REQUEST['_wpnonce'] );
		}
		$nonce = is_string( $nonce ) ? sanitize_text_field( $nonce ) : '';

		if ( $nonce === '' || ! wp_verify_nonce( $nonce, 'tfree_nonce' ) ) {
			wp_die( '', '', array( 'response' => 403 ) );
		}
	}

	public function ajax_update_shipment() {
		$this->verify_admin_ajax_request();
			$trackfree_account_api_key = get_option( 'trackfree_account_api_key' );
			$ord_id                    = isset( $_POST['ord_id'] ) ? sanitize_text_field( wp_unslash( $_POST['ord_id'] ) ) : '';
			$shipment_id               = isset( $_POST['shipment_id'] ) ? sanitize_text_field( wp_unslash( $_POST['shipment_id'] ) ) : '';

			$shipment_details = get_post_meta( $ord_id, '_trackfree_shipment_details', true );
			$shipment_values  = isset( $shipment_details[ $shipment_id ] ) ? $shipment_details[ $shipment_id ] : array();

			$is_tracking_modified  = 0;
			$existing_tracking_num = $shipment_values['tracking_num'] ?? '';
			$existing_courier_name = $shipment_values['courier_name'] ?? '';

			$tracking_num = isset( $_POST['trackfree_tracking_number'] ) ? sanitize_text_field( wp_unslash( $_POST['trackfree_tracking_number'] ) ) : '';
			$courier_name = isset( $_POST['trackfree_courier_name'] ) ? sanitize_text_field( wp_unslash( $_POST['trackfree_courier_name'] ) ) : '';

			if ( $existing_tracking_num != $tracking_num || $existing_courier_name != $courier_name ) {
				$is_tracking_modified = 1;
			}

			$fulfilment_items        = $shipment_values['fulfilment_items'] ?? array();
			$updated_fulfilment_items = isset( $_POST['fulfilment_items'] ) ? (array) $_POST['fulfilment_items'] : array(); // legacy JS posts nested arrays.

			foreach ( $fulfilment_items as $key => $item ) {
				$qty       = isset( $updated_fulfilment_items[ $key ]['quantity'] ) ? (int) $updated_fulfilment_items[ $key ]['quantity'] : 0;
				$total_qty = isset( $updated_fulfilment_items[ $key ]['total_quantity'] ) ? (int) $updated_fulfilment_items[ $key ]['total_quantity'] : 0;
				if ( $qty < 0 ) {
					$qty = 0;
				} elseif ( $qty > $total_qty ) {
					$qty = $total_qty;
				}
				$fulfilment_items[ $key ]['quantity'] = $qty;
			}

			if ( ! empty( $_POST['trackfree_order_status'] ) ) {
				$order = wc_get_order( $ord_id );
				if ( $order ) {
					$order->update_status( str_replace( 'wc-', '', sanitize_text_field( wp_unslash( $_POST['trackfree_order_status'] ) ) ) );
				}
			}

			$track_request = array(
				'key'                  => $trackfree_account_api_key,
				'order_id'             => $ord_id,
				'shipment_id'          => $shipment_id,
				'fulfilment_items'     => $shipment_details,
				'is_tracking_modified' => $is_tracking_modified,
				'tracking_num'         => $tracking_num,
				'courier_name'         => $courier_name,
				'existing_tracking_num' => $existing_tracking_num,
				'existing_courier_name' => $existing_courier_name,
			);

			$response_data = wp_remote_post(
				$this->trackfree_url() . '/api/wc_update_tracking',
				array(
					'sslverify' => tfree_sslverify(),
					'timeout'   => 15,
					'body'      => $track_request,
				)
			);

			if ( is_wp_error( $response_data ) ) {
				echo esc_html( $response_data->get_error_message() );
				wp_die();
			}

			$raw_body   = wp_remote_retrieve_body( $response_data );
			$track_data = json_decode( $raw_body, true );

			if ( $is_tracking_modified == 1 ) {
				if ( ! is_array( $track_data ) || ! isset( $track_data['status'] ) ) {
					$diagnostic = trim( wp_strip_all_tags( $raw_body ) );
					if ( $diagnostic !== '' ) {
						echo esc_html( $diagnostic );
					} else {
						echo esc_html__( 'TrackFree API returned an unexpected or empty response while updating the shipment.', 'trackfree-woocommerce-tracking' );
					}
					wp_die();
				}

				if ( $track_data['status'] == 'success' ) {
					$tf_courier_name = $courier_name;
					if ( ! $tf_courier_name ) {
						$tf_courier_name = $track_data['courier'];
					}

					$shipment_details[ $shipment_id ]['tracking_num']       = $tracking_num;
					$shipment_details[ $shipment_id ]['courier_name']       = $tf_courier_name;
					$shipment_details[ $shipment_id ]['status']             = '';
					$shipment_details[ $shipment_id ]['estimated_delivery'] = '';
					$shipment_details[ $shipment_id ]['delivered_date']     = '';
					$shipment_details[ $shipment_id ]['fulfilment_items']   = $fulfilment_items;

					update_post_meta( $ord_id, '_trackfree_shipment_details', wc_clean( $shipment_details ) );
					if ( get_option( 'trackfree_auto_order_status_update' ) == 1 ) {
						trackfree_update_order_status( $shipment_details, $ord_id );
					}
					echo 'success';
				} else {
					$this->echo_trackfree_api_message( $track_data, $raw_body );
				}
			} else {
				$shipment_details[ $shipment_id ]['fulfilment_items'] = $fulfilment_items;
				update_post_meta( $ord_id, '_trackfree_shipment_details', wc_clean( $shipment_details ) );
				if ( get_option( 'trackfree_auto_order_status_update' ) == 1 ) {
					trackfree_update_order_status( $shipment_details, $ord_id );
				}
				echo 'success';
			}
		wp_die();
	}

	private function echo_trackfree_api_message( $track_data, $raw_body ) {
		if ( ! is_array( $track_data ) ) {
			$diagnostic = trim( wp_strip_all_tags( $raw_body ) );
			echo esc_html( $diagnostic !== '' ? $diagnostic : __( 'Unexpected TrackFree API response.', 'trackfree-woocommerce-tracking' ) );
			return;
		}

		if ( isset( $track_data['message'] ) ) {
			switch ( $track_data['message'] ) {
				case 'already_exist':
					_e( 'This tracking number already exists', 'trackfree-woocommerce-tracking' );
					return;
				case 'limit_exceed':
					_e( 'You can add only up to 3 shipments', 'trackfree-woocommerce-tracking' );
					return;
				case 'invalid_user':
					_e( 'Invalid user', 'trackfree-woocommerce-tracking' );
					return;
				case 'credit_exceed':
					_e( 'Your credit limit is over. Please upgrade', 'trackfree-woocommerce-tracking' );
					return;
				case 'monthly_credit_exceed':
					$upgrade_url = admin_url( 'admin.php?page=trackfree#/account' );
						printf(
							__( 'You have exceeded your monthly credit usage. Upgrade to a higher plan to continue using TrackFree. You can upgrade <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'trackfree-woocommerce-tracking' ),
							esc_url( $upgrade_url )
						);
					return;
				case 'invalid_tracking':
					_e( 'Invalid tracking number', 'trackfree-woocommerce-tracking' );
					return;
				case 'courier_not_supported':
					_e( 'Courier not supported', 'trackfree-woocommerce-tracking' );
					return;
			}
		}

		if ( ! empty( $track_data['message'] ) ) {
			echo wp_kses_post( $track_data['message'] );
			return;
		}

		$diagnostic = trim( wp_strip_all_tags( $raw_body ) );
		echo esc_html( $diagnostic !== '' ? $diagnostic : __( 'TrackFree API reported an error but did not include a message.', 'trackfree-woocommerce-tracking' ) );
	}

	public function ajax_add_new_shipment() {
		$this->verify_admin_ajax_request();
			$fulfil_items      = isset( $_POST['fulfilment_items'] ) ? (array) $_POST['fulfilment_items'] : array();
			$fulfilment_items  = array();
			foreach ( $fulfil_items as $key => $item ) {
				$fulfilment_items_json = isset( $fulfil_items[ $key ]['order_items'] ) ? stripslashes( $fulfil_items[ $key ]['order_items'] ) : '';
				$fulfillment           = $fulfilment_items_json ? json_decode( $fulfilment_items_json, true ) : array();
				$available_qty         = isset( $fulfillment['quantity'] ) ? (int) $fulfillment['quantity'] : 0;
				$quantity              = isset( $item['quantity'] ) ? (int) $item['quantity'] : 0;
				if ( $quantity < 0 ) {
					$quantity = 0;
				} elseif ( $quantity > $available_qty ) {
					$quantity = $available_qty;
				}
				$fulfil_items[ $key ]['quantity'] = $quantity;
				$fulfilment_items[]              = array(
					'id'           => isset( $item['id'] ) ? sanitize_text_field( $item['id'] ) : '',
					'variation_id' => isset( $item['variation_id'] ) ? sanitize_text_field( $item['variation_id'] ) : '',
					'quantity'     => $quantity,
				);
			}

			$plugin_version = defined( 'TRACKFREE_VERSION' ) ? TRACKFREE_VERSION : '';

			$trackfree_account_api_key  = get_option( 'trackfree_account_api_key' );
			$ord_id                     = isset( $_POST['ord_id'] ) ? sanitize_text_field( wp_unslash( $_POST['ord_id'] ) ) : '';
			$trackfree_courier_name     = isset( $_POST['trackfree_courier_name'] ) ? sanitize_text_field( wp_unslash( $_POST['trackfree_courier_name'] ) ) : '';
			$raw_tracking               = isset( $_POST['trackfree_tracking_number'] ) ? wp_unslash( $_POST['trackfree_tracking_number'] ) : '';
			$trackfree_tracking_number  = sanitize_text_field( preg_replace( '/\\s+|[^a-zA-Z0-9\\-]/', '', $raw_tracking ) );

			if ( $trackfree_tracking_number ) {
				$order      = wc_get_order( $ord_id );
				$order_data = $order ? $order->get_data() : array();

				$first_name = $order_data['shipping']['first_name'] ? $order_data['shipping']['first_name'] : $order_data['billing']['first_name'];
				$last_name  = $order_data['shipping']['last_name'] ? $order_data['shipping']['last_name'] : $order_data['billing']['last_name'];

				$order_items  = array();
				$exclude_item = array();

				foreach ( $order->get_items() as $item_values ) {
					$item_data    = $item_values->get_data();
					$product_data = wc_get_product( $item_data['product_id'] );
					if ( ! empty( $product_data ) ) {
						$order_items[]  = array(
							'product_id' => $item_data['product_id'],
							'name'       => $product_data->get_name(),
							'price'      => $product_data->get_price(),
							'sku'        => $product_data->get_sku(),
							'quantity'   => $item_data['quantity'],
							'slug'       => $product_data->get_slug(),
							'image'      => tfree_get_product_image_url( $product_data, 'full', true ),
						);

						$exclude_item[] = $item_data['product_id'];
					}
				}

				list( $_exclude_ids, $_category_slugs, $_category_names ) = tfree_get_order_recommendation_context( $ord_id );
				$store_products     = tfree_get_recommended_product_ids( $_exclude_ids, $_category_slugs, $_category_names, 12 );
					$recommend_products = tfree_build_recommend_products_payload( $store_products, 4, 'full', 'slug' );

				$track_request = array(
					'key'             => $trackfree_account_api_key,
					'tracking_num'    => $trackfree_tracking_number,
					'courier_name'    => $trackfree_courier_name,
					'order_id'        => $order_data['id'],
					'order_number'    => $order_data['number'],
					'customer_email'  => $order_data['billing']['email'],
					'first_name'      => $first_name,
					'last_name'       => $last_name,
					'customer_phone'  => $order_data['billing']['phone'],
					'customer_country' => $order_data['billing']['country'],
					'order_currency'  => $order_data['currency'],
					'order_total'     => $order_data['total'],
					'order_created_at' => $order_data['date_created'] ? $order_data['date_created']->date( 'Y-m-d H:i:s' ) : '',
					'shipping_address_1' => $order_data['shipping']['address_1'],
					'shipping_address_2' => $order_data['shipping']['address_2'],
					'shipping_city'   => $order_data['shipping']['city'],
					'shipping_state'  => $order_data['shipping']['state'],
					'shipping_postcode' => $order_data['shipping']['postcode'],
					'shipping_country' => $order_data['shipping']['country'],
					'order_items'     => $order_items,
					'site_url'        => home_url(),
					'recommendProducts' => $recommend_products,
					'plugin_version'  => $plugin_version,
					'shipment_details' => get_post_meta( $ord_id, '_trackfree_shipment_details', true ),
					'fulfilment_items' => $fulfil_items,
				);

				$response_data = wp_remote_post(
					$this->trackfree_url() . '/api/wc_add_new_track',
					array(
						'sslverify' => tfree_sslverify(),
						'timeout'   => 15,
						'body'      => $track_request,
					)
				);

				if ( is_wp_error( $response_data ) ) {
					echo esc_html( $response_data->get_error_message() );
					wp_die();
				}

				$raw_body   = wp_remote_retrieve_body( $response_data );
				$track_data = json_decode( $raw_body, true );

				if ( ! is_array( $track_data ) || ! isset( $track_data['status'] ) ) {
					$diagnostic = trim( wp_strip_all_tags( $raw_body ) );
					if ( $diagnostic !== '' ) {
						echo esc_html( $diagnostic );
					} else {
						echo esc_html__( 'TrackFree API returned an unexpected or empty response while adding the shipment.', 'trackfree-woocommerce-tracking' );
					}
					wp_die();
				}

				if ( $track_data['status'] == 'success' ) {
					$tf_courier_name = $trackfree_courier_name;
					if ( ! $tf_courier_name ) {
						$tf_courier_name = $track_data['courier'];
					}

					$new_shipment[] = array(
						'tracking_num'       => $trackfree_tracking_number,
						'courier_name'       => $tf_courier_name,
						'status'             => '',
						'estimated_delivery' => '',
						'delivered_date'     => '',
						'fulfilment_items'   => $fulfilment_items,
					);

					$existing_shipments = get_post_meta( $ord_id, '_trackfree_shipment_details', true );
					if ( $existing_shipments ) {
						$shipments = array_merge( $existing_shipments, $new_shipment );
						update_post_meta( $ord_id, '_trackfree_shipment_details', wc_clean( $shipments ) );
						if ( get_option( 'trackfree_auto_order_status_update' ) == 1 ) {
							trackfree_update_order_status( $shipments, $ord_id );
						}
					} else {
						update_post_meta( $ord_id, '_trackfree_shipment_details', wc_clean( $new_shipment ) );
						if ( get_option( 'trackfree_auto_order_status_update' ) == 1 ) {
							trackfree_update_order_status( $new_shipment, $ord_id );
						}
					}

					if ( ! empty( $_POST['trackfree_order_status'] ) && $order ) {
						$order->update_status( str_replace( 'wc-', '', sanitize_text_field( wp_unslash( $_POST['trackfree_order_status'] ) ) ) );
					}

					echo 'success';
				} else {
					$this->echo_trackfree_api_message( $track_data, $raw_body );
				}
			}

		wp_die();
	}

	public function add_shipment_status_column( $columns ) {
		$new_columns = array();
		foreach ( (array) $columns as $key => $column ) {
			$new_columns[ $key ] = $column;
			if ( $key == 'order_status' ) {
				$new_columns['shipment_status'] = __( 'Shipment Status', 'trackfree-woocommerce-tracking' );
			}
		}
		return $new_columns;
	}

	public function render_order_list_custom_column_hpos( $column, $order ) {
		if ( 'shipment_status' !== $column ) {
			return;
		}
		$post_id = $order->get_id();
		$this->render_shipment_status_cell( $post_id );
	}

	public function render_order_list_custom_column_legacy( $column, $post_id ) {
		if ( 'shipment_status' !== $column ) {
			return;
		}
		$this->render_shipment_status_cell( $post_id );
	}

		private function render_shipment_status_cell( $post_id ) {
			$shipment_details = get_post_meta( $post_id, '_trackfree_shipment_details', true );
			$i               = 0;
			if ( ! $shipment_details ) {
				return;
			}

			$modal_id   = 'trackfree-shipment-popup-' . $post_id;
			$content_id = 'trackfree-shipment-content-' . $post_id;

			if ( $this->has_incomplete_shipments( $shipment_details ) ) {
				?>
				<a href="javascript:void(0);" id="<?php echo esc_attr( $post_id ); ?>" class="js-open-modal" data-modal-id="<?php echo esc_attr( $modal_id ); ?>" title="Click to show current status">
					<img src="https://tfree.sfo2.cdn.digitaloceanspaces.com/default/tf-wp-shipment-preview.png" alt="Shipment Status"/>
				</a>
				<?php
			} else {
				foreach ( $shipment_details as $shipment_values ) {
					if ( 0 === $i ) {
						echo '<span style="color: #5b841b;">' . ( $shipment_values['status'] ?? '' ) . '</span><br>' . ( $shipment_values['delivered_date'] ?? '' );
					}
					$i++;
				}
			}

			?>
			<div id="<?php echo esc_attr( $modal_id ); ?>" class="trackfree-modal-box" role="dialog" aria-modal="true" aria-labelledby="trackfree-shipment-title-<?php echo esc_attr( $post_id ); ?>">
				<header>
					<h3 id="trackfree-shipment-title-<?php echo esc_attr( $post_id ); ?>"><?php _e( 'Shipment Status', 'trackfree-woocommerce-tracking' ); ?></h3>
					<a href="javascript:void(0);" class="trackfree-modal-close trackfree-close" aria-label="<?php esc_attr_e( 'Close', 'trackfree-woocommerce-tracking' ); ?>">&times;</a>
				</header>
				<div class="modal-body">
					<div id="<?php echo esc_attr( $content_id ); ?>"></div>
				</div>
				<footer>
					<a href="javascript:void(0);" class="trackfree-modal-close"><?php _e( 'Close', 'trackfree-woocommerce-tracking' ); ?></a>
				</footer>
			</div>
			<?php
		}

	private function has_incomplete_shipments( $shipments ) {
		foreach ( (array) $shipments as $val ) {
			if ( ( $val['status'] ?? '' ) !== 'Delivered' ) {
				return 1;
			}
		}
		return 0;
	}

	public function ajax_tracking_delete() {
		$this->verify_admin_ajax_request();
			$order_id        = isset( $_POST['order_id'] ) ? sanitize_text_field( wp_unslash( $_POST['order_id'] ) ) : '';
			$track_id        = isset( $_POST['track_id'] ) ? sanitize_text_field( wp_unslash( $_POST['track_id'] ) ) : '';
			$shipment_details = get_post_meta( $order_id, '_trackfree_shipment_details', true );
			$api_key         = get_option( 'trackfree_account_api_key' );
			$track_data      = array(
				'tracking_num' => $shipment_details[ $track_id ]['tracking_num'] ?? '',
			);

			wp_remote_get(
				$this->trackfree_url() . '/api/wc_delete_tracking?key=' . $api_key,
				array(
					'sslverify' => tfree_sslverify(),
					'timeout'   => 15,
					'body'      => $track_data,
				)
			);

			if ( is_array( $shipment_details ) && isset( $shipment_details[ $track_id ] ) ) {
				unset( $shipment_details[ $track_id ] );
			}
			update_post_meta( $order_id, '_trackfree_shipment_details', $shipment_details );

			$get_shipment_details = get_post_meta( $order_id, '_trackfree_shipment_details', true );
			$total_shipments      = $get_shipment_details ? sizeof( $get_shipment_details ) : 0;
			echo $total_shipments;
		wp_die();
	}
}
