<?php
/**
 * The file that defines the core plugin class
 *
 * A class definition that includes attributes and functions used across both the
 * public-facing side of the site and the admin area.
 *
 * @link       https://mojitowp.com
 * @since      1.0.0
 *
 * @package    Mojito_Shipping
 * @subpackage Mojito_Shipping/includes
 *
 *
 * Los curiosos deben leer el constructor: __construct()
 */

/**
 * The core plugin class.
 *
 * This is used to define internationalization, admin-specific hooks, and
 * public-facing site hooks.
 *
 * Also maintains the unique identifier of this plugin as well as the current
 * version of the plugin.
 *
 * @since      1.0.0
 * @package    Mojito_Shipping
 * @subpackage Mojito_Shipping/includes
 * @author     Mojito Team <support@mojitowp.com>
 */

namespace Mojito_Shipping;

if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Mojito Shipping main class
 */
class Mojito_Shipping {

	/**
	 * The loader that's responsible for maintaining and registering all hooks that power
	 * the plugin.
	 *
	 * @since    1.0.0
	 * @access   protected
	 * @var      Mojito_Shipping_Loader    $loader    Maintains and registers all hooks for the plugin.
	 */
	protected $loader;

	/**
	 * The unique identifier of this plugin.
	 *
	 * @since    1.0.0
	 * @access   protected
	 * @var      string    $plugin_name    The string used to uniquely identify this plugin.
	 */
	protected $plugin_name;

	/**
	 * The current version of the plugin.
	 *
	 * @since    1.0.0
	 * @access   protected
	 * @var      string    $version    The current version of the plugin.
	 */
	protected $version;

	/**
	 * CCR legacy WS client
	 *
	 * @var Mojito_Shipping_Method_CCR_WSC
	 */
	protected $ccr_ws_client;

	/**
	 * Pymexpress WS Client
	 *
	 * @var Mojito_Shipping_Method_Pymexpress_WSC
	 */
	protected $pymexpress_ws_client;


