<?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_action( 'admin_footer', array( $this, 'render_admin_theme_capture_warmup' ), 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 render_admin_theme_capture_warmup() {
		if (
			! $this->is_trackfree_admin_page()
			|| ! get_option( 'trackfree_account_api_key' )
			|| (int) get_option( 'trackfree_account_verify' ) !== 1
			|| ! empty( $this->get_computed_theme_styles() )
		) {
			return;
		}

		$warmup_url = add_query_arg(
			array(
				'trackfree_theme_capture' => '1',
			),
			home_url( '/' )
		);
		?>
		<script>
			(function () {
				if (window.__trackfreeThemeCaptureWarmupLoaded) return;
				window.__trackfreeThemeCaptureWarmupLoaded = true;

				const iframe = document.createElement('iframe');
				iframe.src = <?php echo wp_json_encode( esc_url_raw( $warmup_url ) ); ?>;
				iframe.setAttribute('aria-hidden', 'true');
				iframe.tabIndex = -1;
				iframe.style.position = 'fixed';
				iframe.style.width = '1px';
				iframe.style.height = '1px';
				iframe.style.opacity = '0';
				iframe.style.pointerEvents = 'none';
				iframe.style.left = '-9999px';
				iframe.style.bottom = '0';
				document.body.appendChild(iframe);

				window.setTimeout(function () {
					iframe.remove();
				}, 10000);
			}());
		</script>
		<?php
	}

	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.f867f041.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 );
		$existing = $this->get_computed_theme_styles();
		$new_score = isset( $stored['meta']['score'] ) ? (int) $stored['meta']['score'] : 0;
		$existing_score = isset( $existing['meta']['score'] ) ? (int) $existing['meta']['score'] : 0;
		$new_version = isset( $stored['meta']['captureVersion'] ) ? (int) $stored['meta']['captureVersion'] : 0;
		$existing_version = isset( $existing['meta']['captureVersion'] ) ? (int) $existing['meta']['captureVersion'] : 0;

		if ( ! empty( $existing ) && $existing_score >= 4 && $existing_version >= $new_version ) {
			return rest_ensure_response(
				array(
					'status'   => 'ignored_existing_capture',
					'computed' => $existing,
				)
			);
		}

		if ( ! empty( $existing ) && $existing_score > $new_score && $new_score < 4 ) {
			return rest_ensure_response(
				array(
					'status'   => 'ignored_low_quality_page',
					'computed' => $existing,
				)
			);
		}

		$changed = wp_json_encode( $existing ) !== wp_json_encode( $stored );

		update_option( 'trackfree_theme_capture_computed_styles', $stored, false );
		update_option( 'trackfree_theme_capture_computed_styles_captured_at', current_time( 'mysql' ), false );
		if ( $changed ) {
			$this->send_theme_capture( 'computed_styles_updated', 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', 'footer', 'primaryCta', 'input', 'card', 'meta' );
		$allowed_keys     = array(
			'text',
			'backgroundColor',
			'color',
			'headingColor',
			'mainHeadingColor',
			'borderColor',
			'borderRadius',
			'fontFamily',
			'fontSize',
			'url',
			'title',
			'summary',
			'score',
			'isHome',
			'isCommerce',
			'isSearchLike',
			'isNotFound',
			'captureVersion',
		);
		$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 ] );
			}
		}

		if ( ! empty( $computed['candidates'] ) && is_array( $computed['candidates'] ) ) {
			$sanitized['candidates'] = $this->sanitize_computed_theme_candidates( $computed['candidates'] );
		}

		return $sanitized;
	}

	private function sanitize_computed_theme_candidates( $candidates ) {
		$allowed_groups = array( 'headers', 'footers', 'buttons' );
		$allowed_keys   = array(
			'selector',
			'tag',
			'text',
			'backgroundColor',
			'color',
			'borderColor',
			'borderRadius',
			'fontFamily',
			'fontSize',
			'width',
			'height',
			'top',
			'left',
			'area',
			'score',
		);
		$sanitized      = array();

		foreach ( $allowed_groups as $group ) {
			if ( empty( $candidates[ $group ] ) || ! is_array( $candidates[ $group ] ) ) {
				continue;
			}

			$sanitized[ $group ] = array();
			foreach ( array_slice( $candidates[ $group ], 0, 12 ) as $candidate ) {
				if ( ! is_array( $candidate ) ) {
					continue;
				}

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

				if ( ! empty( $item ) ) {
					$sanitized[ $group ][] = $item;
				}
			}
		}

		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 parseRgb = (value) => {
					const match = normalize(value).match(/^rgba?\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)/i);
					return match ? [Number(match[1]), Number(match[2]), Number(match[3])] : null;
				};
				const luminance = (value) => {
					const rgb = parseRgb(value);
					if (!rgb) return 0;
					const channel = (part) => {
						const normalized = part / 255;
						return normalized <= 0.03928
							? normalized / 12.92
							: Math.pow((normalized + 0.055) / 1.055, 2.4);
					};
					return (0.2126 * channel(rgb[0])) + (0.7152 * channel(rgb[1])) + (0.0722 * channel(rgb[2]));
				};
				const contrastRatio = (a, b) => {
					const lighter = Math.max(luminance(a), luminance(b));
					const darker = Math.min(luminance(a), luminance(b));
					return (lighter + 0.05) / (darker + 0.05);
				};
				const findEffectiveBackgroundColor = (el) => {
					let node = el;
					while (node && node.nodeType === 1) {
						const style = getStyle(node);
						if (style && !isTransparentColor(style.backgroundColor)) {
							return normalize(style.backgroundColor);
						}

						for (const pseudo of ['::before', '::after']) {
							const pseudoStyle = window.getComputedStyle(node, pseudo);
							if (pseudoStyle && !isTransparentColor(pseudoStyle.backgroundColor)) {
								return normalize(pseudoStyle.backgroundColor);
							}
						}

						node = node.parentElement;
					}
					return '';
				};
				const getLargestRadius = (style) => {
					if (!style) return '';
					const radii = [
						style.borderTopLeftRadius,
						style.borderTopRightRadius,
						style.borderBottomRightRadius,
						style.borderBottomLeftRadius
					].map(function (value) {
						const match = normalize(value).match(/^(\d+(?:\.\d+)?)px$/i);
						return match ? Number(match[1]) : 0;
					});
					const largest = Math.max.apply(Math, radii);
					return Number.isFinite(largest) && largest > 0 ? `${Math.round(largest)}px` : normalize(style.borderRadius);
				};
				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;
						const text = normalize(node.textContent).toLowerCase();
						if (text.length < 3) return false;
						if (node.closest('header, nav, [role="banner"], [role="navigation"], .site-header, .header, #header')) return false;
						if (node.closest('form[role="search"], .search-form, .wp-block-search, .widget_search, [class*="search" i], [id*="search" i]')) return false;
						if (node.closest('[class*="cookie" i], [id*="cookie" i], [class*="newsletter" i], [id*="newsletter" i], .popup, .modal')) return false;
						if (text === 'search' || text.includes('search') || text.includes('cookie') || text.includes('accept') || text.includes('akzeptieren') || text.includes('newsletter') || text.includes('login') || text.includes('account')) 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',
						'main .product_type_simple',
						'main .ajax_add_to_cart'
					];
					const wooButton = firstVisible(wooSelectors, isLikelyPrimaryCta);
					if (wooButton) return wooButton;

					const heroSelectors = [
						'main .elementor-button',
						'main .elementor-button-link',
						'main .dt-btn',
						'main .vc_btn3',
						'main .ultb3-btn',
						'.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([
						'.elementor-button',
						'.elementor-button-link',
						'.dt-btn',
						'.vc_btn3',
						'.ultb3-btn',
						'.wp-block-button__link',
						'.wp-element-button',
						'.button',
						'.btn',
						'button',
						'a[role="button"]'
					], isLikelyPrimaryCta);
				};

				const pickHeader = () => {
					const nav = firstVisible([
						'header nav',
						'header [role="navigation"]',
						'.site-header nav',
						'.main-navigation',
						'.primary-navigation',
						'.navigation',
						'nav.navigation',
						'nav'
					], function (node, style, rect) {
						if (!node || !style || !rect) return false;
						if (rect.width < 240 || rect.height < 28) return false;
						if (!findEffectiveBackgroundColor(node)) return false;
						return node.querySelectorAll('a, button, [role="menuitem"]').length >= 2;
					});
					if (nav) {
						const headerWrapper = nav.closest('header, [role="banner"], .site-header, .header, #header');
						if (headerWrapper) {
							const wrapperRect = headerWrapper.getBoundingClientRect();
							const wrapperBackground = findEffectiveBackgroundColor(headerWrapper);
							if (
								wrapperBackground &&
								wrapperRect.width >= nav.getBoundingClientRect().width &&
								wrapperRect.height >= nav.getBoundingClientRect().height
							) {
								return headerWrapper;
							}
						}
						return nav;
					}

					return firstVisible(['header', '[role="banner"]', '.site-header', '.header', '#header', 'nav.navigation', 'nav']);
				};

				const collect = () => {
					const body = document.body;
					const header = pickHeader();
					const footer = firstVisible(['footer', '[role="contentinfo"]', '.site-footer', '.footer', '#footer']);
					const primaryCta = pickPrimaryCta();
					const input = firstVisible([
						'main input[type="email"]',
						'main input[type="text"]',
						'main input[type="search"]',
						'main textarea',
						'.woocommerce input[type="email"]',
						'.woocommerce input[type="text"]',
						'input[type="email"]',
						'input[type="text"]',
						'input[type="search"]',
						'textarea'
					]);
					const card = firstVisible([
						'main .woocommerce div.product',
						'main .product',
						'main .card',
						'main .wp-block-group',
						'main .entry-content',
						'main article',
						'.site-main',
						'.content-area',
						'main'
					], function (node, style, rect) {
						if (!node || !style || !rect) return false;
						if (rect.width < 180 || rect.height < 80) return false;
						return true;
					});
					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 pageQuality = (() => {
						const bodyText = normalize(document.body && document.body.innerText).toLowerCase();
						const bodyClasses = document.body ? document.body.className.toString().toLowerCase() : '';
						const title = normalize(document.title);
						const isHome = bodyClasses.includes(' home') || bodyClasses === 'home' || bodyClasses.includes('front-page') || window.location.pathname === '/';
						const isNotFound = bodyClasses.includes('error404') || title.toLowerCase().includes('not found') || bodyText.includes('nothing found') || bodyText.includes("can't find what you're looking for");
						const isSearchLike = Boolean(document.querySelector('form[role="search"], .search-form, .wp-block-search, .widget_search')) && (isNotFound || bodyText.includes('perhaps searching can help') || bodyText.includes('search ...'));
						const isCommerce = Boolean(document.querySelector('.woocommerce, .products, .product, .add_to_cart_button, .single_add_to_cart_button')) || bodyText.includes('add to cart') || bodyText.includes('shop');
						let score = 0;
						if (isHome) score += 4;
						if (isCommerce) score += 3;
						if (primaryCta) score += 2;
						if (footer) score += 1;
						if (isSearchLike) score -= 5;
						if (isNotFound) score -= 7;

						return {
							url: window.location.href,
							title,
							summary: isNotFound ? 'not_found' : (isSearchLike ? 'search_like' : (isCommerce ? 'commerce_like' : (isHome ? 'home' : 'generic'))),
							score: String(score),
							isHome: isHome ? '1' : '0',
							isCommerce: isCommerce ? '1' : '0',
							isSearchLike: isSearchLike ? '1' : '0',
							isNotFound: isNotFound ? '1' : '0',
							captureVersion: '2'
						};
					})();

					const pick = (el) => {
						const style = getStyle(el);
						if (!style) return null;
						const backgroundColor = findEffectiveBackgroundColor(el) || normalize(style.backgroundColor);
						const textColor = (() => {
							const textNodes = Array.from(el.querySelectorAll('span, strong, em, b, p, div, a, li, h1, h2, h3, h4, h5, h6'));
							const counts = new Map();
							for (const node of textNodes) {
								const directText = Array.from(node.childNodes || [])
									.filter((child) => child.nodeType === Node.TEXT_NODE)
									.map((child) => normalize(child.textContent))
									.join(' ')
									.trim();
								if (!directText || directText.length < 2) continue;
								const nodeStyle = getStyle(node);
								const rect = node.getBoundingClientRect();
								if (!nodeStyle || nodeStyle.display === 'none' || nodeStyle.visibility === 'hidden' || Number(nodeStyle.opacity) === 0) continue;
								if (rect.width < 4 || rect.height < 4) continue;
								const color = normalize(nodeStyle.color);
								if (color && !isTransparentColor(color)) {
									const previous = counts.get(color) || { count: 0, contrast: 0 };
									counts.set(color, {
										count: previous.count + 1,
										contrast: Math.max(previous.contrast, contrastRatio(color, backgroundColor))
									});
								}
							}
							if (counts.size) {
								return Array.from(counts.entries())
									.sort((a, b) => {
										if (b[1].count !== a[1].count) return b[1].count - a[1].count;
										return b[1].contrast - a[1].contrast;
									})[0][0];
							}
							return normalize(style.color);
						})();
						return {
							text: getText(el),
							backgroundColor,
							color: textColor,
							borderColor: normalize(style.borderColor),
							borderRadius: getLargestRadius(style),
							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 bodyStyle = getStyle(body);
							const bodyBackground = normalize(bodyStyle && bodyStyle.backgroundColor);
							if (headingColor && headingColor !== bodyBackground && headingColor !== 'rgb(255, 255, 255)') {
								bodyStyles.headingColor = headingColor;
								bodyStyles.mainHeadingColor = headingColor;
							}
						}
					}

					const elementDescriptor = (el) => {
						if (!el || !el.tagName) return '';
						const tag = el.tagName.toLowerCase();
						if (el.id) return `${tag}#${el.id}`;
						const classes = normalize(el.className && el.className.toString())
							.split(/\s+/)
							.filter(Boolean)
							.slice(0, 3)
							.join('.');
						return classes ? `${tag}.${classes}` : tag;
					};

					const isVisibleElement = (node) => {
						if (!node) return false;
						const rect = node.getBoundingClientRect();
						const style = getStyle(node);
						if (!style || style.display === 'none' || style.visibility === 'hidden' || Number(style.opacity) === 0) return false;
						return rect.width >= 20 && rect.height >= 12;
					};

					const candidateFromElement = (node, score) => {
						if (!isVisibleElement(node)) return null;
						const picked = pick(node);
						if (!picked) return null;
						const rect = node.getBoundingClientRect();
						return Object.assign({}, picked, {
							selector: elementDescriptor(node),
							tag: node.tagName.toLowerCase(),
							text: normalize(picked.text).slice(0, 120),
							width: String(Math.round(rect.width)),
							height: String(Math.round(rect.height)),
							top: String(Math.round(rect.top + window.scrollY)),
							left: String(Math.round(rect.left + window.scrollX)),
							area: String(Math.round(rect.width * rect.height)),
							score: String(Math.round(score || 0))
						});
					};

					const uniqueElements = (selectors) => {
						const seen = new Set();
						const elements = [];
						for (const selector of selectors) {
							document.querySelectorAll(selector).forEach((node) => {
								if (!node || seen.has(node)) return;
								seen.add(node);
								elements.push(node);
							});
						}
						return elements;
					};

					const scoreButtonCandidate = (node) => {
						const rect = node.getBoundingClientRect();
						const text = normalize(node.textContent).toLowerCase();
						const className = normalize(node.className && node.className.toString()).toLowerCase();
						let score = Math.min(rect.width * rect.height, 12000);
						const nodeStyle = getStyle(node);
						if (nodeStyle && !isTransparentColor(nodeStyle.backgroundColor)) score += 5000;
						if (text.match(/add to cart|buy|shop|checkout|continue|view|read more|learn more|discover|explore|order|warenkorb|entdecken|ansehen/)) score += 6000;
						if (className.match(/button|btn|cta|cart|checkout|primary|wp-element-button|wp-block-button/)) score += 3500;
						if (node.closest('main, .site-main, #content, .content-area, .woocommerce')) score += 2500;
						if (rect.top >= 0 && rect.top < window.innerHeight * 1.2) score += 1500;
						if (node.closest('header, nav, [role="banner"], [role="navigation"], footer')) score -= 5000;
						if (node.closest('form[role="search"], .search-form, .wp-block-search, .widget_search, [class*="search" i], [id*="search" i]')) score -= 9000;
						if (text.match(/^search$|login|account|facebook|google|cookie|accept|newsletter|dismiss|close/)) score -= 9000;
						return score;
					};

					const collectCandidates = () => {
						const headerCandidates = uniqueElements([
							'header',
							'[role="banner"]',
							'.site-header',
							'#masthead',
							'#header',
							'header nav',
							'.site-header nav',
							'.main-navigation',
							'.primary-navigation',
							'nav'
						])
							.filter(isVisibleElement)
							.map((node) => candidateFromElement(node, (node === header ? 10000 : 0) + Math.min(node.getBoundingClientRect().width * node.getBoundingClientRect().height, 25000)))
							.filter(Boolean)
							.sort((a, b) => Number(b.score || 0) - Number(a.score || 0))
							.slice(0, 8);

						const footerCandidates = uniqueElements([
							'footer',
							'[role="contentinfo"]',
							'.site-footer',
							'#colophon',
							'#footer',
							'.footer',
							'footer .widget',
							'footer section',
							'.site-footer .widget',
							'.site-footer section'
						])
							.filter(isVisibleElement)
							.map((node) => {
								const rect = node.getBoundingClientRect();
								const score = (node === footer ? 12000 : 0) + Math.min(rect.width * rect.height, 40000) + Math.max(0, rect.top + window.scrollY);
								return candidateFromElement(node, score);
							})
							.filter(Boolean)
							.sort((a, b) => Number(b.score || 0) - Number(a.score || 0))
							.slice(0, 8);

						const buttonCandidates = uniqueElements([
							'.single_add_to_cart_button',
							'.add_to_cart_button',
							'.wp-block-button__link',
							'.wp-element-button',
							'.elementor-button',
							'.elementor-button-link',
							'.button.alt',
							'.button',
							'.btn',
							'.read-more',
							'.more-link',
							'button',
							'a[role="button"]',
							'input[type="submit"]'
						])
							.filter(isVisibleElement)
							.map((node) => candidateFromElement(node, scoreButtonCandidate(node)))
							.filter(Boolean)
							.sort((a, b) => Number(b.score || 0) - Number(a.score || 0))
							.slice(0, 12);

						return {
							headers: headerCandidates,
							footers: footerCandidates,
							buttons: buttonCandidates
						};
					};

					return {
						computed: {
							body: bodyStyles,
							header: pick(header),
							footer: pick(footer),
							primaryCta: pick(primaryCta),
							input: pick(input),
							card: pick(card),
							meta: pageQuality,
							candidates: collectCandidates()
						}
					};
				};

				const send = () => {
					const payload = collect();
					const meta = payload && payload.computed && payload.computed.meta ? payload.computed.meta : {};
					if (meta.isNotFound === '1' || meta.isSearchLike === '1' || Number(meta.score || 0) < 2) {
						return;
					}
					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', 'trackfree-woocommerce-tracking' ), __( 'Home', 'trackfree-woocommerce-tracking' ), 'manage_options', 'trackfree#/home', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', __( 'Tracking Page - TrackFree', 'trackfree-woocommerce-tracking' ), __( 'Tracking Page', 'trackfree-woocommerce-tracking' ), 'manage_options', 'trackfree#/tracking-page', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', __( 'Shipments - TrackFree', 'trackfree-woocommerce-tracking' ), __( 'Shipments', 'trackfree-woocommerce-tracking' ), 'manage_options', 'trackfree#/shipments', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', __( 'Settings - TrackFree', 'trackfree-woocommerce-tracking' ), __( 'Settings', 'trackfree-woocommerce-tracking' ), 'manage_options', 'trackfree#/settings', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', __( 'Analytics - TrackFree', 'trackfree-woocommerce-tracking' ), __( 'Analytics', 'trackfree-woocommerce-tracking' ), 'manage_options', 'trackfree#/analytics', array( $this, 'render_admin_root' ) );
			add_submenu_page( 'trackfree', __( 'Account - TrackFree', 'trackfree-woocommerce-tracking' ), __( 'Billing', 'trackfree-woocommerce-tracking' ), '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();
	}
}