	/**
	 * Define the core functionality of the plugin.
	 *
	 * Set the plugin name and the plugin version that can be used throughout the plugin.
	 * Load the dependencies, define the locale, and set the hooks for the admin area and
	 * the public-facing side of the site.
	 *
	 * @since    1.0.0
	 */
	public function __construct() {

		if ( defined( 'MOJITO_SHIPPING_VERSION' ) ) {
			$this->version = MOJITO_SHIPPING_VERSION;
		} else {
			$this->version = '1.6.1';
		}
		$this->plugin_name = 'mojito-shipping';

		/**
		 * Define plugin name as constant.
		 */
		define( 'MOJITO_SHIPPING_SLUG', $this->plugin_name );

		$this->maybe_upgrade_runtime_state();
		$this->load_dependencies();
		$this->set_locale();
		$this->define_admin_hooks();
		$this->define_public_hooks();

		/**
		 * Add address support
		 */
		if ( class_exists( 'Mojito_Shipping\Mojito_Shipping_Address' ) ) {
			$mojito_address = new Mojito_Shipping_Address();
		}

		add_action( 'init', array( $this, 'start_woocommerce_shipping' ) );

		/**
		 * Cron jobs
		 */
		$this->cron_recurrences();

		
		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
			
			// Cron: Check your IP address in our Firewall
			\add_action( 'mojito-shipping-pymexpress-cron-control-check-ip', array( $this, 'cron_mojito_proxy_ip_check' ) );

			// Cron: Check the API connection
			\add_action( 'mojito-shipping-pymexpress-cron-control-check-api', array( $this, 'cron_pymexpress_check_api' ) );

			// Cron: Complete orders
			\add_action( 'mojito-shipping-pymexpress-cron-control-complete-orders', array( $this, 'cron_pymexpress_complete_orders' ) );

			// Cron: Update exchange rates
			\add_action( 'mojito-shipping-pymexpress-cron-control-update-exchange-rate', array( $this, 'cron_pymexpress_update_exchange_rate' ) );

			/**
			 * Download settings
			 */
			\add_action( 'wp_ajax_mojito_shipping_download_settings', array( $this, 'download_settings' ) );
	
			/**
			 * Apply settings
			 */
			\add_action( 'wp_ajax_mojito_shipping_apply_settings', array( $this, 'apply_settings' ) );

			/**
			 * Sync cron events when the cron settings are updated from the admin UI.
			 */
			\add_action( 'save_mojito_setting_mojito-shipping-pymexpress-cron-control-check-ip', array( $this, 'sync_premium_cron_events' ) );
			\add_action( 'save_mojito_setting_mojito-shipping-pymexpress-cron-control-check-api', array( $this, 'sync_premium_cron_events' ) );
			\add_action( 'save_mojito_setting_mojito-shipping-pymexpress-cron-control-complete-orders', array( $this, 'sync_premium_cron_events' ) );
			\add_action( 'save_mojito_setting_mojito-shipping-pymexpress-cron-control-update-exchange-rate', array( $this, 'sync_premium_cron_events' ) );

			$this->maybe_sync_premium_cron_events_runtime();

		}

	}

	public function cron_recurrences()
	{
		\add_filter('cron_schedules', function ($schedules) {
			$schedules['every_1_minute'] = [
				'interval' => 60,
				'display'  => __( 'Each 1 minute', 'mojito-shipping' ),
			];
			$schedules['every_5_minutes'] = [
				'interval' => 300,
				'display'  => __( 'Each 5 minutes', 'mojito-shipping' ),
			];
			$schedules['every_10_minutes'] = [
				'interval' => 600,
				'display'  => __( 'Each 10 minutes', 'mojito-shipping' ),
			];
			$schedules['every_15_minutes'] = [
				'interval' => 900,
				'display'  => __( 'Each 15 minutes', 'mojito-shipping' ),
			];
			$schedules['every_30_minutes'] = [
				'interval' => 1800,
				'display'  => __( 'Each 30 minutes', 'mojito-shipping' ),
			];
			$schedules['every_1_hour'] = [
				'interval' => 3600,
				'display'  => __( 'Each 1 hour', 'mojito-shipping' ),
			];
			$schedules['every_2_hours'] = [
				'interval' => 7200,
				'display'  => __( 'Each 2 hours', 'mojito-shipping' ),
			];
			$schedules['every_3_hours'] = [
				'interval' => 10800,
				'display'  => __( 'Each 3 hours', 'mojito-shipping' ),
			];
			$schedules['every_4_hours'] = [
				'interval' => 14400,
				'display'  => __( 'Each 4 hours', 'mojito-shipping' ),
			];
			$schedules['every_6_hours'] = [
				'interval' => 21600,
				'display'  => __( 'Each 6 hours', 'mojito-shipping' ),
			];
			$schedules['every_12_hours'] = [
				'interval' => 43200,
				'display'  => __( 'Each 12 hours', 'mojito-shipping' ),
			];
			$schedules['daily'] = [
				'interval' => 86400,
				'display'  => __( 'Daily', 'mojito-shipping' ),
			];
		
			return $schedules;
		});
		
	}

	/**
	 * Get the current premium cron event configuration.
	 *
	 * @return array
	 */
	private function get_pymexpress_cron_event_settings() {

		return array(
			'mojito-shipping-pymexpress-cron-control-check-ip' => array(
				'option' => 'mojito-shipping-pymexpress-cron-control-check-ip',
			),
			'mojito-shipping-pymexpress-cron-control-check-api' => array(
				'option' => 'mojito-shipping-pymexpress-cron-control-check-api',
			),
			'mojito-shipping-pymexpress-cron-control-complete-orders' => array(
				'option' => 'mojito-shipping-pymexpress-cron-control-complete-orders',
			),
			'mojito-shipping-pymexpress-cron-control-update-exchange-rate' => array(
				'option' => 'mojito-shipping-pymexpress-cron-control-update-exchange-rate',
			),
		);
	}

	/**
	 * Get a list of legacy cron hooks that should be removed during upgrades.
	 *
	 * @return array
	 */
	private function get_pymexpress_legacy_cron_hooks() {

		return array(
			'mojito-shipping-cron-ccr',
			'mojito-shipping-cron-pymexpress',
			'mojito-shipping-cron-mojito-proxy-ip-check',
			'mojito-shipping-cron-complete-orders',
			'mojito-shipping-cron-update-exchange-rate',
		);
	}

	/**
	 * Build a stable signature for the current premium cron configuration.
	 *
	 * @return string
	 */
	private function get_pymexpress_cron_sync_signature() {

		$settings = array();

		foreach ( $this->get_pymexpress_cron_event_settings() as $hook => $event_settings ) {
			$settings[ $hook ] = (string) get_option( $event_settings['option'], 'no' );
		}

		return md5( wp_json_encode( $settings ) );
	}

	/**
	 * Persist runtime upgrade state for settings that need one-time migrations.
	 *
	 * @return void
	 */
	private function maybe_upgrade_runtime_state() {

		$installed_version = (string) get_option( 'mojito-shipping-version', '' );
		$this->maybe_migrate_pymexpress_complete_orders_cron_recurrence();
		$this->maybe_migrate_pymexpress_location_cache();
		$this->maybe_set_pymexpress_pdf_email_cutoff();

		if ( $installed_version === $this->version ) {
			return;
		}

		update_option( 'mojito-shipping-version', $this->version );
	}

	/**
	 * Move legacy 1-minute complete-orders cron schedules to every 4 hours.
	 *
	 * @return void
	 */
	private function maybe_migrate_pymexpress_complete_orders_cron_recurrence() {

		if ( get_option( 'mojito-shipping-pymexpress-complete-orders-cron-migrated', false ) ) {
			return;
		}

		$option_name = 'mojito-shipping-pymexpress-cron-control-complete-orders';
		$recurrence  = (string) get_option( $option_name, 'no' );

		if ( 'every_1_minute' === $recurrence ) {
			update_option( $option_name, 'no' );
		}

		update_option( 'mojito-shipping-pymexpress-complete-orders-cron-migrated', 1 );
	}

	/**
	 * Synchronize premium cron schedules only when the configuration changes.
	 *
	 * @return void
	 */
	private function maybe_sync_premium_cron_events_runtime() {

		if ( ! function_exists( 'mojito_shipping_fs' ) ) {
			return;
		}

		if ( ! mojito_shipping_fs()->is__premium_only() || ! mojito_shipping_fs()->can_use_premium_code() ) {
			return;
		}

		$stored_signature  = (string) get_option( 'mojito-shipping-pymexpress-cron-sync-signature', '' );
		$current_signature = $this->get_pymexpress_cron_sync_signature();
		$migrated          = (bool) get_option( 'mojito-shipping-pymexpress-cron-sync-migrated', false );

		if ( $migrated && hash_equals( $stored_signature, $current_signature ) ) {
			return;
		}

		$this->sync_premium_cron_events();
	}

	/**
	 * Remove the legacy permanent Pymexpress location transients once per site.
	 *
	 * @return void
	 */
	private function maybe_migrate_pymexpress_location_cache() {

		if ( get_option( 'mojito-shipping-pymexpress-location-cache-migrated', false ) ) {
			return;
		}

		global $wpdb;

		$location_prefixes = array(
			'mojito-shipping-provinces',
			'mojito-shipping-cantones-from-province-',
			'mojito-shipping-districts-from-province-',
			'mojito-shipping-cities-from-province-',
			'mojito-shipping-postcode-from-province-',
		);
		$where_clauses     = array();
		$query_params      = array();

		foreach ( $location_prefixes as $location_prefix ) {
			$where_clauses[] = 'option_name LIKE %s';
			$query_params[]  = $wpdb->esc_like( '_transient_' . $location_prefix ) . '%';
			$where_clauses[] = 'option_name LIKE %s';
			$query_params[]  = $wpdb->esc_like( '_transient_timeout_' . $location_prefix ) . '%';
		}

		$deleted          = $wpdb->query(
			$wpdb->prepare(
				"DELETE FROM {$wpdb->options} WHERE " . implode( ' OR ', $where_clauses ),
				$query_params
			)
		);

		if ( false === $deleted ) {
			mojito_shipping_debug( 'Unable to clean the legacy Pymexpress location cache.' );
			return;
		}

		mojito_shipping_debug(
			sprintf(
				'Cleaned %d legacy Pymexpress location cache entries.',
				(int) $deleted
			)
		);

		update_option( 'mojito-shipping-pymexpress-preloaded', true );
		update_option( 'mojito-shipping-pymexpress-location-cache-migrated', 1 );
	}

	/**
	 * Get the current site-local datetime with compatibility for WordPress 5.2.
	 *
	 * @return \DateTimeImmutable
	 */
	private function get_site_local_datetime() {

		if ( function_exists( 'current_datetime' ) ) {
			$current_datetime = current_datetime();

			if ( $current_datetime instanceof \DateTimeImmutable ) {
				return $current_datetime;
			}

			if ( $current_datetime instanceof \DateTime ) {
				return \DateTimeImmutable::createFromMutable( $current_datetime );
			}
		}

		$timezone_string = (string) get_option( 'timezone_string', '' );
		if ( '' !== $timezone_string ) {
			try {
				return new \DateTimeImmutable( 'now', new \DateTimeZone( $timezone_string ) );
			} catch ( \Exception $e ) {
				mojito_shipping_debug( 'Invalid timezone_string detected while building the Pymexpress PDF email cutoff.' );
			}
		}

		$offset_seconds = (int) round( (float) get_option( 'gmt_offset', 0 ) * HOUR_IN_SECONDS );
		$offset_sign    = ( $offset_seconds < 0 ) ? '-' : '+';
		$offset_seconds = abs( $offset_seconds );
		$offset_hours   = (int) floor( $offset_seconds / HOUR_IN_SECONDS );
		$offset_minutes = (int) floor( ( $offset_seconds % HOUR_IN_SECONDS ) / MINUTE_IN_SECONDS );
		$timezone       = new \DateTimeZone( sprintf( '%s%02d:%02d', $offset_sign, $offset_hours, $offset_minutes ) );

		return new \DateTimeImmutable( 'now', $timezone );
	}

	/**
	 * Set the Pymexpress PDF email cutoff to the start of the current site day.
	 *
	 * @return void
	 */
	private function maybe_set_pymexpress_pdf_email_cutoff() {

		$existing_cutoff = (int) get_option( 'mojito-shipping-pymexpress-pdf-email-cutoff', 0 );
		if ( $existing_cutoff > 0 ) {
			return;
		}

		$today  = $this->get_site_local_datetime();
		$cutoff = $today->setTime( 0, 0, 0 )->getTimestamp();

		update_option( 'mojito-shipping-pymexpress-pdf-email-cutoff', $cutoff );
	}

	/**
	 * Check whether a Pymexpress order is eligible to receive the PDF email.
	 *
	 * @param mixed $order WooCommerce order.
	 * @return bool
	 */
	private function pymexpress_should_send_pdf_email_for_order( $order ) {

		if ( is_bool( $order ) || ! is_a( $order, 'WC_Order' ) ) {
			return false;
		}

		$cutoff = (int) get_option( 'mojito-shipping-pymexpress-pdf-email-cutoff', 0 );
		if ( $cutoff <= 0 ) {
			return true;
		}

		$date_created = $order->get_date_created();
		if ( ! $date_created ) {
			return false;
		}

		return $date_created->getTimestamp() >= $cutoff;
	}

	/**
	 * Synchronize premium cron events with the current plugin settings.
	 *
	 * @param mixed $saved_value Optional value received from save_mojito_setting actions.
	 * @return void
	 */
	public function sync_premium_cron_events( $saved_value = null ) {

		unset( $saved_value );

		if ( ! function_exists( 'mojito_shipping_fs' ) ) {
			return;
		}

		if ( ! mojito_shipping_fs()->is__premium_only() || ! mojito_shipping_fs()->can_use_premium_code() ) {
			return;
		}

		foreach ( $this->get_pymexpress_legacy_cron_hooks() as $legacy_hook ) {
			if ( \wp_next_scheduled( $legacy_hook ) ) {
				\wp_clear_scheduled_hook( $legacy_hook );
			}
		}

		$schedules = \wp_get_schedules();

		foreach ( $this->get_pymexpress_cron_event_settings() as $hook => $event_settings ) {

			$recurrence      = \get_option( $event_settings['option'], 'no' );
			$scheduled_event = \wp_get_scheduled_event( $hook );

			if ( empty( $recurrence ) || 'no' === $recurrence ) {
				if ( false !== $scheduled_event ) {
					\wp_clear_scheduled_hook( $hook );
				}

				continue;
			}

			if ( ! isset( $schedules[ $recurrence ] ) ) {
				mojito_shipping_debug( sprintf( 'Skipping cron sync for %s because schedule "%s" is not registered.', $hook, $recurrence ) );
				\wp_clear_scheduled_hook( $hook );
				continue;
			}

			if ( false === $scheduled_event ) {
				\wp_schedule_event( time(), $recurrence, $hook );
				continue;
			}

			if ( $scheduled_event->schedule !== $recurrence ) {
				\wp_clear_scheduled_hook( $hook );
				\wp_schedule_event( time(), $recurrence, $hook );
			}
		}

		update_option( 'mojito-shipping-pymexpress-cron-sync-signature', $this->get_pymexpress_cron_sync_signature() );
		update_option( 'mojito-shipping-pymexpress-cron-sync-migrated', 1 );
	}

	/**
	 * Load the required dependencies for this plugin.
	 *
	 * Include the following files that make up the plugin:
	 *
	 * - Mojito_Shipping_Loader. Orchestrates the hooks of the plugin.
	 * - Mojito_Shipping_I18n. Defines internationalization functionality.
	 * - Mojito_Shipping_Admin. Defines all hooks for the admin area.
	 * - Mojito_Shipping_Public. Defines all hooks for the public side of the site.
	 *
	 * Create an instance of the loader which will be used to register the hooks
	 * with WordPress.
	 *
	 * @since    1.0.0
	 * @access   private
	 */
	private function load_dependencies() {

		/**
		 * The class responsible for orchestrating the actions and filters of the
		 * core plugin.
		 */
		if ( ! class_exists( 'Mojito_Shipping_Loader' ) ) {
			require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-loader.php';
		}

		/**
		 * The class responsible for defining internationalization functionality
		 * of the plugin.
		 */
		if ( ! class_exists( 'Mojito_Shipping_I18n' ) ) {
			require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-i18n.php';
		}

		/**
		 * The class responsible for generate settings controls ans inputs
		 */
		if ( ! class_exists( 'Mojito_Settings' ) ) {
			require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-settings.php';
		}

		/**
		 * The class responsible for exchange rates.
		 */
		if ( ! class_exists( 'Mojito_Shipping_Exchange_Rate' ) ) {
			require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-exchange-rate.php';
		}

		/**
		 * Load Address
		 */
		require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-address.php';

		/**
		 * The class responsible for defining all actions that occur in the admin area.
		 */
		if ( ! class_exists( 'Mojito_Shipping\Mojito_Shipping_Admin' ) ) {
			require_once MOJITO_SHIPPING_DIR . 'admin/class-mojito-shipping-admin.php';
			if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
				if ( ! class_exists( 'Mojito_Shipping\Mojito_Shipping_Admin_Pro' ) ) {
					require_once MOJITO_SHIPPING_DIR . 'admin/class-mojito-shipping-admin-pro.php';
				}
			}
		}

		/**
		 * The class responsible for defining all actions that occur in the public-facing
		 * side of the site.
		 */
		require_once MOJITO_SHIPPING_DIR . 'public/class-mojito-shipping-public.php';

		$this->loader = new Mojito_Shipping_Loader();
	}

	/**
	 * Define the locale for this plugin for internationalization.
	 *
	 * Uses the Mojito_Shipping_I18n class in order to set the domain and to register the hook
	 * with WordPress.
	 *
	 * @since    1.0.0
	 * @access   private
	 */
	private function set_locale() {

		$plugin_i18n = new Mojito_Shipping_I18n();

		$this->loader->add_action( 'init', $plugin_i18n, 'load_plugin_textdomain', 5 );
	}

	/**
	 * Register all of the hooks related to the admin area functionality
	 * of the plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 */
	private function define_admin_hooks() {

		$plugin_admin = new Mojito_Shipping_Admin();
		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
			if ( class_exists( 'Mojito_Shipping\Mojito_Shipping_Admin_Pro' ) ) {
				$plugin_admin = new Mojito_Shipping_Admin_Pro();
			}
		}

		$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_styles' );
		$this->loader->add_action( 'admin_enqueue_scripts', $plugin_admin, 'enqueue_scripts' );
		$this->loader->add_action( 'admin_menu', $plugin_admin, 'menu_options' );
	}

	/**
	 * Register all of the hooks related to the public-facing functionality
	 * of the plugin.
	 *
	 * @since    1.0.0
	 * @access   private
	 */
	private function define_public_hooks() {

		$plugin_public = new Mojito_Shipping_Public( $this->get_plugin_name(), $this->get_version() );

		$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_styles' );
		$this->loader->add_action( 'wp_enqueue_scripts', $plugin_public, 'enqueue_scripts' );
	}

	/**
	 * Run the loader to execute all of the hooks with WordPress.
	 *
	 * @since    1.0.0
	 */
	public function run() {

		$carrier_provider = get_option( 'mojito-shipping-carrier-provider' );

		if ( is_array( $carrier_provider ) ) {

			if ( in_array( 'ccr', $carrier_provider, true ) ) {

				// Init web service client.
				if ( ! class_exists( 'Mojito_Shipping_Method_CCR_WSC' ) ) {
					require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-ccr-webservice-client.php';
				}

				$this->ccr_ws_client = new Mojito_Shipping_Method_CCR_WSC();

				add_action( 'woocommerce_checkout_after_customer_details', array( $this, 'ccr_checkout_after_customer_details' ) );

				add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'ccr_checkout_update_order_meta_save_guide_number' ) );

				add_action( 'woocommerce_thankyou', array( $this, 'ccr_thankyou_log_send' ) );

				add_action( 'woocommerce_order_details_after_order_table_items', array( $this, 'ccr_order_items_table_success_meta' ), 30, 1 );

				add_action( 'woocommerce_admin_order_data_after_billing_address', array( $this, 'ccr_admin_order_data_after_billing_address' ), 40, 1 );

				add_action( 'load-post.php', array( $this, 'ccr_admin_order_tracking_data' ), 40, 1 );

				add_action( 'woocommerce_email_after_order_table', array( $this, 'ccr_email_after_order_table_add_guide_number' ), 12, 2 );

				/**
				 * Manual Guide number request
				 */
				add_action( 'wp_ajax_mojito_shipping_ccr_manual_request_guide_number', array( $this, 'ccr_manual_request' ) );

				/**
				 * Manual register Guide number
				 */
				add_action( 'wp_ajax_mojito_shipping_ccr_manual_register_guide_number', array( $this, 'ccr_manual_register' ) );

				/**
				 * Download PDF from admin
				 */
				add_action( 'wp_ajax_mojito_shipping_ccr_download_pdf', array( $this, 'ccr_pdf_download' ) );

				/**
				 * Download PDF from customer order details
				 */
				if ( 'yes' === get_option( 'mojito-shipping-ccr-pdf-export-in-customer-order' ) ) {
					add_action( 'wp_ajax_mojito_shipping_ccr_download_pdf_customer', array( $this, 'ccr_pdf_download_customer' ) );
				}
			}

			if ( in_array( 'pymexpress', $carrier_provider, true ) ) {

				// Init web service client.
				if ( ! class_exists( 'Mojito_Shipping_Method_Pymexpress_WSC' ) ) {
					require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-pymexpress-webservice-client.php';
				}

				$this->pymexpress_ws_client = new Mojito_Shipping_Method_Pymexpress_WSC();

				add_action( 'woocommerce_checkout_after_customer_details', array( $this, 'pymexpress_checkout_after_customer_details' ) );

				add_action( 'woocommerce_checkout_update_order_meta', array( $this, 'pymexpress_checkout_update_order_meta_save_guide_number' ) );

				add_action( 'woocommerce_order_status_changed', array( $this, 'pymexpress_order_is_completed' ) );

				add_action( 'woocommerce_order_details_after_order_table_items', array( $this, 'pymexpress_order_items_table_success_meta' ), 30, 1 );

				add_action( 'woocommerce_admin_order_data_after_billing_address', array( $this, 'pymexpress_admin_order_data_after_billing_address' ), 40, 1 );

				add_action( 'load-post.php', array( $this, 'pymexpress_admin_order_tracking_data' ), 40, 1 );

				add_action( 'woocommerce_email_after_order_table', array( $this, 'pymexpress_email_after_order_table_add_guide_number' ), 12, 2 );

				/**
				 * Manual Guide number request
				 */
				add_action( 'wp_ajax_mojito_shipping_pymexpress_manual_request_guide_number', array( $this, 'pymexpress_manual_request' ) );

				/**
				 * Manual register Guide number
				 */
				add_action( 'wp_ajax_mojito_shipping_pymexpress_manual_register_guide_number', array( $this, 'pymexpress_manual_register' ) );

				/**
				 * Download PDF from admin
				 */
				add_action( 'wp_ajax_mojito_shipping_pymexpress_download_pdf', array( $this, 'pymexpress_pdf_download' ) );

				/**
				 * Download PDF from customer order details
				 */
				if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-in-customer-order' ) ) {
					add_action( 'wp_ajax_mojito_shipping_pymexpress_download_pdf_customer', array( $this, 'pymexpress_pdf_download_customer' ) );
				}

				/**
				 * Pymexpress location list
				 */
				$mojito_address = new Mojito_Shipping_Address();
				add_action( 'wp_ajax_mojito_shipping_pymexpress_get_provinces_list', array( $mojito_address, 'get_pymexpress_provinces_list_ajax' ) );
				add_action( 'wp_ajax_mojito_shipping_pymexpress_get_cantons_list', array( $mojito_address, 'get_pymexpress_cantons_list_ajax' ) );
				add_action( 'wp_ajax_mojito_shipping_pymexpress_get_district_list', array( $mojito_address, 'get_pymexpress_districts_list_ajax' ) );
				add_action( 'wp_ajax_mojito_shipping_pymexpress_get_cities_list', array( $mojito_address, 'get_pymexpress_cities_list_ajax' ) );

				if ( ! get_option( 'mojito-shipping-pymexpress-preloaded' ) ) {
					$mojito_address->pre_load_pymexpress_locations();
				}
			}
		}
		$this->loader->run();
	}

	/**
	 * Add CCR guide number after customer details
	 *
	 * @return void
	 */
	public function ccr_checkout_after_customer_details() {

		woocommerce_form_field(
			'mojito_shipping_ccr_guide_number',
			array(
				'type'              => 'text',
				'class'             => array( 'hidden' ),
				'default'           => $this->ccr_ws_client->ccr_get_guide_number(),
				'custom_attributes' => array( 'readonly' => 'readonly' ),
			)
		);
	}

	/**
	 * Update meta, save guide number.
	 *
	 * @param Int $order_id Order ID.
	 * @return void
	 */
	public function ccr_checkout_update_order_meta_save_guide_number( $order_id ) {

		$order = wc_get_order( $order_id );

		if ( ! $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {
			return;
		}

		if ( ! empty( $_POST['mojito_shipping_ccr_guide_number'] ) && ( $order->has_shipping_method( 'mojito_shipping_ccr' ) ) ) {
			$order->update_meta_data( 'mojito_shipping_ccr_guide_number', sanitize_text_field( $_POST['mojito_shipping_ccr_guide_number'] ) );
			$order->save();
		}
	}

	/**
	 * Thank you page
	 *
	 * @param Int     $order_id Order id.
	 * @param boolean $manual_request is a manual request?.
	 * @return void
	 */
	public function ccr_thankyou_log_send( $order_id, $manual_request = false ) {

		$order = wc_get_order( $order_id );

		/**
		 * Is a valid order?
		 */
		if ( ! $order instanceof \WC_Order ) {
			return;
		}

		$log_send = $order->get_meta( 'mojito_ccr_shipping_log', true );
		$details  = '';

		$items       = array();
		$weight_unit = get_option( 'woocommerce_weight_unit' );

		if ( ( $manual_request || empty( $log_send ) ) && $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {

			$full_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
			if ( 0 === strlen( trim( $full_name ) ) ) {
				$full_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
			}

			$address = $order->get_shipping_address_1();
			if ( ! empty( $order->get_shipping_address_2() ) ) {
				$address .= ' ' . $order->get_shipping_address_2();
			}

			foreach ( $order->get_items() as $key => $order_values ) {

				$product            = $order_values->get_product();
				$product_order_data = $order_values->get_data();
				$product_name       = $order_values->get_name();
				$product_weight     = ( $product && is_object( $product ) ) ? $product->get_weight() : 0;

				$items[] = array(
					'quantity' => $product_order_data['quantity'],
					'weight'   => $product_weight,
				);

				if ( empty( $details ) ) {
					$details = $product_name;
				} elseif ( $details !== $product_name ) {
					$details .= ', ' . $product_name;
				}
			}

			$shipping_weight = 0;
			foreach ( $items as $id => $data ) {

				$weight = $data['weight'];
				if ( ! is_numeric( $weight ) ) {
					/**
					 * 1 kg default weight
					 */
					$weight = 1000;
				}

				$product_weight   = $data['quantity'] * $weight;
				$shipping_weight += $product_weight;
			}

			if ( 'g' === $weight_unit ) {
				// no changes.
			} elseif ( 'kg' === $weight_unit ) {
				$shipping_weight = $shipping_weight * 1000;

			} elseif ( 'lbs' === $weight_unit ) {
				$shipping_weight = $shipping_weight / 0.0022046;

			} elseif ( 'oz' === $weight_unit ) {
				$shipping_weight = $shipping_weight / 0.035274;
			}

			/**
			 * If $order->get_shipping_postcode() is empty, then use get_billing_postcode()
			 */
			$post_code = $order->get_shipping_postcode();
			if ( empty( $post_code ) ) {
				$post_code = $order->get_billing_postcode();
			}

			$dest_phone_number = $order->get_shipping_phone();
			$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
			$dest_phone_number = str_replace( '-', '', $dest_phone_number );

			if ( empty( $dest_phone_number ) ){
				$dest_phone_number = $order->get_billing_phone();
				$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
				$dest_phone_number = str_replace( '-', '', $dest_phone_number );
			}

			if ( strpos( $dest_phone_number, '/') !== false ) {
				$dest_phone_number = explode( '/', $dest_phone_number );
				$dest_phone_number = $dest_phone_number[0];
			}

			return $order->add_order_note(
				__( 'Correos de Costa Rica Answer: ', 'mojito-shipping' ) .
					$this->ccr_ws_client->ccr_register_sending(
						$order_id,
						$order->get_meta( 'mojito_shipping_ccr_guide_number', true ),
						$details,
						$order->get_shipping_total(),
						$full_name,
						$address,
						$dest_phone_number,
						$post_code,
						$shipping_weight
					)
			);
		}
	}

	/**
	 * Add info to order data.
	 *
	 * @param Order $order Order object.
	 * @return void
	 */
	public function ccr_order_items_table_success_meta( $order ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {
			return;
		}

		$order_id              = $order->get_id();
		$guide_number          = $order->get_meta( 'mojito_shipping_ccr_guide_number', true );
		$ccr_msj_email_label   = get_option( 'mojito-shipping-ccr-mail-orders-name' );
		$ccr_msj_email_content = get_option( 'mojito-shipping-ccr-mail-orders-message' );

		if ( ! empty( $guide_number ) ) {

			$ccr_msj_email_label   = ( ! empty( $ccr_msj_email_label ) ) ? $ccr_msj_email_label : __( 'Correos de Costa Rica Tracking code', 'mojito-shipping' );
			$ccr_msj_email_content = ( ! empty( $ccr_msj_email_content ) ) ? $ccr_msj_email_content : __( 'Guide number for packages tracking', 'mojito-shipping' );

			$html  = '';
			$html .= '<tr class="mojito-ccr-ws order_item">';
			$html .= '<td scope="row">';
			$html .= '<strong class="guide-number-title">' . $ccr_msj_email_label . ':</strong>';
			$html .= '</td>';
			$html .= '<td>';
			$html .= '<strong><span class="guide-number">' . $guide_number . '</span></strong>';
			$html .= '<small>  ' . $ccr_msj_email_content . '</small>';
			$html .= '</td>';
			$html .= '</tr>';

			/**
			 * Tracking and PDF Download
			 */

			 if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

				if ( 'yes' === get_option( 'mojito-shipping-ccr-tracking-user-order-details' ) ) {

					$response = $this->ccr_ws_client->ccr_get_movil_tracking( $guide_number );

					$html .= '<tr class="mojito-ccr-ws-tracking order_item">';
					$html .= '<td scope="row">';
					$html .= '<strong class="guide-number-title">' . __( 'Tracking', 'mojito-shipping' ) . ':</strong>';
					$html .= '</td>';
					$html .= '<td>';

					$html .= '<a class="mojito-shipping-toggle-tracking">' . __( 'Show tracking details', 'mojito-shipping' ) . '</a>';
					$html .= '<table class="tracking-details">';
					$html .= '<tr>';
					$html .= '<td>' . __( 'Date', 'mojito-shipping' ) . '</td>';
					$html .= '<td>' . __( 'Event', 'mojito-shipping' ) . '</td>';
					$html .= '<td>' . __( 'Location', 'mojito-shipping' ) . '</td>';
					$html .= '</tr>';

					$response = json_decode( $response, true );

					if ( is_array( $response ) ) {
						foreach ( $response as $key => $event ) {

							$fecha_hora = ( ! empty( $event['FECHA_HORA'] ) ) ? $event['FECHA_HORA'] : '';
							$evento     = ( ! empty( $event['EVENTO'] ) ) ? $event['EVENTO'] : '';
							$unidad     = ( ! empty( $event['UNIDAD'] ) ) ? $event['UNIDAD'] : '' ;

							$html .= '<tr>';
							$html .= '<td>' . $fecha_hora . '</td>';
							$html .= '<td>' . $evento . '</td>';
							$html .= '<td>' . $unidad . '</td>';
							$html .= '</tr>';
						}
					}

					$html .= '</table>';

					$html .= '</td>';
					$html .= '</tr>';
				}

				if ( 'yes' === get_option( 'mojito-shipping-ccr-pdf-export-in-customer-order' ) ) {

					$html .= '<tr class="mojito-ccr-download-pdf order_item">';
					$html .= '<td scope="row">';
					$html .= '<strong class="guide-number-title">' . __( 'Download Correos de Costa Rica Guide (PDF)', 'mojito-shipping' ) . ':</strong>';
					$html .= '</td>';
					$html .= '<td>';
					$html .= '<a id="' . esc_attr( $order_id ) . '" class="mojito-shipping-download-customer-pdf" data-order-id="' . esc_attr( $order_id ) . '" data-action="mojito_shipping_ccr_download_pdf_customer">' . esc_html( $guide_number ) . '</a>';
					$html .= '</td>';
					$html .= '</tr>';
				}
			}

			echo $html;
		}
	}

	/**
	 * Data after billing address.
	 *
	 * @param object $order Order id.
	 * @return void
	 */
	public function ccr_admin_order_data_after_billing_address( $order ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {
			return;
		}

		$order_id     = $order->get_id();
		$guide_number = $order->get_meta( 'mojito_shipping_ccr_guide_number', true );
		$reponse_code = $order->get_meta( 'mojito_shipping_ccr_ccrRegistroEnvio_response_code', true );

		$html  = '';
		$html .= '<tr class="mojito-ccr-ws">';
		$html .= '<td colspan="2">';
		$html .= '<div class="mojito-ccr-ws">';
		$html .= '<span class="title" style="">' . __( 'Guide number from Correos de Costa Rica: ', 'mojito-shipping' ) . '</span>';

		if ( empty( $guide_number ) ) {
			$html .= '<a id="' . $order_id . '" class="mojito-shipping-ccr-manual-request"> ' . __( 'Click to request. ', 'mojito-shipping' ) . '</a>';

		} elseif ( '00' !== $reponse_code && '36' !== $reponse_code ) {
			$html .= '<a id="' . $order_id . '" class="mojito-shipping-ccr-manual-register"> ' . __( 'Click to request. ', 'mojito-shipping' ) . '</a>';

		} else {

			$html .= '<p> ' . $guide_number . ' </p>';
			$html .= '<a id="' . $order_id . '" class="download mojito-shipping-ccr-download-pdf">';
			$html .= '<img src="' . plugin_dir_url( __DIR__ ) . 'admin/img/download.svg">';
			$html .= '</a>';

		}
		$html .= '</div>';
		$html .= '</td>';
		$html .= '</tr>';
		echo $html;

	}

	/**
	 * Add tracking to admin
	 *
	 * @return void
	 */
	public function ccr_admin_order_tracking_data() {

		if ( ! isset( $_GET['post'] ) ) {
			return;
		}

		$post_id = sanitize_text_field( $_GET['post'] );
		if ( ! is_numeric( $post_id ) ) {
			return;
		}

		$order = wc_get_order( $post_id );

		if ( is_bool( $order ) ) {
			return;
		}

		if ( ! $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {
			return;
		}

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

			if ( 'yes' === get_option( 'mojito-shipping-ccr-tracking-admin-order-details' ) ) {

				add_meta_box(
					'ccr_admin_order_tracking_data',
					__( 'Package tracking', 'mojito-shipping' ),
					function () use ( $order ) {

						$order_id     = $order->get_id();
						$guide_number = $order->get_meta('mojito_shipping_ccr_guide_number', true );

						$response = $this->ccr_ws_client->ccr_get_movil_tracking( $guide_number );

						$html  = '';
						$html .= '<table class="tracking-details-admin">';
						$html .= '<tr>';
						$html .= '<td>' . __( 'Date', 'mojito-shipping' ) . '</td>';
						$html .= '<td>' . __( 'Event', 'mojito-shipping' ) . '</td>';
						$html .= '<td>' . __( 'Location', 'mojito-shipping' ) . '</td>';
						$html .= '</tr>';

						$response = json_decode( $response, true );

						if ( is_array( $response ) ) {
							foreach ( $response as $key => $event ) {

								$fecha_hora = ( ! empty( $event['FECHA_HORA'] ) ) ? $event['FECHA_HORA'] : '';
								$evento     = ( ! empty( $event['EVENTO'] ) ) ? $event['EVENTO'] : '';
								$unidad     = ( ! empty( $event['UNIDAD'] ) ) ? $event['UNIDAD'] : '' ;

								$html .= '<tr>';
								$html .= '<td>' . $fecha_hora . '</td>';
								$html .= '<td>' . $evento . '</td>';
								$html .= '<td>' . $unidad . '</td>';
								$html .= '</tr>';

							}
						}

						$html .= '</table>';
						echo $html;
					},
					null,
					'normal'
				);
			}
		}

	}

	/**
	 * Add data to tabmel in email-
	 *
	 * @param Object $order Order.
	 * @param bool   $sent_to_admin Send to admin.
	 * @return void
	 */
	public function ccr_email_after_order_table_add_guide_number( $order, $sent_to_admin ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_ccr' ) ) {
			return;
		}

		/**
		 * If order is Failed or Canceled, then return.
		 */
		if ( in_array( $order->get_status(), array( 'failed', 'canceled' ), true ) ) {
			return;
		}

		$order_id              = $order->get_id();
		$guide_number          = $order->get_meta( 'mojito_shipping_ccr_guide_number', true );
		$ccr_msj_email_label   = get_option( 'mojito-shipping-ccr-mail-orders-name' );
		$ccr_msj_email_content = get_option( 'mojito-shipping-ccr-mail-orders-message' );

		if ( ! empty( $guide_number ) ) {

			$ccr_msj_email_label   = ( ! empty( $ccr_msj_email_label ) ) ? $ccr_msj_email_label : '';
			$ccr_msj_email_content = ( ! empty( $ccr_msj_email_content ) ) ? $ccr_msj_email_content : '';

			$ccr_tracking_url = apply_filters( 'mojito_shipping_ccr_tracking_url', 'https://correos.go.cr/rastreo/' );

			$html  = '';
			$html .= '<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;" border="1">';
			$html .= '<tr class="mojito-shipping-ccr-payment-gateway">';
			$html .= '<td class="td" scope="row" colspan="2">';
			$html .= '<strong class="title" style="display: block;">' . $ccr_msj_email_label . '</strong>';
			$html .= '<span style="font-size: 12px;">' . $guide_number . '</span>';
			$html .= '<span style="font-size: 12px; display: block;"><a href="' . $ccr_tracking_url . '">' . $ccr_msj_email_content . '</a></span>';
			$html .= '</td>';
			$html .= '</tr>';
			$html .= '</table>';
			echo $html;
		}
	}

	/**
	 * Check whether the current user can manage WooCommerce orders.
	 *
	 * @return bool
	 */
	private function current_user_can_manage_orders() {

		return current_user_can( 'manage_woocommerce' ) || current_user_can( 'edit_shop_orders' );
	}

	/**
	 * Return the posted order ID for an AJAX order action.
	 *
	 * @return int
	 */
	private function get_ajax_order_id_from_request() {

		if ( empty( $_POST['order_id'] ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'Missing order ID.', 'mojito-shipping' ),
				),
				400
				);
		}

		$order_id = absint( wp_unslash( $_POST['order_id'] ) );
		if ( $order_id <= 0 ) {
			wp_send_json_error(
				array(
					'message' => __( 'Invalid order ID.', 'mojito-shipping' ),
				),
				400
			);
		}

		return $order_id;
	}

	/**
	 * Validate an admin-side order AJAX request and return the target order.
	 *
	 * @return \WC_Order
	 */
	private function get_admin_ajax_order_from_request() {

		if ( ! $this->current_user_can_manage_orders() ) {
			wp_send_json_error(
				array(
					'message' => __( 'You are not allowed to manage this order.', 'mojito-shipping' ),
				),
				403
			);
		}

		if ( ! check_ajax_referer( 'mojito_shipping_admin_order_action', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'The order request could not be verified. Reload the page and try again.', 'mojito-shipping' ),
				),
				403
			);
		}

		$order = wc_get_order( $this->get_ajax_order_id_from_request() );
		if ( ! $order instanceof \WC_Order ) {
			wp_send_json_error(
				array(
					'message' => __( 'The requested order could not be found.', 'mojito-shipping' ),
				),
				404
			);
		}

		return $order;
	}

	/**
	 * Validate a customer-side order AJAX request and return the target order.
	 *
	 * @return \WC_Order
	 */
	private function get_customer_ajax_order_from_request() {

		if ( ! is_user_logged_in() ) {
			wp_send_json_error(
				array(
					'message' => __( 'You must be logged in to access this order.', 'mojito-shipping' ),
				),
				403
			);
		}

		if ( ! check_ajax_referer( 'mojito_shipping_customer_order_action', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'The order request could not be verified. Reload the page and try again.', 'mojito-shipping' ),
				),
				403
			);
		}

		$order = wc_get_order( $this->get_ajax_order_id_from_request() );
		if ( ! $order instanceof \WC_Order ) {
			wp_send_json_error(
				array(
					'message' => __( 'The requested order could not be found.', 'mojito-shipping' ),
				),
				404
			);
		}

		if ( $this->current_user_can_manage_orders() ) {
			return $order;
		}

		if ( (int) $order->get_user_id() !== get_current_user_id() ) {
			wp_send_json_error(
				array(
					'message' => __( 'You are not allowed to access this order.', 'mojito-shipping' ),
				),
				403
			);
		}

		return $order;
	}

	/**
	 * Manual request
	 * Useful when guide number request fail during the shopping
	 */
	public function ccr_manual_request() {

		$order        = $this->get_admin_ajax_order_from_request();
		$order_id     = $order->get_id();
		$guide_number = $this->ccr_ws_client->ccr_get_guide_number();

		$order->update_meta_data(
			'mojito_shipping_ccr_guide_number',
			sanitize_text_field( $guide_number )
		);
		$order->save();

		$comment_id = $this->ccr_thankyou_log_send( $order_id, true );

		if ( is_numeric( $comment_id ) ) {
			echo wp_json_encode( true );
			die();
		} else {
			echo wp_json_encode( false );
			die();
		}
	}

	/**
	 * Manual register
	 * Useful when register process fail during the shopping
	 */
	public function ccr_manual_register() {

		$order_id   = $this->get_admin_ajax_order_from_request()->get_id();
		$comment_id = $this->ccr_thankyou_log_send( $order_id, true );

		if ( is_numeric( $comment_id ) ) {
			echo wp_json_encode( true );
			die();
		} else {
			echo wp_json_encode( false );
			die();
		}
	}

	/**
	 * Download PDF
	 * Download generated pdf with the guide number
	 */
	public function ccr_pdf_download( $customer_request = false ) {

		if ( $customer_request ) {
			$order = $this->get_customer_ajax_order_from_request();
		} else {
			$order = $this->get_admin_ajax_order_from_request();
		}

		$order_id = $order->get_id();

		/**
		 * Validate order
		 */
		$order = \wc_get_order( $order_id );

		/**
		 * Is a valid order?
		 */
		if ( is_bool( $order ) ) {
			return;
		}

		/**
		 * TMP folder
		 */
		$tmp_dir    = '';
		$upload_dir = wp_upload_dir();

		if ( ! empty( $upload_dir['error'] ) ) {
			$tmp_dir = get_temp_dir();
		} else {
			$tmp_dir = $upload_dir['basedir'];
		}

		$tmp_dir .= '/mojito-shipping-tmp/';

		/**
		 * Check if folder exists
		 */
		if ( ! is_dir( $tmp_dir ) ) {
			// dir doesn't exist, make it.
			mkdir( $tmp_dir );
		}

		/**
		 * Guide number
		 */
		$guide_number = $order->get_meta( 'mojito_shipping_ccr_guide_number', true );

		/**
		 * Filename
		 */
		$file = $tmp_dir . $guide_number . ' .pdf';

		/**
		 * Create PDF
		 */
		$pdf = new \TCPDF( PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false );

		// remove default header/footer.
		$pdf->setPrintHeader( false );
		$pdf->setPrintFooter( false );

		// add a page.
		$pdf->AddPage();

		/**
		 * Filter: Custom header.
		 */
		$custom_content = apply_filters(
			'mojito_shipping_ccr_pdf_custom_header',
			array(
				'content'  => '',
				'position' => 'L',
			)
		);
		if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
			$custom_content['position'] = 'L';
		}
		if ( ! empty( $custom_content['content'] ) ) {
			$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
		}

		/**
		 * Barcode
		 */
		$style = array();
		$pdf->write1DBarcode( $guide_number, 'C39', '', '', '', 16, 0.6, $style, 'N' );
		$pdf->writeHTML( $guide_number, true, false, true, false, 'C' );
		$pdf->writeHTML( '<br>', true, false, false, false, 'C' );

		if ( 'full' === get_option( 'mojito-shipping-ccr-pdf-export-content' ) ) {
			// translators: date.
			$pdf->writeHTML( sprintf( __( 'Created: %s', 'mojito-shipping' ), gmdate( 'd-m-Y' ) ), true, false, true, false, 'R' );
		}

		/**
		 * Filter: After barcode
		 */
		$custom_content = apply_filters(
			'mojito_shipping_ccr_pdf_after_barcode',
			array(
				'content'  => '',
				'position' => 'L',
			)
		);

		if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
			$custom_content['position'] = 'L';
		}
		if ( ! empty( $custom_content['content'] ) ) {
			$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
		}

		if ( 'full' === get_option( 'mojito-shipping-ccr-pdf-export-content' ) ) {

			/**
			 * Sender data
			 */
			$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<h2>' . __( 'Sender details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<b>' . __( 'Sender name:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-ccr-sender-name' ) );
			$pdf->writeHTML( '<b>' . __( 'Address:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-ccr-sender-address' ) );
			$pdf->writeHTML( '<b>' . __( 'Zip-code:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-ccr-sender-zip-code' ) );
			$pdf->writeHTML( '<b>' . __( 'Phone:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-ccr-sender-phone' ) );
			$pdf->writeHTML( '<b>' . __( 'Email:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-ccr-sender-email' ) );

			/**
			 * Filter: After Sender data
			 */
			$custom_content = apply_filters(
				'mojito_shipping_ccr_pdf_after_sender_data',
				array(
					'content'  => '',
					'position' => 'L',
				)
			);
			if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
				$custom_content['position'] = 'L';
			}
			if ( ! empty( $custom_content['content'] ) ) {
				$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
			}

			/**
			 * Recipient details
			 */

			// Full Name.
			$full_name = '';
			if ( ! empty( $order->get_shipping_first_name() ) && ! empty( $order->get_shipping_last_name() ) ) {
				$full_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
			} else {
				$full_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
			}

			// Company.
			$company = '';
			if ( ! empty( $order->get_shipping_company() ) ) {
				$company = $order->get_shipping_company();

			} elseif ( ! empty( $order->get_billing_company() ) ) {
				$company = $order->get_billing_company();
			} else {
				$company = false;
			}

			// Address.
			$address = $order->get_shipping_address_1() . ' ' . $order->get_shipping_address_2();
			if ( empty( $address ) ) {
				$address = $order->get_billing_address_1() . ' ' . $order->get_billing_address_2();
			}

			// City, State.
			$city    = '';
			$state   = '';
			$canton  = '';
			$distric = '';
			$states  = array(
				'SJ' => 'San José',
				'AL' => 'Alajuela',
				'CG' => 'Cartago',
				'HD' => 'Heredia',
				'GT' => 'Guanacaste',
				'PT' => 'Puntarenas',
				'LM' => 'Limón',
			);

			if ( ! empty( $order->get_shipping_city() ) ) {
				$city    = $order->get_shipping_city();
				$canton  = trim( explode( ',', $city )[0] );
				$distric = trim( explode( ',', $city )[1] );

			} elseif ( ! empty( $order->get_billing_city() ) ) {
				$city    = $order->get_billing_city();
				$canton  = trim( explode( ',', $city )[0] );
				$distric = trim( explode( ',', $city )[1] );

			} else {
				$city = false;
			}

			if ( ! empty( $order->get_shipping_state() ) ) {
				$state = $order->get_shipping_state();

			} elseif ( ! empty( $order->get_billing_state() ) ) {
				$state = $order->get_billing_state();

			} else {
				$state = false;
			}
			if ( array_key_exists( $state, $states ) ) {
				$state = $states[ $state ];
			}

			// Post code.
			$post_code = $order->get_shipping_postcode();
			if ( empty( $post_code ) ) {
				$post_code = $order->get_billing_postcode();
			}

			// HTML.
			$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<h2>' . __( 'Recipient details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<b>' . __( 'Recipient name:', 'mojito-shipping' ) . '</b> ' . $full_name );

			if ( false !== $company && ! empty( $company ) ) {
				$pdf->writeHTML( '<b>' . __( 'Company:', 'mojito-shipping' ) . '</b> ' . $company );
			}
			if ( false !== $state && ! empty( $state ) ) {
				$pdf->writeHTML( '<b>' . __( 'State:', 'mojito-shipping' ) . '</b> ' . $state );
			}
			if ( false !== $city && ! empty( $city ) ) {
				$pdf->writeHTML( '<b>' . __( 'Canton:', 'mojito-shipping' ) . '</b> ' . $canton );
				$pdf->writeHTML( '<b>' . __( 'Distric:', 'mojito-shipping' ) . '</b> ' . $distric );
			}

			$pdf->writeHTML( '<b>' . __( 'Address:', 'mojito-shipping' ) . '</b> ' . $address );
			$pdf->writeHTML( '<b>' . __( 'Zip-code:', 'mojito-shipping' ) . '</b> ' . $post_code );
			
			$dest_phone_number = $order->get_shipping_phone();
			$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
			$dest_phone_number = str_replace( '-', '', $dest_phone_number );

			if ( empty( $dest_phone_number ) ){
				$dest_phone_number = $order->get_billing_phone();
				$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
				$dest_phone_number = str_replace( '-', '', $dest_phone_number );
			}

			$pdf->writeHTML( '<b>' . __( 'Phone:', 'mojito-shipping' ) . '</b> ' . $dest_phone_number );

			/**
			 * Filter: After Recipient data
			 */
			$custom_content = apply_filters(
				'mojito_shipping_ccr_pdf_after_recipient_data',
				array(
					'content'  => '',
					'position' => 'L',
				)
			);
			if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
				$custom_content['position'] = 'L';
			}
			if ( ! empty( $custom_content['content'] ) ) {
				$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
			}

			/**
			 * Package content details
			 */
			if ( 'yes' === get_option( 'mojito-shipping-ccr-pdf-export-order-content', 'no' ) ) {
				$package_items = '';

				foreach ( $order->get_items() as $item_id => $item ) {

					$line  = $item->get_name();
					$line .= ' ( ';
					$line .= $item->get_quantity();
					$line .= ' ), ';

					$package_items .= $line;
				}

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

				$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
				$pdf->writeHTML( '<h2>' . __( 'Package details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
				$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
				$pdf->writeHTML( '<b>' . __( 'Details:', 'mojito-shipping' ) . '</b> ' . $package_items );

				/**
				 * Filter: After package content details
				 */
				$custom_content = apply_filters(
					'mojito_shipping_ccr_pdf_after_package_content',
					array(
						'content'  => '',
						'position' => 'L',
					)
				);
				if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
					$custom_content['position'] = 'L';
				}
				if ( ! empty( $custom_content['content'] ) ) {
					$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
				}
			}

			/**
			 * Client notes
			 */
			$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<h2>' . __( 'Client notes', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
			$pdf->writeHTML( '<b>' . __( 'Client note:', 'mojito-shipping' ) . '</b> ' . $order->get_customer_note() );

			/**
			 * Filter: After Client notes
			 */
			$custom_content = apply_filters(
				'mojito_shipping_ccr_pdf_after_client_notes',
				array(
					'content'  => '',
					'position' => 'L',
				)
			);

			// Backguards compatibility.
			$custom_content = apply_filters( 'mojito_shipping_ccr_pdf_after_package_data', $custom_content );

			if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
				$custom_content['position'] = 'L';
			}
			if ( ! empty( $custom_content['content'] ) ) {
				$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
			}

			/**
			 * Logos
			 */
			$logos_html = '<table><tr>';
			if ( 'yes' === get_option( 'mojito-shipping-ccr-pdf-export-ccr-logo' ) ) {

				$logo_file   = 'logo-correos-de-costa-rica.jpg';
				$logo_url    = apply_filters( 'mojito_shipping_ccr_pdf_ccr_logo_src', plugin_dir_url( __DIR__ ) . 'public/img/' . $logo_file );
				$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
				$logos_html .= '<td>' . $img . '</td>';
			}
			if ( 'yes' === get_option( 'mojito-shipping-ccr-pdf-export-site-logo' ) ) {

				$blog_id = ( is_multisite() ) ? get_current_blog_id() : 0;

				if ( has_custom_logo( $blog_id ) ) {

					$custom_logo_id = get_theme_mod( 'custom_logo' );
					$image          = wp_get_attachment_image_src( $custom_logo_id, 'full' );

					add_filter(
						'get_custom_logo',
						function ( $html, $blog_id ) {
							return str_replace( 'itemprop="logo"', '', $html );
						},
						10,
						2
					);

					$logo_url    = apply_filters( 'mojito_shipping_ccr_pdf_site_logo_src', $image[0] );
					$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
					$logos_html .= '<td>' . $img . '</td>';

				} else {

					$logo_url    = apply_filters( 'mojito_shipping_ccr_pdf_site_logo_src', '' );
					$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
					$logos_html .= '<td>' . $img . '</td>';
				}
			}
			$logos_html .= '</tr></table>';
			$pdf->writeHTML( '<div>' . $logos_html . '</div>', true, false, true, false, 'C' );
		}

		/**
		 * Save file
		 */
		$output = $pdf->Output( $file, 'S' );

		file_put_contents( $file, $output );

		$content = base64_encode( file_get_contents( $file ) );

		$url = $upload_dir['baseurl'] . '/mojito-shipping-tmp/' . $guide_number . ' .pdf';
		echo wp_json_encode(
			array(
				'url'          => $url,
				'content'      => $content,
				'guide_number' => $guide_number,
			)
		);

		wp_delete_file( $file );

		die();
	}

	/**
	 * Download the CCR PDF from the customer order details page.
	 *
	 * @return void
	 */
	public function ccr_pdf_download_customer() {

		$this->ccr_pdf_download( true );
	}

	/**
	 * Add CCR Pymexpress guide number after customer details
	 *
	 * @return void
	 */
	public function pymexpress_checkout_after_customer_details() {

		woocommerce_form_field(
			'mojito_shipping_pymexpress_guide_number',
			array(
				'type'              => 'text',
				'class'             => array( 'hidden' ),
				'default'           => $this->pymexpress_ws_client->generar_guia(),
				'custom_attributes' => array( 'readonly' => 'readonly' ),
			)
		);
	}

	/**
	 * Update meta, save guide number.
	 *
	 * @param Int $order_id Order ID.
	 * @return void
	 */
	public function pymexpress_checkout_update_order_meta_save_guide_number( $order_id ) {

		$order = wc_get_order( $order_id );

		if ( ! $order->has_shipping_method('mojito_shipping_pymexpress' ) ) {
			return;
		}

		if ( ! empty( $_POST['mojito_shipping_pymexpress_guide_number'] ) && ( $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) ) {
			$order->update_meta_data( 'mojito_shipping_pymexpress_guide_number', sanitize_text_field( $_POST['mojito_shipping_pymexpress_guide_number'] ) );
			$order->save();
		}
	}

	/**
	 * Thank you page
	 *
	 * @param Int     $order_id Order id.
	 * @param boolean $manual_request is a manual request?.
	 * @return void
	 */
	public function pymexpress_thankyou_log_send( $order_id, $manual_request = false ) {

		$order = wc_get_order( $order_id );

		/**
		 * Is a valid order?
		 */
		if ( ! $order instanceof \WC_Order ) {
			return;
		}

		$log_send = $order->get_meta( 'mojito_pymexpress_shipping_log', true );
		$details  = '';

		$items       = array();
		$weight_unit = get_option( 'woocommerce_weight_unit' );

		if ( ( $manual_request || empty( $log_send ) ) && $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {

			$full_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
			if ( 0 === strlen( trim( $full_name ) ) ) {
				$full_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
			}

			$address = $order->get_shipping_address_1();
			if ( ! empty( $order->get_shipping_address_2() ) ) {
				$address .= ' ' . $order->get_shipping_address_2();
			}

			foreach ( $order->get_items() as $key => $order_values ) {

				$product            = $order_values->get_product();
				$product_order_data = $order_values->get_data();
				$product_name       = $order_values->get_name();
				$product_weight     = ( $product && is_object( $product ) ) ? $product->get_weight() : 0;

				$items[] = array(
					'quantity' => $product_order_data['quantity'],
					'weight'   => $product_weight,
				);

				if ( empty( $details ) ) {
					$details = $product_name;
				} elseif ( $details !== $product_name ) {
					$details .= ', ' . $product_name;
				}
			}

			$shipping_weight = 0;
			foreach ( $items as $id => $data ) {

				$weight = $data['weight'];
				if ( ! is_numeric( $weight ) ) {
					/**
					 * 1 kg default weight
					 */
					$weight = 1000;
				}

				$product_weight   = $data['quantity'] * $weight;
				$shipping_weight += $product_weight;
			}

			if ( 'g' === $weight_unit ) {
				// no changes.
			} elseif ( 'kg' === $weight_unit ) {
				$shipping_weight = $shipping_weight * 1000;

			} elseif ( 'lbs' === $weight_unit ) {
				$shipping_weight = $shipping_weight / 0.0022046;

			} elseif ( 'oz' === $weight_unit ) {
				$shipping_weight = $shipping_weight / 0.035274;
			}

			/**
			 * If $order->get_shipping_postcode() is empty, then use get_billing_postcode()
			 */
			$post_code = $order->get_shipping_postcode();
			if ( empty( $post_code ) ) {
				$post_code = $order->get_billing_postcode();
			}

			if ( empty( $post_code ) ) {

				$find_address = new Mojito_Shipping_Address();
				$post_code    = $find_address->find_postcode_legacy( $order->get_shipping_state(), $order->get_shipping_city() );

				if ( empty( $post_code ) ) {
					$post_code = $find_address->find_postcode_legacy( $order->get_billing_state(), $order->get_billing_city() );
				}
			}

			/**	
			 * Remove letters from postcode
			 */
			$post_code = preg_replace( '/[^0-9]/', '', $post_code );


			$shipping_total = $order->get_shipping_total();

			/**
			 * Exchange rates
			 */
			if ( 'enable' === get_option( 'mojito-shipping-pymexpress-exchange-rate-enable', 'disabled' ) ) {

				$origin        = get_option( 'mojito-shipping-pymexpress-exchange-rate-origin', 'manual' );
				$exchange_rate = get_option( 'mojito-shipping-pymexpress-exchange-rate-rate', 620 );

				if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
					if ( 'automatic' === $origin ) {
						$exchange_object = new Mojito_Shipping_Exchange_Rate();
						$exchange_rate   = $exchange_object->get_exchange_rate_crc_usd();
					}
				}
				if ( $exchange_rate <= 0 ) {
					$exchange_rate = 1;
				}
				$shipping_total = $shipping_total * $exchange_rate;
			}

			if ( empty( $shipping_total ) || 0 === $shipping_total ) {
        		$shipping_total = 2000;
			}

			/**
			 * Check destination phone number
			 */
			$dest_phone_number = $order->get_shipping_phone();
			$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
			$dest_phone_number = str_replace( '-', '', $dest_phone_number );

			if ( empty( $dest_phone_number ) ){
				$dest_phone_number = $order->get_billing_phone();
				$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
				$dest_phone_number = str_replace( '-', '', $dest_phone_number );
			}

			if ( strpos( $dest_phone_number, '/') !== false ) {
				$dest_phone_number = explode( '/', $dest_phone_number );
				$dest_phone_number = $dest_phone_number[0];
			}


			if ( $shipping_weight <= 0){
				$shipping_weight = $shipping_weight * -1;
			}
			if ( $shipping_weight < 1000){
				$shipping_weight = 1000;
			}

			if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
				/**
				 * Filtros adicionales
				 */
				$post_code         = apply_filters( 'mojito_shipping_pymexpress_post_code', $post_code );
				$address           = apply_filters( 'mojito_shipping_pymexpress_dest_direction', $address );
				$full_name         = apply_filters( 'mojito_shipping_pymexpress_dest_name', $full_name );
				$dest_phone_number = apply_filters( 'mojito_shipping_pymexpress_dest_phone', $dest_phone_number );
				$post_code         = apply_filters( 'mojito_shipping_pymexpress_dest_zip', $post_code );
				$shipping_total    = apply_filters( 'mojito_shipping_pymexpress_amount', $shipping_total );
				$details           = apply_filters( 'mojito_shipping_pymexpress_details', $details );
				$shipping_weight   = apply_filters( 'mojito_shipping_pymexpress_weight', $shipping_weight );
			}

			$details = str_replace( ' & ', ' y ', $details );
			$details = str_replace( '&', '', $details );

			$guide_number  = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );
			$missing_data  = array();
			$missing_error = '';

			if ( empty( $guide_number ) ) {
				$missing_data[] = 'guide_number';
			}
			if ( empty( $post_code ) ) {
				$missing_data[] = 'postcode';
			}
			if ( empty( $address ) ) {
				$missing_data[] = 'address';
			}
			if ( empty( $full_name ) ) {
				$missing_data[] = 'full_name';
			}
			if ( empty( $dest_phone_number ) ) {
				$missing_data[] = 'phone';
			}
			if ( empty( $shipping_total ) ) {
				$missing_data[] = 'shipping_total';
			}
			if ( empty( $details ) ) {
				$missing_data[] = 'details';
			}
			if ( empty( $shipping_weight ) ) {
				$missing_data[] = 'shipping_weight';
			}

			if ( ! empty( $missing_data ) ) {
				$missing_error = sprintf(
					/* translators: %s: missing required shipping fields. */
					__( 'Correos de Costa Rica shipping registration skipped because required data is missing: %s', 'mojito-shipping' ),
					implode( ', ', $missing_data )
				);

				if ( $order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_error', true ) !== $missing_error ) {
					$order->add_order_note( $missing_error );
				}

				$order->update_meta_data( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_error', $missing_error );
				$order->update_meta_data( 'mojito_shipping_pymexpress_retry_reason', 'missing_required_data' );
				$order->update_meta_data( 'mojito_shipping_pymexpress_retry_after', time() + $this->pymexpress_get_retry_delay( 'missing_required_data' ) );
				$order->save();

				return false;
			}

			/**
			 * Filter to change address based on postcode
			 */
			$address = apply_filters( 'mojito_shipping_pymexpress_address', $address, $post_code );

			$comment_id = $order->add_order_note(
				__( 'Correos de Costa Rica Answer: ', 'mojito-shipping' ) .
					$this->pymexpress_ws_client->registro_envio(
						$order_id,
						array(
							'DEST_APARTADO'  => $post_code,
							'DEST_DIRECCION' => $address,
							'DEST_NOMBRE'    => $full_name,
							'DEST_TELEFONO'  => $dest_phone_number,
							'DEST_ZIP'       => $post_code,
							'ENVIO_ID'       => $guide_number,
							'MONTO_FLETE'    => $shipping_total,
							'OBSERVACIONES'  => $details,
							'PESO'           => $shipping_weight,
						)
					)
			);

				/**
				 * Try to send emails
				 */
				if ( ! empty( get_option( 'mojito-shipping-pymexpress-pdf-export-send-to-emails' ) ) ) {

					$notification_order = $order;
					if ( ! $this->pymexpress_should_send_pdf_email_for_order( $notification_order ) ) {
						return $comment_id;
					}

				$status = (int) $notification_order->get_meta( 'mojito_pymexpress_shipping_order_notificated', true );
				if ( 1 === $status ) {
					return $comment_id;
				}

				$emails  = str_replace( ' ', '', get_option( 'mojito-shipping-pymexpress-pdf-export-send-to-emails' ) );
				// translators: order id.
				$subject = sprintf( __( 'New Pymexpress guide for order: %s', 'mojito-shipping' ), $order_id );
				// translators: order id.
				$body    = sprintf( __( 'Please find attached the PDF Guide for the order %s', 'mojito-shipping' ), $order_id );
				$headers = array( 'Content-Type: text/html; charset=UTF-8' );
				$pdf     = $this->pymexpress_pdf_download( $order_id );
				if ( ! is_array( $pdf ) || empty( $pdf['path'] ) || ! is_string( $pdf['path'] ) || ! file_exists( $pdf['path'] ) ) {
					mojito_shipping_debug(
						sprintf(
							'Unable to attach the Pymexpress PDF for order %d because the file could not be generated.',
							(int) $order_id
						)
					);
					return $comment_id;
				}

				$file = $pdf['path'];

				$mail_sent = wp_mail( $emails, $subject, $body, $headers, $file );
				wp_delete_file( $file );

				if ( $mail_sent ) {
					$notification_order->update_meta_data( 'mojito_pymexpress_shipping_order_notificated', 1 );
					$notification_order->save();
				}
			}


			return $comment_id;
		}
	}

	/**
	 * Return the retry delay for a Pymexpress background task.
	 *
	 * @param string $reason Retry reason.
	 * @return int
	 */
	private function pymexpress_get_retry_delay( $reason = '' ) {

		switch ( $reason ) {
			case 'missing_required_data':
				return 12 * HOUR_IN_SECONDS;

			case 'guide_generation_failed':
				return 30 * MINUTE_IN_SECONDS;

			case 'registration_failed':
			default:
				return HOUR_IN_SECONDS;
		}
	}

	/**
	 * Check if an order is ready for the automatic Pymexpress cron process.
	 *
	 * @param mixed $order WooCommerce order.
	 * @return bool
	 */
	private function pymexpress_order_is_ready_for_cron( $order ) {

		if ( is_bool( $order ) || ! is_a( $order, 'WC_Order' ) ) {
			return false;
		}

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return false;
		}

		if ( in_array( $order->get_status(), array( 'failed', 'cancelled', 'refunded' ), true ) ) {
			return false;
		}

		$retry_after = (int) $order->get_meta( 'mojito_shipping_pymexpress_retry_after', true );
		if ( $retry_after > time() ) {
			return false;
		}

		return true;
	}

	/**
	 * Save retry metadata for the automatic Pymexpress cron process.
	 *
	 * @param \WC_Order $order Order object.
	 * @param string    $reason Retry reason.
	 * @param string    $message Retry message.
	 * @return void
	 */
	private function pymexpress_schedule_order_retry( $order, $reason = '', $message = '' ) {

		if ( is_bool( $order ) || ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		$order->update_meta_data( 'mojito_shipping_pymexpress_retry_reason', sanitize_key( $reason ) );
		$order->update_meta_data( 'mojito_shipping_pymexpress_retry_after', time() + $this->pymexpress_get_retry_delay( $reason ) );

		if ( ! empty( $message ) ) {
			$order->update_meta_data( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_error', $message );
		}

		$order->save();
	}

	/**
	 * Clear retry metadata for the automatic Pymexpress cron process.
	 *
	 * @param \WC_Order $order Order object.
	 * @return void
	 */
	private function pymexpress_clear_order_retry_state( $order ) {

		if ( is_bool( $order ) || ! is_a( $order, 'WC_Order' ) ) {
			return;
		}

		$order->delete_meta_data( 'mojito_shipping_pymexpress_retry_after' );
		$order->delete_meta_data( 'mojito_shipping_pymexpress_retry_reason' );
		$order->delete_meta_data( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_error' );
		$order->save();
	}

	public function pymexpress_order_is_completed( $order_id, $old_status='', $new_status='', $order='' ) {

		$order = wc_get_order( $order_id );

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return;
		}
		
		$reponse_code = $order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code', true );
		if ( $reponse_code == '00' ) {
			return;
		}
		
		if ( in_array( $order->get_status(), array( 'completed', 'on-hold' ) ) ) {
			$this->pymexpress_thankyou_log_send( $order_id );
		}
	}

	/**
	 * Add info to order data.
	 *
	 * @param Order $order Order object.
	 * @return void
	 */
	public function pymexpress_order_items_table_success_meta( $order ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return;
		}

		$order_id              = $order->get_id();
		$guide_number          = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );
		$ccr_msj_email_label   = get_option( 'mojito-shipping-pymexpress-mail-orders-name' );
		$ccr_msj_email_content = get_option( 'mojito-shipping-pymexpress-mail-orders-message' );

		if ( ! empty( $guide_number ) ) {

			$ccr_msj_email_label   = ( ! empty( $ccr_msj_email_label ) ) ? $ccr_msj_email_label : __( 'Correos de Costa Rica Tracking code', 'mojito-shipping' );
			$ccr_msj_email_content = ( ! empty( $ccr_msj_email_content ) ) ? $ccr_msj_email_content : __( 'Guide number for packages tracking', 'mojito-shipping' );

			$html  = '';
			$html .= '<tr class="mojito-pymexpress-ws order_item">';
			$html .= '<td scope="row">';
			$html .= '<strong class="guide-number-title">' . $ccr_msj_email_label . ':</strong>';
			$html .= '</td>';
			$html .= '<td>';
			$html .= '<strong><span class="guide-number">' . $guide_number . '</span></strong>';
			$html .= '<small>  ' . $ccr_msj_email_content . '</small>';
			$html .= '</td>';
			$html .= '</tr>';

			/**
			 * Tracking and PDF Download
			 */

			 if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

				if ( 'yes' === get_option( 'mojito-shipping-pymexpress-tracking-user-order-details' ) ) {

					$response = $this->pymexpress_ws_client->get_tracking( $guide_number );

					$html .= '<tr class="mojito-pymexpress-ws-tracking order_item">';
					$html .= '<td scope="row">';
					$html .= '<strong class="guide-number-title">' . __( 'Tracking', 'mojito-shipping' ) . ':</strong>';
					$html .= '</td>';
					$html .= '<td>';

					$html .= '<a class="mojito-shipping-toggle-tracking">' . __( 'Show tracking details', 'mojito-shipping' ) . '</a>';
					$html .= '<table class="tracking-details">';
					$html .= '<tr>';
					$html .= '<td>' . __( 'Date', 'mojito-shipping' ) . '</td>';
					$html .= '<td>' . __( 'Event', 'mojito-shipping' ) . '</td>';
					$html .= '<td>' . __( 'Location', 'mojito-shipping' ) . '</td>';
					$html .= '</tr>';

					$response = json_decode( $response, true );

					if ( ! empty( $response['eventos'] ) && is_array( $response['eventos'] ) ) {
						foreach ( $response['eventos'] as $key => $event ) {

							$fecha_hora = ( ! empty( $event['fecha-hora'] ) ) ? $event['fecha-hora'] : '';
							$evento     = ( ! empty( $event['evento'] ) ) ? $event['evento'] : '';
							$unidad     = ( ! empty( $event['unidad'] ) ) ? $event['unidad'] : '';

							$html .= '<tr>';
							$html .= '<td>' . $fecha_hora . '</td>';
							$html .= '<td>' . $evento . '</td>';
							$html .= '<td>' . $unidad . '</td>';
							$html .= '</tr>';
						}
					}

					$html .= '</table>';

					$html .= '</td>';
					$html .= '</tr>';
				}

				if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-in-customer-order' ) ) {

					$html .= '<tr class="mojito-pymexpress-download-pdf order_item">';
					$html .= '<td scope="row">';
					$html .= '<strong class="guide-number-title">' . __( 'Download Correos de Costa Rica Guide (PDF)', 'mojito-shipping' ) . ':</strong>';
					$html .= '</td>';
					$html .= '<td>';
					$html .= '<a id="' . esc_attr( $order_id ) . '" class="mojito-shipping-download-customer-pdf" data-order-id="' . esc_attr( $order_id ) . '" data-action="mojito_shipping_pymexpress_download_pdf_customer">' . esc_html( $guide_number ) . '</a>';
					$html .= '</td>';
					$html .= '</tr>';
				}
			}

			echo $html;
		}
	}

	/**
	 * Data after billing address.
	 *
	 * @param object $order Order id.
	 * @return void
	 */
	public function pymexpress_admin_order_data_after_billing_address( $order ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return;
		}

		$order_id     = $order->get_id();
		$guide_number = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );
		$reponse_code = $order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code', true );

		$html  = '';
		$html .= '<tr class="mojito-pymexpress-ws">';
		$html .= '<td colspan="2">';
		$html .= '<div class="mojito-pymexpress-ws">';
		$html .= '<span class="title" style="">' . __( 'Guide number from Correos de Costa Rica: ', 'mojito-shipping' ) . '</span>';

		if ( empty( $guide_number ) ) {
			$html .= '<a id="' . $order_id . '" class="mojito-shipping-pymexpress-manual-request"> ' . __( 'Click to request. ', 'mojito-shipping' ) . '</a>';

		} elseif ( ! empty( $reponse_code ) && ( '00' !== $reponse_code && '36' !== $reponse_code ) ) {
			$html .= '<a id="' . $order_id . '" class="mojito-shipping-pymexpress-manual-register"> ' . __( 'Click to request. ', 'mojito-shipping' ) . '</a>';

		} else {

			$html .= '<p> ' . $guide_number . ' </p>';
			$html .= '<a id="' . $order_id . '" class="download mojito-shipping-pymexpress-download-pdf">';
			$html .= '<img src="' . plugin_dir_url( __DIR__ ) . 'admin/img/download.svg">';
			$html .= '</a>';

		}
		$html .= '</div>';
		$html .= '</td>';
		$html .= '</tr>';
		echo $html;

	}

	/**
	 * Add tracking to admin
	 *
	 * @return void
	 */
	public function pymexpress_admin_order_tracking_data() {

		if ( ! isset( $_GET['post'] ) ) {
			return;
		}

		$post_id = sanitize_text_field( $_GET['post'] );
		if ( ! is_numeric( $post_id ) ) {
			return;
		}

		$order = wc_get_order( $post_id );

		if ( is_bool( $order ) ) {
			return;
		}

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return;
		}

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

			if ( 'yes' === get_option( 'mojito-shipping-pymexpress-tracking-admin-order-details' ) ) {

				add_meta_box(
					'pymexpress_admin_order_tracking_data',
					__( 'Package tracking', 'mojito-shipping' ),
					function () use ( $order ) {

						$order_id     = $order->get_id();
						$guide_number = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );

						$response = $this->pymexpress_ws_client->get_tracking( $guide_number );

						$html  = '';
						$html .= '<table class="tracking-details-admin">';
						$html .= '<tr>';
						$html .= '<td>' . __( 'Date', 'mojito-shipping' ) . '</td>';
						$html .= '<td>' . __( 'Event', 'mojito-shipping' ) . '</td>';
						$html .= '<td>' . __( 'Location', 'mojito-shipping' ) . '</td>';
						$html .= '</tr>';

						$response = json_decode( $response, true );

						if ( is_array( $response['eventos'] ) ) {
							foreach ( $response['eventos'] as $key => $event ) {

								$fecha_hora = ( ! empty( $event['fecha-hora'] ) ) ? $event['fecha-hora'] : '';
								$evento     = ( ! empty( $event['evento'] ) ) ? $event['evento'] : '';
								$unidad     = ( ! empty( $event['unidad'] ) ) ? $event['unidad'] : '';

								$html .= '<tr>';
								$html .= '<td>' . $fecha_hora . '</td>';
								$html .= '<td>' . $evento . '</td>';
								$html .= '<td>' . $unidad . '</td>';
								$html .= '</tr>';
							}
						}

						$html .= '</table>';
						echo $html;
					},
					null,
					'normal'
				);
			}
		}

	}

	/**
	 * Add data to tabmel in email-
	 *
	 * @param Object $order Order.
	 * @param bool   $sent_to_admin Send to admin.
	 * @return void
	 */
	public function pymexpress_email_after_order_table_add_guide_number( $order, $sent_to_admin ) {

		if ( ! $order->has_shipping_method( 'mojito_shipping_pymexpress' ) ) {
			return;
		}

		/**
		 * If order is Failed or Canceled, then return.
		 */
		if ( in_array( $order->get_status(), array( 'failed', 'canceled' ), true ) ) {
			return;
		}

		$order_id              = $order->get_id();
		$guide_number          = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );
		$ccr_msj_email_label   = get_option( 'mojito-shipping-pymexpress-mail-orders-name' );
		$ccr_msj_email_content = get_option( 'mojito-shipping-pymexpress-mail-orders-message' );

		if ( ! empty( $guide_number ) ) {

			$ccr_msj_email_label   = ( ! empty( $ccr_msj_email_label ) ) ? $ccr_msj_email_label : '';
			$ccr_msj_email_content = ( ! empty( $ccr_msj_email_content ) ) ? $ccr_msj_email_content : '';

			$ccr_tracking_url = apply_filters( 'mojito_shipping_pymexpress_tracking_url', 'https://correos.go.cr/rastreo/' );

			$html  = '';
			$html .= '<table class="td" cellspacing="0" cellpadding="6" style="width: 100%; font-family: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif;" border="1">';
			$html .= '<tr class="mojito-shipping-pymexpress-payment-gateway">';
			$html .= '<td class="td" scope="row" colspan="2">';
			$html .= '<strong class="title" style="display: block;">' . $ccr_msj_email_label . '</strong>';
			$html .= '<span style="font-size: 12px;">' . $guide_number . '</span>';
			$html .= '<span style="font-size: 12px; display: block;"><a href="' . $ccr_tracking_url . '">' . $ccr_msj_email_content . '</a></span>';
			$html .= '</td>';
			$html .= '</tr>';
			$html .= '</table>';
			echo $html;
		}
	}

	/**
	 * Manual request
	 * Useful when guide number request fail during the shopping
	 */
	public function pymexpress_manual_request() {

		$order        = $this->get_admin_ajax_order_from_request();
		$order_id     = $order->get_id();
		$guide_number = $this->pymexpress_ws_client->generar_guia();

		$order->update_meta_data(
			'mojito_shipping_pymexpress_guide_number',
			sanitize_text_field( $guide_number )
		);
		$order->save();

		$comment_id = $this->pymexpress_thankyou_log_send( $order_id, true );

		if ( is_numeric( $comment_id ) ) {
			echo wp_json_encode( true );
			die();
		} else {
			echo wp_json_encode( false );
			die();
		}
	}

	/**
	 * Manual register
	 * Useful when register process fail during the shopping
	 */
	public function pymexpress_manual_register() {

		$order_id   = $this->get_admin_ajax_order_from_request()->get_id();
		$comment_id = $this->pymexpress_thankyou_log_send( $order_id, true );

		if ( is_numeric( $comment_id ) ) {
			echo wp_json_encode( true );
			die();
		} else {
			echo wp_json_encode( false );
			die();
		}
	}

	/**
	 * Get Pymexpress recipient details for PDF rendering.
	 *
	 * @param \WC_Order $order Order object.
	 * @return array
	 */
	private function pymexpress_get_pdf_recipient_context( $order ) {

		$states = array(
			'SJ' => 'San Jose',
			'AL' => 'Alajuela',
			'CG' => 'Cartago',
			'HD' => 'Heredia',
			'GT' => 'Guanacaste',
			'PT' => 'Puntarenas',
			'LM' => 'Limon',
		);

		$full_name = trim( $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name() );
		if ( empty( $full_name ) ) {
			$full_name = trim( $order->get_billing_first_name() . ' ' . $order->get_billing_last_name() );
		}

		$company = $order->get_shipping_company();
		if ( empty( $company ) ) {
			$company = $order->get_billing_company();
		}

		$address = trim( $order->get_shipping_address_1() . ' ' . $order->get_shipping_address_2() );
		if ( empty( $address ) ) {
			$address = trim( $order->get_billing_address_1() . ' ' . $order->get_billing_address_2() );
		}

		$city = $order->get_shipping_city();
		if ( empty( $city ) ) {
			$city = $order->get_billing_city();
		}

		$canton   = '';
		$district = '';
		if ( ! empty( $city ) ) {
			$city_parts = array_map( 'trim', explode( ',', $city, 2 ) );
			$canton     = $city_parts[0] ?? '';
			$district   = $city_parts[1] ?? '';
		}

		$state = $order->get_shipping_state();
		if ( empty( $state ) ) {
			$state = $order->get_billing_state();
		}
		if ( isset( $states[ $state ] ) ) {
			$state = $states[ $state ];
		}

		$post_code = trim( $order->get_shipping_postcode() );
		if ( empty( $post_code ) ) {
			$post_code = trim( $order->get_billing_postcode() );
		}

		$phone = $order->get_shipping_phone();
		$phone = str_replace( array( ' ', '-' ), '', $phone );
		if ( empty( $phone ) ) {
			$phone = $order->get_billing_phone();
			$phone = str_replace( array( ' ', '-' ), '', $phone );
		}
		if ( false !== strpos( $phone, '/' ) ) {
			$phone = explode( '/', $phone );
			$phone = $phone[0];
		}

		return array(
			'full_name' => $full_name,
			'company'   => $company,
			'address'   => $address,
			'state'     => $state,
			'canton'    => $canton,
			'district'  => $district,
			'post_code' => $post_code,
			'phone'     => $phone,
		);
	}

	/**
	 * Get Pymexpress sender details for PDF rendering.
	 *
	 * @return array
	 */
	private function pymexpress_get_pdf_sender_context() {

		return array(
			'name'      => get_option( 'mojito-shipping-pymexpress-sender-name' ),
			'address'   => get_option( 'mojito-shipping-pymexpress-sender-address' ),
			'post_code' => get_option( 'mojito-shipping-pymexpress-sender-zip-code' ),
			'phone'     => get_option( 'mojito-shipping-pymexpress-sender-phone' ),
			'email'     => get_option( 'mojito-shipping-pymexpress-sender-email' ),
		);
	}

	/**
	 * Get a printable summary of the order items for PDF rendering.
	 *
	 * @param \WC_Order $order Order object.
	 * @return string
	 */
	private function pymexpress_get_pdf_package_items_summary( $order ) {

		$package_items = array();

		foreach ( $order->get_items() as $item_id => $item ) {
			$line           = $item->get_name();
			$variant_values = array();
			$attribute_map  = array(
				get_option( 'mojito-shipping-pymexpress-pdf-export-first-attribute', 'pa_color' ),
				get_option( 'mojito-shipping-pymexpress-pdf-export-second-attribute', 'pa_size' ),
				get_option( 'mojito-shipping-pymexpress-pdf-export-third-attribute', 'pa_weight' ),
				get_option( 'mojito-shipping-pymexpress-pdf-export-fourth-attribute', 'pa_material' ),
			);

			foreach ( $attribute_map as $attribute_slug ) {
				if ( empty( $attribute_slug ) ) {
					continue;
				}

				$attribute_value = $item->get_meta( $attribute_slug );
				if ( ! empty( $attribute_value ) ) {
					$variant_values[] = $attribute_value;
				}
			}

			if ( ! empty( $variant_values ) ) {
				$line .= ' (' . implode( ', ', $variant_values ) . ')';
			}

			$line .= ' x ' . $item->get_quantity();
			$package_items[] = $line;
		}

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

	/**
	 * Limit a PDF text field to a safe length.
	 *
	 * @param string $text Text.
	 * @param int    $max_length Max length.
	 * @return string
	 */
	private function pymexpress_limit_pdf_text( $text, $max_length = 0 ) {

		$text = trim( wp_strip_all_tags( (string) $text ) );
		if ( $max_length <= 0 || '' === $text ) {
			return $text;
		}

		if ( function_exists( 'mb_strlen' ) && function_exists( 'mb_substr' ) ) {
			if ( mb_strlen( $text, 'UTF-8' ) > $max_length ) {
				return rtrim( mb_substr( $text, 0, max( 0, $max_length - 3 ), 'UTF-8' ) ) . '...';
			}

			return $text;
		}

		if ( strlen( $text ) > $max_length ) {
			return rtrim( substr( $text, 0, max( 0, $max_length - 3 ) ) ) . '...';
		}

		return $text;
	}

	/**
	 * Render a section in the 4x6 thermal label PDF.
	 *
	 * @param \TCPDF $pdf PDF object.
	 * @param string $title Section title.
	 * @param array  $lines Section lines.
	 * @return void
	 */
	private function pymexpress_write_4x6_pdf_section( $pdf, $title, $lines ) {

		$lines = array_values(
			array_filter(
				array_map(
					function ( $line ) {
						return trim( (string) $line );
					},
					(array) $lines
				)
			)
		);

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

		$pdf->Ln( 1.2 );
		$pdf->SetFont( 'helvetica', 'B', 10 );
		$pdf->Cell( 0, 4.5, $title, 0, 1, 'C' );
		$pdf->SetFont( 'helvetica', '', 9 );

		foreach ( $lines as $line ) {
			$pdf->MultiCell( 0, 4.3, $line, 0, 'L', false, 1 );
		}
	}

	/**
	 * Render a 4x6 thermal label for Pymexpress PDFs generated by Mojito.
	 *
	 * @param \TCPDF   $pdf PDF object.
	 * @param \WC_Order $order Order object.
	 * @param string   $guide_number Guide number.
	 * @return void
	 */
	private function pymexpress_render_4x6_pdf( $pdf, $order, $guide_number ) {

		$pdf_content  = get_option( 'mojito-shipping-pymexpress-pdf-export-content', 'full' );
		$recipient    = $this->pymexpress_get_pdf_recipient_context( $order );
		$sender       = $this->pymexpress_get_pdf_sender_context();
		$package_text = '';
		$client_note  = '';

		if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-order-content', 'no' ) ) {
			$package_text = $this->pymexpress_limit_pdf_text( $this->pymexpress_get_pdf_package_items_summary( $order ), 260 );
		}

		if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-client-note', 'no' ) ) {
			$client_note = $this->pymexpress_limit_pdf_text( $order->get_customer_note(), 160 );
		}

		$pdf->AddPage();

		$style = array(
			'position'    => '',
			'align'       => 'C',
			'stretch'     => true,
			'fitwidth'    => true,
			'border'      => false,
			'padding'     => 0,
			'fgcolor'     => array( 0, 0, 0 ),
			'bgcolor'     => false,
			'text'        => false,
			'font'        => 'helvetica',
			'fontsize'    => 8,
			'stretchtext' => 4,
		);

		$pdf->SetFont( 'helvetica', '', 10 );
		$pdf->write1DBarcode( $guide_number, 'C39', '', '', '', 16, 0.85, $style, 'N' );
		$pdf->Ln( 1 );
		$pdf->SetFont( 'helvetica', 'B', 12 );
		$pdf->Cell( 0, 5, $guide_number, 0, 1, 'C' );
		$pdf->SetFont( 'helvetica', '', 7 );
		$pdf->Cell( 0, 4, sprintf( __( 'Created: %s', 'mojito-shipping' ), gmdate( 'd-m-Y' ) ), 0, 1, 'R' );

		if ( 'only-barcode' === $pdf_content ) {
			return;
		}

		$pdf->Ln( 1.2 );
		$pdf->SetFont( 'helvetica', 'B', 10 );
		$pdf->Cell( 0, 4.5, __( 'Recipient details', 'mojito-shipping' ), 0, 1, 'C' );

		if ( ! empty( $recipient['full_name'] ) ) {
			$pdf->SetFont( 'helvetica', 'B', 12 );
			$pdf->MultiCell( 0, 5.2, $recipient['full_name'], 0, 'L', false, 1 );
		}

		$recipient_lines = array();
		if ( ! empty( $recipient['company'] ) ) {
			$recipient_lines[] = sprintf( __( 'Company: %s', 'mojito-shipping' ), $recipient['company'] );
		}
		if ( ! empty( $recipient['state'] ) ) {
			$recipient_lines[] = sprintf( __( 'State: %s', 'mojito-shipping' ), $recipient['state'] );
		}
		if ( ! empty( $recipient['canton'] ) ) {
			$recipient_lines[] = sprintf( __( 'Canton: %s', 'mojito-shipping' ), $recipient['canton'] );
		}
		if ( ! empty( $recipient['district'] ) ) {
			$recipient_lines[] = sprintf( __( 'Distric: %s', 'mojito-shipping' ), $recipient['district'] );
		}
		if ( ! empty( $recipient['address'] ) ) {
			$recipient_lines[] = sprintf( __( 'Address: %s', 'mojito-shipping' ), $recipient['address'] );
		}
		if ( ! empty( $recipient['post_code'] ) ) {
			$recipient_lines[] = sprintf( __( 'Zip-code: %s', 'mojito-shipping' ), $recipient['post_code'] );
		}
		if ( ! empty( $recipient['phone'] ) ) {
			$recipient_lines[] = sprintf( __( 'Phone: %s', 'mojito-shipping' ), $recipient['phone'] );
		}

		$pdf->SetFont( 'helvetica', '', 9 );
		foreach ( $recipient_lines as $line ) {
			$pdf->MultiCell( 0, 4.3, $line, 0, 'L', false, 1 );
		}

		if ( 'full' !== $pdf_content ) {
			return;
		}

		$this->pymexpress_write_4x6_pdf_section(
			$pdf,
			__( 'Sender details', 'mojito-shipping' ),
			array(
				sprintf( __( 'Sender name: %s', 'mojito-shipping' ), $sender['name'] ),
				sprintf( __( 'Address: %s', 'mojito-shipping' ), $sender['address'] ),
				sprintf( __( 'Zip-code: %s', 'mojito-shipping' ), $sender['post_code'] ),
				sprintf( __( 'Phone: %s', 'mojito-shipping' ), $sender['phone'] ),
				sprintf( __( 'Email: %s', 'mojito-shipping' ), $sender['email'] ),
			)
		);

		if ( ! empty( $package_text ) ) {
			$this->pymexpress_write_4x6_pdf_section(
				$pdf,
				__( 'Package details', 'mojito-shipping' ),
				array(
					sprintf( __( 'Details: %s', 'mojito-shipping' ), $package_text ),
				)
			);
		}

		if ( ! empty( $client_note ) ) {
			$this->pymexpress_write_4x6_pdf_section(
				$pdf,
				__( 'Client notes', 'mojito-shipping' ),
				array(
					sprintf( __( 'Client note: %s', 'mojito-shipping' ), $client_note ),
				)
			);
		}
	}

	/**
	 * Download PDF
	 * Download generated pdf with the guide number
	 */
	public function pymexpress_pdf_download( $order_id = '', $customer_request = false ) {

		$ajax_call = false;
		if ( empty( $order_id ) ) {

			$ajax_call = true;

			if ( $customer_request ) {
				$order = $this->get_customer_ajax_order_from_request();
			} else {
				$order = $this->get_admin_ajax_order_from_request();
			}

			$order_id = $order->get_id();
		}

		if ( ! is_numeric( $order_id ) ) {
			echo wp_json_encode( false );
			die();
		}

		/**
		 * Validate order
		 */
		if ( ! isset( $order ) || ! $order instanceof \WC_Order ) {
			$order = \wc_get_order( $order_id );
		}

		/**
		 * Is a valid order?
		 */
		if ( is_bool( $order ) ) {
			return;
		}

		/**
		 * Validate license
		 */
		if ( 0 == get_option('mojito-shipping-premium-valid-license', 0) ) {
			return;
		}

		/**
		 * TMP folder
		 */
		$tmp_dir    = '';
		$upload_dir = wp_upload_dir();

		if ( ! empty( $upload_dir['error'] ) ) {
			$tmp_dir = get_temp_dir();
		} else {
			$tmp_dir = $upload_dir['basedir'];
		}

		$tmp_dir .= '/mojito-shipping-tmp/';

		/**
		 * Guide number
		 */
		$guide_number = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );

		/**
		 * Filename
		 */
		$file = $tmp_dir . $guide_number . '.pdf';

		/**
		 * PDF origin is pymexpress?
		 */
		if ( 'mojito' === get_option( 'mojito-shipping-pymexpress-pdf-export-origin', 'mojito' ) ) {

			$pdf_paper_size = get_option( 'mojito-shipping-pymexpress-pdf-export-paper-size', 'letter' );
	
			/**
			 * Check if folder exists
			 */
			if ( ! is_dir( $tmp_dir ) ) {
				// dir doesn't exist, make it.
				mkdir( $tmp_dir );
			}
	
			/**
			 * Check index for tmp folder
			 */
			if ( ! file_exists( $tmp_dir . 'index.php' ) ) {
				file_put_contents( $tmp_dir . 'index.php', "<?php \n" );
			}

			if ( 'label-4x6' === $pdf_paper_size ) {

				/**
				 * Create 4x6 thermal label PDF.
				 */
				$pdf = new \TCPDF( 'P', 'mm', array( 101.6, 152.4 ), true, 'UTF-8', false );
				$pdf->setPrintHeader( false );
				$pdf->setPrintFooter( false );
				$pdf->SetMargins( 6, 6, 6 );
				$pdf->SetAutoPageBreak( true, 6 );
				$pdf->SetCreator( 'Mojito Shipping' );
				$pdf->SetAuthor( 'Mojito Shipping' );
				$pdf->SetTitle( $guide_number );

				$this->pymexpress_render_4x6_pdf( $pdf, $order, $guide_number );

			} else {

				/**
				 * Create PDF
				 */
				$pdf = new \TCPDF( PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false );
	
				// remove default header/footer.
				$pdf->setPrintHeader( false );
				$pdf->setPrintFooter( false );
	
				// add a page.
				$pdf->AddPage();
	
				/**
				 * Filter: Custom header.
				 */
				$custom_content = apply_filters(
					'mojito_shipping_pymexpress_pdf_custom_header',
					array(
						'content'  => '',
						'position' => 'L',
					)
				);
				if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
					$custom_content['position'] = 'L';
				}
				if ( ! empty( $custom_content['content'] ) ) {
					$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
				}
	
				/**
				 * Barcode
				 */
				$style = array();
				$pdf->write1DBarcode( $guide_number, 'C39', '', '', '', 16, 0.6, $style, 'N' );
				$pdf->writeHTML( $guide_number, true, false, true, false, 'C' );
				$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
	
				if ( 'full' === get_option( 'mojito-shipping-pymexpress-pdf-export-content' ) ) {
					// translators: date.
					$pdf->writeHTML( sprintf( __( 'Created: %s', 'mojito-shipping' ), gmdate( 'd-m-Y' ) ), true, false, true, false, 'R' );
				}
	
				/**
				 * Filter: After barcode
				 */
				$custom_content = apply_filters(
					'mojito_shipping_pymexpress_pdf_after_barcode',
					array(
						'content'  => '',
						'position' => 'L',
					)
				);
	
				if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
					$custom_content['position'] = 'L';
				}
				if ( ! empty( $custom_content['content'] ) ) {
					$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
				}
	
				if ( 'full' === get_option( 'mojito-shipping-pymexpress-pdf-export-content' ) ) {
	
					/**
					 * Sender data
					 */
					$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<h2>' . __( 'Sender details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<b>' . __( 'Sender name:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-pymexpress-sender-name' ) );
					$pdf->writeHTML( '<b>' . __( 'Address:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-pymexpress-sender-address' ) );
					$pdf->writeHTML( '<b>' . __( 'Zip-code:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-pymexpress-sender-zip-code' ) );
					$pdf->writeHTML( '<b>' . __( 'Phone:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-pymexpress-sender-phone' ) );
					$pdf->writeHTML( '<b>' . __( 'Email:', 'mojito-shipping' ) . '</b> ' . get_option( 'mojito-shipping-pymexpress-sender-email' ) );
	
					/**
					 * Filter: After Sender data
					 */
					$custom_content = apply_filters(
						'mojito_shipping_pymexpress_pdf_after_sender_data',
						array(
							'content'  => '',
							'position' => 'L',
						)
					);
					if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
						$custom_content['position'] = 'L';
					}
					if ( ! empty( $custom_content['content'] ) ) {
						$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
					}
	
					/**
					 * Recipient details
					 */
	
					// Full Name.
					$full_name = '';
					if ( ! empty( $order->get_shipping_first_name() ) && ! empty( $order->get_shipping_last_name() ) ) {
						$full_name = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
					} else {
						$full_name = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
					}
	
					// Company.
					$company = '';
					if ( ! empty( $order->get_shipping_company() ) ) {
						$company = $order->get_shipping_company();
	
					} elseif ( ! empty( $order->get_billing_company() ) ) {
						$company = $order->get_billing_company();
					} else {
						$company = false;
					}
	
					// Address.
					$address = $order->get_shipping_address_1() . ' ' . $order->get_shipping_address_2();
					if ( empty( $address ) ) {
						$address = $order->get_billing_address_1() . ' ' . $order->get_billing_address_2();
					}
	
					// City, State.
					$city    = '';
					$state   = '';
					$canton  = '';
					$distric = '';
					$states  = array(
						'SJ' => 'San José',
						'AL' => 'Alajuela',
						'CG' => 'Cartago',
						'HD' => 'Heredia',
						'GT' => 'Guanacaste',
						'PT' => 'Puntarenas',
						'LM' => 'Limón',
					);
	
					if ( ! empty( $order->get_shipping_city() ) ) {
						$city    = $order->get_shipping_city();
						$canton  = trim( explode( ',', $city )[0] );
						$distric = trim( explode( ',', $city )[1] );
	
					} elseif ( ! empty( $order->get_billing_city() ) ) {
						$city    = $order->get_billing_city();
						$canton  = trim( explode( ',', $city )[0] );
						$distric = trim( explode( ',', $city )[1] );
	
					} else {
						$city = false;
					}
	
					if ( ! empty( $order->get_shipping_state() ) ) {
						$state = $order->get_shipping_state();
	
					} elseif ( ! empty( $order->get_billing_state() ) ) {
						$state = $order->get_billing_state();
	
					} else {
						$state = false;
					}
					if ( array_key_exists( $state, $states ) ) {
						$state = $states[ $state ];
					}
	
					// Post code.
					$post_code = trim($order->get_shipping_postcode());
					if ( empty( $post_code ) ) {
						$post_code = trim($order->get_billing_postcode());
					}
	
					// HTML.
					$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<h2>' . __( 'Recipient details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
					$pdf->writeHTML( '<b>' . __( 'Recipient name:', 'mojito-shipping' ) . '</b> ' . $full_name );
	
					if ( false !== $company && ! empty( $company ) ) {
						$pdf->writeHTML( '<b>' . __( 'Company:', 'mojito-shipping' ) . '</b> ' . $company );
					}
					if ( false !== $state && ! empty( $state ) ) {
						$pdf->writeHTML( '<b>' . __( 'State:', 'mojito-shipping' ) . '</b> ' . $state );
					}
					if ( false !== $city && ! empty( $city ) ) {
						$pdf->writeHTML( '<b>' . __( 'Canton:', 'mojito-shipping' ) . '</b> ' . $canton );
						$pdf->writeHTML( '<b>' . __( 'Distric:', 'mojito-shipping' ) . '</b> ' . $distric );
					}
	
					$pdf->writeHTML( '<b>' . __( 'Address:', 'mojito-shipping' ) . '</b> ' . $address );
					$pdf->writeHTML( '<b>' . __( 'Zip-code:', 'mojito-shipping' ) . '</b> ' . $post_code );
					
					$dest_phone_number = $order->get_shipping_phone();
					$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
					$dest_phone_number = str_replace( '-', '', $dest_phone_number );
	
					if ( empty( $dest_phone_number ) ){
						$dest_phone_number = $order->get_billing_phone();
						$dest_phone_number = str_replace( ' ', '', $dest_phone_number );
						$dest_phone_number = str_replace( '-', '', $dest_phone_number );
					}
	
					$pdf->writeHTML( '<b>' . __( 'Phone:', 'mojito-shipping' ) . '</b> ' . $dest_phone_number );
	
					/**
					 * Filter: After Recipient data
					 */
					$custom_content = apply_filters(
						'mojito_shipping_pymexpress_pdf_after_recipient_data',
						array(
							'content'  => '',
							'position' => 'L',
						)
					);
					if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
						$custom_content['position'] = 'L';
					}
					if ( ! empty( $custom_content['content'] ) ) {
						$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
					}
	
					/**
					 * Package content details
					 */
					if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-order-content', 'no' ) ) {
						$package_items = '';
	
						foreach ( $order->get_items() as $item_id => $item ) {
	
							$add_variant_to_line = false;
							$variant_line = '';
							$line  = $item->get_name();

							// Buscar la talla y el color entre los meta datos
							$first_attribute_slug = get_option( 'mojito-shipping-pymexpress-pdf-export-first-attribute', 'pa_color' );
							if ( ! empty( $first_attribute_slug )) {
								$first_attribute_value = $item->get_meta($first_attribute_slug);
								if ( ! empty( $first_attribute_value )) {
									$variant_line .= $first_attribute_value;
									$add_variant_to_line = true;
								}
							}
							$second_attribute_slug = get_option( 'mojito-shipping-pymexpress-pdf-export-second-attribute', 'pa_size' );
							if ( ! empty( $second_attribute_slug )) {
								$second_attribute_value = $item->get_meta($second_attribute_slug);
								if ( ! empty( $second_attribute_value )) {
									if ( ! empty( $first_attribute_value )) {
										$variant_line .= ', ';
									}
									$variant_line .= $second_attribute_value;
									$add_variant_to_line = true;
								}
							}
							$third_attribute_slug = get_option( 'mojito-shipping-pymexpress-pdf-export-third-attribute', 'pa_weight' );
							if ( ! empty( $third_attribute_slug )) {
								$third_attribute_value = $item->get_meta($third_attribute_slug);
								if ( ! empty( $third_attribute_value )) {
									if ( ! empty( $first_attribute_value ) || ! empty( $second_attribute_value )) {
										$variant_line .= ', ';
									}
									$variant_line .= $third_attribute_value;
									$add_variant_to_line = true;
								}
							}
							$fourth_attribute_slug = get_option( 'mojito-shipping-pymexpress-pdf-export-fourth-attribute', 'pa_material' );
							if ( ! empty( $fourth_attribute_slug )) {
								$fourth_attribute_value = $item->get_meta($fourth_attribute_slug);
								if ( ! empty( $fourth_attribute_value )) {
									if ( ! empty( $first_attribute_value ) || ! empty( $second_attribute_value ) || ! empty( $third_attribute_value )) {
										$variant_line .= ', ';
									}
									$variant_line .= $fourth_attribute_value;
									$add_variant_to_line = true;
								}
							}

							if ( $add_variant_to_line ) {
								$line .= ' (';
								$line .= $variant_line;
								$line .= ')';
							}

							$line .= ' x ';
							$line .= $item->get_quantity();
							$line .= ', ';
							$package_items .= $line;
						}
	
						$package_items = rtrim( $package_items, ', ' );
	
						$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<h2>' . __( 'Package details', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<b>' . __( 'Details:', 'mojito-shipping' ) . '</b> ' . $package_items );
	
						/**
						 * Filter: After package content details
						 */
						$custom_content = apply_filters(
							'mojito_shipping_pymexpress_pdf_after_package_content',
							array(
								'content'  => '',
								'position' => 'L',
							)
						);
						if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
							$custom_content['position'] = 'L';
						}
						if ( ! empty( $custom_content['content'] ) ) {
							$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
						}
					}
	
					/**
					 * Client notes
					 */
					if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-client-note', 'no' ) ) {
						$pdf->writeHTML( '<br>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<h2>' . __( 'Client notes', 'mojito-shipping' ) . '</h2>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<hr>', true, false, false, false, 'C' );
						$pdf->writeHTML( '<b>' . __( 'Client note:', 'mojito-shipping' ) . '</b> ' . $order->get_customer_note() );
					}
	
					/**
					 * Filter: After Client notes
					 */
					$custom_content = apply_filters(
						'mojito_shipping_pymexpress_pdf_after_client_notes',
						array(
							'content'  => '',
							'position' => 'L',
						)
					);
	
					// Backguards compatibility.
					$custom_content = apply_filters( 'mojito_shipping_pymexpress_pdf_after_package_data', $custom_content );
	
					if ( 'L' !== $custom_content['position'] && 'C' !== $custom_content['position'] && 'R' !== $custom_content['position'] ) {
						$custom_content['position'] = 'L';
					}
					if ( ! empty( $custom_content['content'] ) ) {
						$pdf->writeHTML( $custom_content['content'], true, false, false, false, $custom_content['position'] );
					}
	
					/**
					 * Logos
					 */
					$logos_html = '<table><tr>';
					if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-ccr-logo' ) ) {
	
						$logo_file   = 'logo-correos-de-costa-rica.jpg';
						$logo_url    = apply_filters( 'mojito_shipping_pymexpress_pdf_ccr_logo_src', plugin_dir_url( __DIR__ ) . 'public/img/' . $logo_file );
						$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
						$logos_html .= '<td>' . $img . '</td>';
					}
					if ( 'yes' === get_option( 'mojito-shipping-pymexpress-pdf-export-site-logo' ) ) {
	
						$blog_id = ( is_multisite() ) ? get_current_blog_id() : 0;
	
						if ( has_custom_logo( $blog_id ) ) {
	
							$custom_logo_id = get_theme_mod( 'custom_logo' );
							$image          = wp_get_attachment_image_src( $custom_logo_id, 'full' );
	
							add_filter(
								'get_custom_logo',
								function ( $html, $blog_id ) {
									return str_replace( 'itemprop="logo"', '', $html );
								},
								10,
								2
							);
	
							$logo_url    = apply_filters( 'mojito_shipping_pymexpress_pdf_site_logo_src', $image[0] );
							if ( empty($logo_url)) {
								mojito_shipping_debug( 'No logo found for PDF Export' );
							}
							$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
							$logos_html .= '<td>' . $img . '</td>';
	
						} else {
	
							$logo_url    = apply_filters( 'mojito_shipping_pymexpress_pdf_site_logo_src', '' );
							if ( empty($logo_url)) {
								mojito_shipping_debug( 'No logo found for PDF Export' );
							}
							$img         = '<img style="width:200px;display:inline-block;" src="' . $logo_url . '">';
							$logos_html .= '<td>' . $img . '</td>';
						}
					}
					$logos_html .= '</tr></table>';
					$pdf->writeHTML( '<div>' . $logos_html . '</div>', true, false, true, false, 'C' );
				}
			}

			/**
			 * Save file
			 */
			$output = $pdf->Output( $file, 'S' );

			file_put_contents( $file, $output );

			$content  = base64_encode( file_get_contents( $file ) );
			
		} elseif ( 'pymexpress' === get_option( 'mojito-shipping-pymexpress-pdf-export-origin', 'mojito' ) ) {
			$content = $order->get_meta( 'mojito_shipping_pymexpress_pdf', true );
			file_put_contents( $file, base64_decode( $content ) );
		}

		$url      = $upload_dir['baseurl'] . '/mojito-shipping-tmp/' . $guide_number . '.pdf';
		$response = array(
			'url'          => $url,
			'content'      => $content,
			'guide_number' => $guide_number,
		);

		if ( $ajax_call ) {
			echo wp_json_encode( $response  );
			wp_delete_file( $file );
			die();
		} else {
			$response['path'] = $file;
			return $response;
		}
	}

	/**
	 * Download the Pymexpress PDF from the customer order details page.
	 *
	 * @return void
	 */
	public function pymexpress_pdf_download_customer() {

		$this->pymexpress_pdf_download( '', true );
	}


	/**
	 * The name of the plugin used to uniquely identify it within the context of
	 * WordPress and to define internationalization functionality.
	 *
	 * @since     1.0.0
	 * @return    string    The name of the plugin.
	 */
	public function get_plugin_name() {
		return $this->plugin_name;
	}

	/**
	 * The reference to the class that orchestrates the hooks with the plugin.
	 *
	 * @since     1.0.0
	 * @return    Mojito_Shipping_Loader    Orchestrates the hooks of the plugin.
	 */
	public function get_loader() {
		return $this->loader;
	}

	/**
	 * Retrieve the version number of the plugin.
	 *
	 * @since     1.0.0
	 * @return    string    The version number of the plugin.
	 */
	public function get_version() {
		return $this->version;
	}

	/**
	 * ¡Vaya que eres curioso!
	 */
	public function soy_curiso() {
		/**
		 * Este método no hace nada más que darte un 25% de descuento con el cupón SOYCURIOSO
		 * Ya quedan pocos, ¡póngale!
		 */
	}

	/**
	 * Start WooCommerce Shipping method
	 */
	public function start_woocommerce_shipping() {

		$carrier_provider = get_option( 'mojito-shipping-carrier-provider' );

		if ( is_array( $carrier_provider ) ) {

			if ( in_array( 'ccr', $carrier_provider, true ) ) {

				add_action(
					'woocommerce_shipping_init',
					function () {
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-ccr.php';
						global $instance_ccr_shipping_method;
						if ( ! isset( $instance_ccr_shipping_method ) ) {
							$instance_ccr_shipping_method = new Mojito_Shipping_Method_CCR();
						}
					}
				);

				/**
				 * Register shipping method
				 */
				add_filter(
					'woocommerce_shipping_methods',
					function ( $methods ) {
						$methods['mojito_shipping_ccr'] = 'Mojito_Shipping\Mojito_Shipping_Method_CCR';
						return $methods;
					}
				);
			}

			if ( in_array( 'pymexpress', $carrier_provider, true ) ) {

				add_action(
					'woocommerce_shipping_init',
					function () {
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-pymexpress.php';
						global $instance_pymexpress_shipping_method;
						if ( ! isset( $instance_pymexpress_shipping_method ) ) {
							$instance_pymexpress_shipping_method = new Mojito_Shipping_Method_Pymexpress();
						}
					}
				);

				/**
				 * Register shipping method
				 */
				add_filter(
					'woocommerce_shipping_methods',
					function ( $methods ) {
						$methods['mojito_shipping_pymexpress'] = 'Mojito_Shipping\Mojito_Shipping_Method_Pymexpress';
						return $methods;
					}
				);
			}

			if ( in_array( 'ccr-simple', $carrier_provider, true ) ) {

				add_action(
					'woocommerce_shipping_init',
					function () {
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-ccr.php';
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-ccr-simple.php';
						global $instance_ccr_simple_shipping_method;
						if ( ! isset( $instance_ccr_simple_shipping_method ) ) {
							$instance_ccr_simple_shipping_method = new Mojito_Shipping_Method_CCR_Simple();
						}
					}
				);

				/**
				 * Register shipping method
				 */
				add_filter(
					'woocommerce_shipping_methods',
					function ( $methods ) {
						$methods['mojito_shipping_correos_simple'] = 'Mojito_Shipping\Mojito_Shipping_Method_CCR_Simple';
						return $methods;
					}
				);
			}

			if ( in_array( 'simple', $carrier_provider, true ) ) {

				add_action(
					'woocommerce_shipping_init',
					function () {
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-simple.php';
						global $instance_simple_shipping_method;
						if ( ! isset( $instance_simple_shipping_method ) ) {
							$instance_simple_shipping_method = new Mojito_Shipping_Method_Simple();
						}
					}
				);

				/**
				 * Register shipping method
				 */
				add_filter(
					'woocommerce_shipping_methods',
					function ( $methods ) {
						$methods['mojito_shipping_simple'] = 'Mojito_Shipping\Mojito_Shipping_Method_Simple';
						return $methods;
					}
				);
			}
		}
	}

	/**
	 * Cron jobs
	 * https://wordpress.org/support/topic/no-se-genera-guia-si-el-pago-es-con-tarjeta/
	 *
	 * @return void
	 */
	public function cron_pymexpress_complete_orders() {

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

			$allow = get_option( 'mojito-shipping-pymexpress-cron-control-complete-orders', 'no' );
	
			if ( 'no' == $allow ) {
				return;
			}

			$lock_key = 'mojito_shipping_pymexpress_complete_orders_lock';
			if ( get_transient( $lock_key ) ) {
				mojito_shipping_debug( 'Skipping Pymexpress complete orders cron because it is already running.' );
				return;
			}

			set_transient( $lock_key, time(), 10 * MINUTE_IN_SECONDS );

			try {

				mojito_shipping_debug( 'Checking Pymexpress orders pending guide or registration completion.' );

				$query_args = array(
						'return'     => 'ids',
						'limit'      => 1,
						'orderby'    => 'date',
						'order'      => 'DESC',
						'status'     => array( 'pending', 'on-hold', 'processing', 'completed' ),
						'meta_query' => array(
							'relation' => 'OR',
							array(
								'key'     => 'mojito_shipping_pymexpress_guide_number',
								'compare' => 'NOT EXISTS',
							),
							array(
								'key'     => 'mojito_shipping_pymexpress_guide_number',
								'value'   => '',
								'compare' => '=',
							),
							array(
								'key'     => 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code',
								'compare' => 'NOT EXISTS',
							),
							array(
								'key'     => 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code',
								'value'   => '',
								'compare' => '=',
							),
							array(
								'relation' => 'AND',
								array(
									'key'     => 'mojito_shipping_pymexpress_retry_reason',
									'compare' => 'EXISTS',
								),
								array(
									'relation' => 'OR',
									array(
										'key'     => 'mojito_shipping_pymexpress_retry_after',
										'compare' => 'NOT EXISTS',
									),
									array(
										'key'     => 'mojito_shipping_pymexpress_retry_after',
										'value'   => time(),
										'type'    => 'NUMERIC',
										'compare' => '<=',
									),
								),
							),
						),
					);
					$orders_to_check = array_map( 'intval', wc_get_orders( $query_args ) );


				if ( ! $this->pymexpress_ws_client instanceof Mojito_Shipping_Method_Pymexpress_WSC ) {
					// Init web service client.
					if ( ! class_exists( 'Mojito_Shipping_Method_Pymexpress_WSC' ) ) {
						require_once MOJITO_SHIPPING_DIR . 'includes/class-mojito-shipping-method-pymexpress-webservice-client.php';
					}
					$this->pymexpress_ws_client = new Mojito_Shipping_Method_Pymexpress_WSC();
				}

				foreach ( $orders_to_check as $key => $order_id ) {

					$order = wc_get_order( $order_id );
					if ( ! $this->pymexpress_order_is_ready_for_cron( $order ) ) {
						continue;
					}

					$response_code = $order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code', true );
					if ( in_array( $response_code, array( '00', '36' ), true ) ) {
						$this->pymexpress_clear_order_retry_state( $order );
						continue;
					}

					$guide_number = $order->get_meta( 'mojito_shipping_pymexpress_guide_number', true );
					if ( empty( $guide_number ) ) {
						$guide_number = $this->pymexpress_ws_client->generar_guia();
						if ( empty( $guide_number ) ) {
							$this->pymexpress_schedule_order_retry(
								$order,
								'guide_generation_failed',
								__( 'Unable to generate a Correos de Costa Rica guide number automatically.', 'mojito-shipping' )
							);
							continue;
						}

						$order->update_meta_data(
							'mojito_shipping_pymexpress_guide_number',
							sanitize_text_field( $guide_number )
						);
						$order->save();
					}

					$this->pymexpress_thankyou_log_send( $order_id, true );
					$order         = wc_get_order( $order_id );
					$response_code = $order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_code', true );

					if ( in_array( $response_code, array( '00', '36' ), true ) ) {
						$this->pymexpress_clear_order_retry_state( $order );
						continue;
					}

					$retry_reason = $order->get_meta( 'mojito_shipping_pymexpress_retry_reason', true );
					if ( empty( $retry_reason ) ) {
						$retry_reason = 'registration_failed';
					}

					$this->pymexpress_schedule_order_retry(
						$order,
						$retry_reason,
						$order->get_meta( 'mojito_shipping_pymexpress_ccrRegistroEnvio_response_error', true )
					);
				}
			} finally {
				delete_transient( $lock_key );
			}
		}

	}
	public function cron_pymexpress(){
		$this->cron_pymexpress_complete_orders();
	}

	/**
	 * Revisar IP contra el firewall de Mojito Proxy
	 */
	public function cron_mojito_proxy_ip_check(){

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
			$allow = get_option( 'mojito-shipping-pymexpress-cron-control-check-ip', 'no' );
	
			if ( 'no' == $allow ) {
				return;
			}

			$lock_key = 'mojito_shipping_proxy_ip_check_lock';
			if ( get_transient( $lock_key ) ) {
				mojito_shipping_debug( 'Skipping proxy IP check cron because it is already running.' );
				return;
			}

			set_transient( $lock_key, time(), 5 * MINUTE_IN_SECONDS );

			try {
				mojito_shipping_debug( 'Checking IP against Mojito Proxy' );

				if ( 'true' === get_option( 'mojito-shipping-pymexpress-mojito-proxy-enable', 'false' ) ) {
					$my_ip    = 'https://myip.mojitowp.com?type=pro&version=' . MOJITO_SHIPPING_VERSION;
					$response = wp_remote_get( $my_ip );

					if ( $response instanceof \WP_Error ) {
						\do_action( 'mojito_shipping_pymexpress_check_ip_failed' );
					}
				}
			} finally {
				delete_transient( $lock_key );
			}
		}
	}

	public function cron_pymexpress_check_api()
	{

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {
			$allow = get_option( 'mojito-shipping-pymexpress-cron-control-check-api', 'no' );

			if ( 'no' == $allow ) {
				return;
			}

			$lock_key = 'mojito_shipping_pymexpress_check_api_lock';
			if ( get_transient( $lock_key ) ) {
				mojito_shipping_debug( 'Skipping Pymexpress API check cron because it is already running.' );
				return;
			}

			set_transient( $lock_key, time(), 5 * MINUTE_IN_SECONDS );

			try {
				mojito_shipping_debug( 'Checking Pymexpress API' );

				$pymexpress_wc = new Mojito_Shipping_Method_Pymexpress_WSC();
				$token         = $pymexpress_wc->get_token();

				if ( empty( $token ) ) {
					\do_action( 'mojito_shipping_pymexpress_check_api_failed' );
				}
			} finally {
				delete_transient( $lock_key );
			}
		}
	}

	public function cron_pymexpress_update_exchange_rate()
	{

		if ( mojito_shipping_fs()->is__premium_only() && mojito_shipping_fs()->can_use_premium_code() ) {

			$allow = get_option( 'mojito-shipping-pymexpress-cron-control-update-exchange-rate', 'no' );

			if ( 'no' == $allow ) {
				return;
			}

			$lock_key = 'mojito_shipping_update_exchange_rate_lock';
			if ( get_transient( $lock_key ) ) {
				mojito_shipping_debug( 'Skipping exchange rate update cron because it is already running.' );
				return;
			}

			set_transient( $lock_key, time(), 5 * MINUTE_IN_SECONDS );

			try {
				mojito_shipping_debug( 'Updating exchange rate' );

				$exchange_object = new Mojito_Shipping_Exchange_Rate();
				$exchange_rate   = $exchange_object->get_exchange_rate_crc_usd();

				if ( empty( $exchange_rate ) ) {
					\do_action( 'mojito_shipping_pymexpress_update_exchange_rate_failed' );
				}
			} finally {
				delete_transient( $lock_key );
			}
		}
	}

	/**
	 * Validate the premium settings AJAX request.
	 *
	 * @return void
	 */
	private function verify_settings_ajax_request() {

		if ( ! current_user_can( 'manage_options' ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'You are not allowed to manage Mojito Shipping settings.', 'mojito-shipping' ),
				),
				403
			);
		}

		if ( ! check_ajax_referer( 'mojito_shipping_manage_settings', 'nonce', false ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'The settings request could not be verified. Reload the page and try again.', 'mojito-shipping' ),
				),
				403
			);
		}
	}

	/**
	 * Recursively sanitize imported setting values.
	 *
	 * @param mixed $value Imported setting value.
	 * @return mixed
	 */
	private function sanitize_imported_setting_value( $value ) {

		if ( is_array( $value ) ) {
			$sanitized = array();

			foreach ( $value as $key => $single_value ) {
				$sanitized_key               = is_string( $key ) ? sanitize_text_field( $key ) : $key;
				$sanitized[ $sanitized_key ] = $this->sanitize_imported_setting_value( $single_value );
			}

			return $sanitized;
		}

		if ( is_string( $value ) ) {
			return wp_check_invalid_utf8( $value );
		}

		if ( is_scalar( $value ) || null === $value ) {
			return $value;
		}

		return '';
	}

	public function download_settings(){

		$this->verify_settings_ajax_request();
		
		$settings = array();
		$settings['mojito-shipping-carrier-provider'] = get_option('mojito-shipping-carrier-provider');
		$settings['mojito-shipping-pymexpress-cart-and-checkout-address-preselection'] = get_option('mojito-shipping-pymexpress-cart-and-checkout-address-preselection');
		$settings['mojito-shipping-pymexpress-cron-control-check-api'] = get_option('mojito-shipping-pymexpress-cron-control-check-api');
		$settings['mojito-shipping-pymexpress-cron-control-check-ip'] = get_option('mojito-shipping-pymexpress-cron-control-check-ip');
		$settings['mojito-shipping-pymexpress-cron-control-complete-orders'] = get_option('mojito-shipping-pymexpress-cron-control-complete-orders');
		$settings['mojito-shipping-pymexpress-cron-control-update-exchange-rate'] = get_option('mojito-shipping-pymexpress-cron-control-update-exchange-rate');
		$settings['mojito-shipping-pymexpress-exchange-rate-enable'] = get_option('mojito-shipping-pymexpress-exchange-rate-enable');
		$settings['mojito-shipping-pymexpress-exchange-rate-origin'] = get_option('mojito-shipping-pymexpress-exchange-rate-origin');
		$settings['mojito-shipping-pymexpress-exchange-rate-rate'] = get_option('mojito-shipping-pymexpress-exchange-rate-rate');
		$settings['mojito-shipping-pymexpress-fixed-rates-enable'] = get_option('mojito-shipping-pymexpress-fixed-rates-enable');
		$settings['mojito-shipping-pymexpress-fixed-rates-gam-rate'] = get_option('mojito-shipping-pymexpress-fixed-rates-gam-rate');
		$settings['mojito-shipping-pymexpress-fixed-rates-no-gam-rate'] = get_option('mojito-shipping-pymexpress-fixed-rates-no-gam-rate');
		$settings['mojito-shipping-pymexpress-label-label'] = get_option('mojito-shipping-pymexpress-label-label');
		$settings['mojito-shipping-pymexpress-location-rules-custom-zipcodes'] = get_option('mojito-shipping-pymexpress-location-rules-custom-zipcodes');
		$settings['mojito-shipping-pymexpress-location-rules-exclude-gam'] = get_option('mojito-shipping-pymexpress-location-rules-exclude-gam');
		$settings['mojito-shipping-pymexpress-location-rules-exclude-no-gam'] = get_option('mojito-shipping-pymexpress-location-rules-exclude-no-gam');
		$settings['mojito-shipping-pymexpress-logo-css-class'] = get_option('mojito-shipping-pymexpress-logo-css-class');
		$settings['mojito-shipping-pymexpress-logo-link'] = get_option('mojito-shipping-pymexpress-logo-link');
		$settings['mojito-shipping-pymexpress-logo-logo-ccr'] = get_option('mojito-shipping-pymexpress-logo-logo-ccr');
		$settings['mojito-shipping-pymexpress-logo-position'] = get_option('mojito-shipping-pymexpress-logo-position');
		$settings['mojito-shipping-pymexpress-logo-size'] = get_option('mojito-shipping-pymexpress-logo-size');
		$settings['mojito-shipping-pymexpress-mail-orders-message'] = get_option('mojito-shipping-pymexpress-mail-orders-message');
		$settings['mojito-shipping-pymexpress-mail-orders-name'] = get_option('mojito-shipping-pymexpress-mail-orders-name');
		$settings['mojito-shipping-pymexpress-max-weight-enable'] = get_option('mojito-shipping-pymexpress-max-weight-enable');
		$settings['mojito-shipping-pymexpress-minimal-amount-general'] = get_option('mojito-shipping-pymexpress-minimal-amount-general');
		$settings['mojito-shipping-pymexpress-minimal-amount-inside-gam'] = get_option('mojito-shipping-pymexpress-minimal-amount-inside-gam');
		$settings['mojito-shipping-pymexpress-minimal-amount-outside-gam'] = get_option('mojito-shipping-pymexpress-minimal-amount-outside-gam');
		$settings['mojito-shipping-pymexpress-minimal-enable'] = get_option('mojito-shipping-pymexpress-minimal-enable');
		$settings['mojito-shipping-pymexpress-minimal-round-the-amount'] = get_option('mojito-shipping-pymexpress-minimal-round-the-amount');
		$settings['mojito-shipping-pymexpress-mojito-proxy-enable'] = get_option('mojito-shipping-pymexpress-mojito-proxy-enable');
		$settings['mojito-shipping-pymexpress-packing-costs-custom-packing-cost'] = get_option('mojito-shipping-pymexpress-packing-costs-custom-packing-cost');
		$settings['mojito-shipping-pymexpress-packing-costs-enable'] = get_option('mojito-shipping-pymexpress-packing-costs-enable');
		$settings['mojito-shipping-pymexpress-packing-costs-size'] = get_option('mojito-shipping-pymexpress-packing-costs-size');
		$settings['mojito-shipping-pymexpress-pdf-export-ccr-logo'] = get_option('mojito-shipping-pymexpress-pdf-export-ccr-logo');
		$settings['mojito-shipping-pymexpress-pdf-export-client-note'] = get_option('mojito-shipping-pymexpress-pdf-export-client-note');
		$settings['mojito-shipping-pymexpress-pdf-export-content'] = get_option('mojito-shipping-pymexpress-pdf-export-content');
		$settings['mojito-shipping-pymexpress-pdf-export-first-attribute'] = get_option('mojito-shipping-pymexpress-pdf-export-first-attribute');
		$settings['mojito-shipping-pymexpress-pdf-export-fourth-attribute'] = get_option('mojito-shipping-pymexpress-pdf-export-fourth-attribute');
		$settings['mojito-shipping-pymexpress-pdf-export-in-customer-order'] = get_option('mojito-shipping-pymexpress-pdf-export-in-customer-order');
		$settings['mojito-shipping-pymexpress-pdf-export-in-orders-list'] = get_option('mojito-shipping-pymexpress-pdf-export-in-orders-list');
		$settings['mojito-shipping-pymexpress-pdf-export-order-content'] = get_option('mojito-shipping-pymexpress-pdf-export-order-content');
		$settings['mojito-shipping-pymexpress-pdf-export-origin'] = get_option('mojito-shipping-pymexpress-pdf-export-origin');
		$settings['mojito-shipping-pymexpress-pdf-export-paper-size'] = get_option('mojito-shipping-pymexpress-pdf-export-paper-size');
		$settings['mojito-shipping-pymexpress-pdf-export-second-attribute'] = get_option('mojito-shipping-pymexpress-pdf-export-second-attribute');
		$settings['mojito-shipping-pymexpress-pdf-export-send-to-emails'] = get_option('mojito-shipping-pymexpress-pdf-export-send-to-emails');
		$settings['mojito-shipping-pymexpress-pdf-export-site-logo'] = get_option('mojito-shipping-pymexpress-pdf-export-site-logo');
		$settings['mojito-shipping-pymexpress-pdf-export-third-attribute'] = get_option('mojito-shipping-pymexpress-pdf-export-third-attribute');
		$settings['mojito-shipping-pymexpress-preloaded'] = get_option('mojito-shipping-pymexpress-preloaded');
		$settings['mojito-shipping-pymexpress-proxy-enable'] = get_option('mojito-shipping-pymexpress-proxy-enable');
		$settings['mojito-shipping-pymexpress-proxy-ip'] = get_option('mojito-shipping-pymexpress-proxy-ip');
		$settings['mojito-shipping-pymexpress-proxy-password'] = get_option('mojito-shipping-pymexpress-proxy-password');
		$settings['mojito-shipping-pymexpress-proxy-port'] = get_option('mojito-shipping-pymexpress-proxy-port');
		$settings['mojito-shipping-pymexpress-proxy-username'] = get_option('mojito-shipping-pymexpress-proxy-username');
		$settings['mojito-shipping-pymexpress-sender-address'] = get_option('mojito-shipping-pymexpress-sender-address');
		$settings['mojito-shipping-pymexpress-sender-email'] = get_option('mojito-shipping-pymexpress-sender-email');
		$settings['mojito-shipping-pymexpress-sender-name'] = get_option('mojito-shipping-pymexpress-sender-name');
		$settings['mojito-shipping-pymexpress-sender-phone'] = get_option('mojito-shipping-pymexpress-sender-phone');
		$settings['mojito-shipping-pymexpress-sender-zip-code'] = get_option('mojito-shipping-pymexpress-sender-zip-code');
		$settings['mojito-shipping-pymexpress-shipping-rules-discount'] = get_option('mojito-shipping-pymexpress-shipping-rules-discount');
		$settings['mojito-shipping-pymexpress-shipping-rules-discount-mode'] = get_option('mojito-shipping-pymexpress-shipping-rules-discount-mode');
		$settings['mojito-shipping-pymexpress-shipping-rules-minmax'] = get_option('mojito-shipping-pymexpress-shipping-rules-minmax');
		$settings['mojito-shipping-pymexpress-shipping-rules-rule-mode'] = get_option('mojito-shipping-pymexpress-shipping-rules-rule-mode');
		$settings['mojito-shipping-pymexpress-store-canton'] = get_option('mojito-shipping-pymexpress-store-canton');
		$settings['mojito-shipping-pymexpress-store-district'] = get_option('mojito-shipping-pymexpress-store-district');
		$settings['mojito-shipping-pymexpress-store-iva-ccr'] = get_option('mojito-shipping-pymexpress-store-iva-ccr');
		$settings['mojito-shipping-pymexpress-store-province'] = get_option('mojito-shipping-pymexpress-store-province');
		$settings['mojito-shipping-pymexpress-tracking-admin-order-details'] = get_option('mojito-shipping-pymexpress-tracking-admin-order-details');
		$settings['mojito-shipping-pymexpress-tracking-user-order-details'] = get_option('mojito-shipping-pymexpress-tracking-user-order-details');
		$settings['mojito-shipping-pymexpress-web-service-client-code'] = get_option('mojito-shipping-pymexpress-web-service-client-code');
		$settings['mojito-shipping-pymexpress-web-service-environment'] = get_option('mojito-shipping-pymexpress-web-service-environment');
		$settings['mojito-shipping-pymexpress-web-service-password'] = get_option('mojito-shipping-pymexpress-web-service-password');
		$settings['mojito-shipping-pymexpress-web-service-service-id'] = get_option('mojito-shipping-pymexpress-web-service-service-id');
		$settings['mojito-shipping-pymexpress-web-service-system'] = get_option('mojito-shipping-pymexpress-web-service-system');
		$settings['mojito-shipping-pymexpress-web-service-user-id'] = get_option('mojito-shipping-pymexpress-web-service-user-id');
		$settings['mojito-shipping-pymexpress-web-service-username'] = get_option('mojito-shipping-pymexpress-web-service-username');
		$settings['mojito-shipping-pymexpress-ws-cache-control-allow-cache'] = get_option('mojito-shipping-pymexpress-ws-cache-control-allow-cache');
		$settings['mojito-shipping-pymexpress-ws-cache-control-lifetime'] = get_option('mojito-shipping-pymexpress-ws-cache-control-lifetime');
		$settings['mojito-shipping-settings-debug'] = get_option('mojito-shipping-settings-debug');
		$settings['woocommerce_mojito_shipping_pymexpress_enabled'] = get_option('woocommerce_mojito_shipping_pymexpress_enabled');
		$settings['woocommerce_mojito_shipping_pymexpress_title'] = get_option('woocommerce_mojito_shipping_pymexpress_title');
		$settings['woocommerce_mojito-sinpe_setting'] = get_option('woocommerce_mojito-sinpe_setting');

		$response = array(
			'settings' => base64_encode( wp_json_encode( $settings ) ),
		);
		wp_send_json( $response );
	}

	public function apply_settings(){

		$this->verify_settings_ajax_request();

		mojito_shipping_debug( 'Applying settings' );

		$settings = isset( $_POST['settings'] ) ? wp_unslash( $_POST['settings'] ) : '';

		if ( empty( $settings ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'No settings payload was received.', 'mojito-shipping' ),
				),
				400
			);
		}

		$settings = base64_decode( $settings, true );

		if ( false === $settings ) {
			wp_send_json_error(
				array(
					'message' => __( 'The uploaded settings file is not valid.', 'mojito-shipping' ),
				),
				400
			);
		}

		$settings = json_decode( $settings, true );

		if ( ! is_array( $settings ) ) {
			wp_send_json_error(
				array(
					'message' => __( 'The uploaded settings payload could not be decoded.', 'mojito-shipping' ),
				),
				400
			);
		}

		$settings = $this->sanitize_imported_setting_value( $settings );

		mojito_shipping_debug(
			sprintf(
				'Applying imported Mojito Shipping settings for %d options.',
				count( $settings )
			)
		);

		if( ! empty( $settings['mojito-shipping-carrier-provider']) ) {
			update_option('mojito-shipping-carrier-provider',$settings['mojito-shipping-carrier-provider']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-cart-and-checkout-address-preselection'] ) ) {
			update_option('mojito-shipping-pymexpress-cart-and-checkout-address-preselection', $settings['mojito-shipping-pymexpress-cart-and-checkout-address-preselection']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-cron-control-check-api'] ) ) {
			update_option('mojito-shipping-pymexpress-cron-control-check-api',$settings['mojito-shipping-pymexpress-cron-control-check-api']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-cron-control-check-ip'] ) ) {
			update_option('mojito-shipping-pymexpress-cron-control-check-ip',$settings['mojito-shipping-pymexpress-cron-control-check-ip']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-cron-control-complete-orders'] ) ) {
			update_option('mojito-shipping-pymexpress-cron-control-complete-orders',$settings['mojito-shipping-pymexpress-cron-control-complete-orders']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-cron-control-update-exchange-rate'] ) ) {
			update_option('mojito-shipping-pymexpress-cron-control-update-exchange-rate',$settings['mojito-shipping-pymexpress-cron-control-update-exchange-rate']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-exchange-rate-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-exchange-rate-enable',$settings['mojito-shipping-pymexpress-exchange-rate-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-exchange-rate-origin'] ) ) {
			update_option('mojito-shipping-pymexpress-exchange-rate-origin',$settings['mojito-shipping-pymexpress-exchange-rate-origin']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-exchange-rate-rate'] ) ) {
			update_option('mojito-shipping-pymexpress-exchange-rate-rate',$settings['mojito-shipping-pymexpress-exchange-rate-rate']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-fixed-rates-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-fixed-rates-enable',$settings['mojito-shipping-pymexpress-fixed-rates-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-fixed-rates-gam-rate'] ) ) {
			update_option('mojito-shipping-pymexpress-fixed-rates-gam-rate',$settings['mojito-shipping-pymexpress-fixed-rates-gam-rate']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-fixed-rates-no-gam-rate'] ) ) {
			update_option('mojito-shipping-pymexpress-fixed-rates-no-gam-rate',$settings['mojito-shipping-pymexpress-fixed-rates-no-gam-rate']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-label-label'] ) ) {
			update_option('mojito-shipping-pymexpress-label-label',$settings['mojito-shipping-pymexpress-label-label']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-location-rules-custom-zipcodes'] ) ) {
			update_option('mojito-shipping-pymexpress-location-rules-custom-zipcodes',$settings['mojito-shipping-pymexpress-location-rules-custom-zipcodes']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-location-rules-exclude-gam'] ) ) {
			update_option('mojito-shipping-pymexpress-location-rules-exclude-gam',$settings['mojito-shipping-pymexpress-location-rules-exclude-gam']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-location-rules-exclude-no-gam'] ) ) {
			update_option('mojito-shipping-pymexpress-location-rules-exclude-no-gam',$settings['mojito-shipping-pymexpress-location-rules-exclude-no-gam']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-logo-css-class'] ) ) {
			update_option('mojito-shipping-pymexpress-logo-css-class',$settings['mojito-shipping-pymexpress-logo-css-class']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-logo-link'] ) ) {
			update_option('mojito-shipping-pymexpress-logo-link',$settings['mojito-shipping-pymexpress-logo-link']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-logo-logo-ccr'] ) ) {
			update_option('mojito-shipping-pymexpress-logo-logo-ccr',$settings['mojito-shipping-pymexpress-logo-logo-ccr']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-logo-position'] ) ) {
			update_option('mojito-shipping-pymexpress-logo-position',$settings['mojito-shipping-pymexpress-logo-position']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-logo-size'] ) ) {
			update_option('mojito-shipping-pymexpress-logo-size',$settings['mojito-shipping-pymexpress-logo-size']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-mail-orders-message'] ) ) {
			update_option('mojito-shipping-pymexpress-mail-orders-message',$settings['mojito-shipping-pymexpress-mail-orders-message']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-mail-orders-name'] ) ) {
			update_option('mojito-shipping-pymexpress-mail-orders-name',$settings['mojito-shipping-pymexpress-mail-orders-name']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-max-weight-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-max-weight-enable',$settings['mojito-shipping-pymexpress-max-weight-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-minimal-amount-general'] ) ) {
			update_option('mojito-shipping-pymexpress-minimal-amount-general',$settings['mojito-shipping-pymexpress-minimal-amount-general']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-minimal-amount-inside-gam'] ) ) {
			update_option('mojito-shipping-pymexpress-minimal-amount-inside-gam',$settings['mojito-shipping-pymexpress-minimal-amount-inside-gam']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-minimal-amount-outside-gam'] ) ) {
			update_option('mojito-shipping-pymexpress-minimal-amount-outside-gam',$settings['mojito-shipping-pymexpress-minimal-amount-outside-gam']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-minimal-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-minimal-enable',$settings['mojito-shipping-pymexpress-minimal-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-minimal-round-the-amount'] ) ) {
			update_option('mojito-shipping-pymexpress-minimal-round-the-amount',$settings['mojito-shipping-pymexpress-minimal-round-the-amount']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-mojito-proxy-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-mojito-proxy-enable',$settings['mojito-shipping-pymexpress-mojito-proxy-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-packing-costs-custom-packing-cost'] ) ) {
			update_option('mojito-shipping-pymexpress-packing-costs-custom-packing-cost',$settings['mojito-shipping-pymexpress-packing-costs-custom-packing-cost']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-packing-costs-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-packing-costs-enable',$settings['mojito-shipping-pymexpress-packing-costs-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-packing-costs-size'] ) ) {
			update_option('mojito-shipping-pymexpress-packing-costs-size',$settings['mojito-shipping-pymexpress-packing-costs-size']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-ccr-logo'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-ccr-logo',$settings['mojito-shipping-pymexpress-pdf-export-ccr-logo']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-client-note'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-client-note',$settings['mojito-shipping-pymexpress-pdf-export-client-note']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-content'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-content',$settings['mojito-shipping-pymexpress-pdf-export-content']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-first-attribute'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-first-attribute',$settings['mojito-shipping-pymexpress-pdf-export-first-attribute']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-fourth-attribute'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-fourth-attribute',$settings['mojito-shipping-pymexpress-pdf-export-fourth-attribute']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-in-customer-order'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-in-customer-order',$settings['mojito-shipping-pymexpress-pdf-export-in-customer-order']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-in-orders-list'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-in-orders-list',$settings['mojito-shipping-pymexpress-pdf-export-in-orders-list']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-order-content'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-order-content',$settings['mojito-shipping-pymexpress-pdf-export-order-content']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-origin'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-origin',$settings['mojito-shipping-pymexpress-pdf-export-origin']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-paper-size'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-paper-size',$settings['mojito-shipping-pymexpress-pdf-export-paper-size']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-second-attribute'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-second-attribute',$settings['mojito-shipping-pymexpress-pdf-export-second-attribute']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-send-to-emails'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-send-to-emails',$settings['mojito-shipping-pymexpress-pdf-export-send-to-emails']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-site-logo'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-site-logo',$settings['mojito-shipping-pymexpress-pdf-export-site-logo']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-pdf-export-third-attribute'] ) ) {
			update_option('mojito-shipping-pymexpress-pdf-export-third-attribute',$settings['mojito-shipping-pymexpress-pdf-export-third-attribute']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-preloaded'] ) ) {
			update_option('mojito-shipping-pymexpress-preloaded',$settings['mojito-shipping-pymexpress-preloaded']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-proxy-enable'] ) ) {
			update_option('mojito-shipping-pymexpress-proxy-enable',$settings['mojito-shipping-pymexpress-proxy-enable']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-proxy-ip'] ) ) {
			update_option('mojito-shipping-pymexpress-proxy-ip',$settings['mojito-shipping-pymexpress-proxy-ip']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-proxy-password'] ) ) {
			update_option('mojito-shipping-pymexpress-proxy-password',$settings['mojito-shipping-pymexpress-proxy-password']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-proxy-port'] ) ) {
			update_option('mojito-shipping-pymexpress-proxy-port',$settings['mojito-shipping-pymexpress-proxy-port']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-proxy-username'] ) ) {
			update_option('mojito-shipping-pymexpress-proxy-username',$settings['mojito-shipping-pymexpress-proxy-username']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-sender-address'] ) ) {
			update_option('mojito-shipping-pymexpress-sender-address',$settings['mojito-shipping-pymexpress-sender-address']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-sender-email'] ) ) {
			update_option('mojito-shipping-pymexpress-sender-email',$settings['mojito-shipping-pymexpress-sender-email']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-sender-name'] ) ) {
			update_option('mojito-shipping-pymexpress-sender-name',$settings['mojito-shipping-pymexpress-sender-name']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-sender-phone'] ) ) {
			update_option('mojito-shipping-pymexpress-sender-phone',$settings['mojito-shipping-pymexpress-sender-phone']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-sender-zip-code'] ) ) {
			update_option('mojito-shipping-pymexpress-sender-zip-code',$settings['mojito-shipping-pymexpress-sender-zip-code']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-shipping-rules-discount'] ) ) {
			update_option('mojito-shipping-pymexpress-shipping-rules-discount',$settings['mojito-shipping-pymexpress-shipping-rules-discount']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-shipping-rules-discount-mode'] ) ) {
			update_option('mojito-shipping-pymexpress-shipping-rules-discount-mode',$settings['mojito-shipping-pymexpress-shipping-rules-discount-mode']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-shipping-rules-minmax'] ) ) {
			update_option('mojito-shipping-pymexpress-shipping-rules-minmax',$settings['mojito-shipping-pymexpress-shipping-rules-minmax']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-shipping-rules-rule-mode'] ) ) {
			update_option('mojito-shipping-pymexpress-shipping-rules-rule-mode',$settings['mojito-shipping-pymexpress-shipping-rules-rule-mode']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-store-canton'] ) ) {
			update_option('mojito-shipping-pymexpress-store-canton',$settings['mojito-shipping-pymexpress-store-canton']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-store-district'] ) ) {
			update_option('mojito-shipping-pymexpress-store-district',$settings['mojito-shipping-pymexpress-store-district']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-store-iva-ccr'] ) ) {
			update_option('mojito-shipping-pymexpress-store-iva-ccr',$settings['mojito-shipping-pymexpress-store-iva-ccr']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-store-province'] ) ) {
			update_option('mojito-shipping-pymexpress-store-province',$settings['mojito-shipping-pymexpress-store-province']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-tracking-admin-order-details'] ) ) {
			update_option('mojito-shipping-pymexpress-tracking-admin-order-details',$settings['mojito-shipping-pymexpress-tracking-admin-order-details']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-tracking-user-order-details'] ) ) {
			update_option('mojito-shipping-pymexpress-tracking-user-order-details',$settings['mojito-shipping-pymexpress-tracking-user-order-details']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-client-code'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-client-code',$settings['mojito-shipping-pymexpress-web-service-client-code']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-environment'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-environment',$settings['mojito-shipping-pymexpress-web-service-environment']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-password'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-password',$settings['mojito-shipping-pymexpress-web-service-password']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-service-id'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-service-id',$settings['mojito-shipping-pymexpress-web-service-service-id']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-system'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-system',$settings['mojito-shipping-pymexpress-web-service-system']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-user-id'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-user-id',$settings['mojito-shipping-pymexpress-web-service-user-id']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-web-service-username'] ) ) {
			update_option('mojito-shipping-pymexpress-web-service-username',$settings['mojito-shipping-pymexpress-web-service-username']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-ws-cache-control-allow-cache'] ) ) {
			update_option('mojito-shipping-pymexpress-ws-cache-control-allow-cache',$settings['mojito-shipping-pymexpress-ws-cache-control-allow-cache']);

		}
		if( ! empty( $settings['mojito-shipping-pymexpress-ws-cache-control-lifetime'] ) ) {
			update_option('mojito-shipping-pymexpress-ws-cache-control-lifetime',$settings['mojito-shipping-pymexpress-ws-cache-control-lifetime']);

		}
		if( ! empty( $settings['mojito-shipping-settings-debug'] ) ) {
			update_option('mojito-shipping-settings-debug',$settings['mojito-shipping-settings-debug']);

		}
		if( ! empty( $settings['woocommerce_mojito_shipping_pymexpress_enabled'] ) ) {
			update_option('woocommerce_mojito_shipping_pymexpress_enabled',$settings['woocommerce_mojito_shipping_pymexpress_enabled']);

		}
		if( ! empty( $settings['woocommerce_mojito_shipping_pymexpress_title'] ) ) {
			update_option('woocommerce_mojito_shipping_pymexpress_title',$settings['woocommerce_mojito_shipping_pymexpress_title']);

		}
		if( ! empty( $settings['woocommerce_mojito-sinpe_setting'] ) ) {
			update_option('woocommerce_mojito-sinpe_setting',$settings['woocommerce_mojito-sinpe_setting']);

		}

		$this->sync_premium_cron_events();

		wp_send_json_success(
			array(
				'message' => __( 'Settings applied successfully.', 'mojito-shipping' ),
			)
		);

	}
}
