<?php

namespace Ilabs\Inpost_International\Settings;

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


use Ilabs\Inpost_International\Helpers\Helper;
use WP_List_Table;
use WP_Query;

/**
 * Manage_Shipments_Table
 */
class Manage_Shipments_Table extends WP_List_Table {

	/**
	 * Constructor
	 */
	public function __construct() {
		parent::__construct(
			array(
				'singular' => 'order',
				'plural'   => 'inpost-intl-shipments-table',
				'ajax'     => false,
			)
		);
	}


	/**
	 * Prepare items
	 *
	 * @return void
	 */
	public function prepare_items() {

		$columns               = $this->get_columns();
		$hidden                = array();
		$sortable              = $this->get_sortable_columns();
		$this->_column_headers = array( $columns, $hidden, $sortable );

		$per_page = 20;

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		if ( isset( $_REQUEST['shipment_qty'] ) && is_numeric( $_REQUEST['shipment_qty'] ) ) {
			$per_page = intval( sanitize_text_field( wp_unslash( $_REQUEST['shipment_qty'] ) ) );
		}

		$current_page = $this->get_pagenum();
		$total_items  = $this->get_total_shipments();

		$this->set_pagination_args(
			array(
				'total_items' => $total_items,
				'per_page'    => $per_page,
			)
		);

		$this->items = $this->get_shipments( $per_page, $current_page );
	}


	/**
	 * Gets the current page number.
	 *
	 * @return int
	 */
	public function get_pagenum() {

		$pagenum = 0;

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		if ( isset( $_GET['page'] ) && 'inpost-international-api' === $_GET['page'] && isset( $_GET['tab'] ) && 'shipments' === $_GET['tab'] ) {
			$pagenum = isset( $_REQUEST['shipments_paged'] ) ? absint( sanitize_text_field( wp_unslash( $_REQUEST['shipments_paged'] ) ) ) : 0;
		}

		if ( isset( $this->_pagination_args['total_pages'] ) && $pagenum > $this->_pagination_args['total_pages'] ) {
			$pagenum = $this->_pagination_args['total_pages'];
		}

		return max( 1, $pagenum );
	}


	/**
	 * Get columns
	 *
	 * @return array
	 */
	public function get_columns() {
		$columns = array(
			'cb'                 => '<input type="checkbox" />',
			'order_id'           => esc_html__( 'Order No', 'inpost-international' ),
			'order_tracking'     => esc_html__( 'Tracking', 'inpost-international' ),
			'status'             => esc_html__( 'Status', 'inpost-international' ),
			'dimensions'         => esc_html__( 'Dimensions', 'inpost-international' ),
			'send_method'        => esc_html__( 'Send method', 'inpost-international' ),
			'package_created'    => esc_html__( 'When created', 'inpost-international' ),
			'package_dispatched' => esc_html__( 'When dispatched', 'inpost-international' ),
			'recipient'          => esc_html__( 'Recipient', 'inpost-international' ),
			'ref_number'         => esc_html__( 'Reference number', 'inpost-international' ),
			'action'             => esc_html__( 'Action', 'inpost-international' ),
		);
		return $columns;
	}

	/**
	 * Get sortable columns
	 *
	 * @return array[]
	 */
	public function get_sortable_columns() {
		$sortable_columns = array(
			'order_id' => array( 'order_id', false ),
		);
		return $sortable_columns;
	}


	/**
	 * Get total products
	 *
	 * @return int
	 */
	private function get_total_shipments() {

		$order_ids = array();

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		if ( isset( $_REQUEST['search_tracking'] ) || isset( $_REQUEST['search_order'] )
			|| isset( $_REQUEST['search_phone'] ) || isset( $_REQUEST['search_email'] )
			|| isset( $_REQUEST['search_reference'] )
			|| isset( $_REQUEST['shipment_send_type'] )
		) {

			if ( isset( $_GET['page'] ) && 'inpost-international-api' === $_GET['page'] && isset( $_GET['tab'] ) && 'shipments' === $_GET['tab'] ) {
				if ( isset( $_REQUEST['search_tracking'] ) ) {
					$tracking  = sanitize_text_field( wp_unslash( $_REQUEST['search_tracking'] ) );
					$tracking  = trim( $tracking );
					$order_ids = $this->get_search_by_tracking( $tracking );
				} elseif ( isset( $_REQUEST['search_order'] ) ) {
					$order_id  = sanitize_text_field( wp_unslash( $_REQUEST['search_order'] ) );
					$order_id  = trim( $order_id );
					$order_ids = $this->get_search_by_order( $order_id );
				} elseif ( isset( $_REQUEST['search_phone'] ) ) {
					$phone     = sanitize_text_field( wp_unslash( $_REQUEST['search_phone'] ) );
					$phone     = trim( $phone );
					$order_ids = $this->get_search_by_phone( $phone );
				} elseif ( isset( $_REQUEST['search_email'] ) ) {
					$email     = sanitize_text_field( wp_unslash( $_REQUEST['search_email'] ) );
					$email     = trim( $email );
					$order_ids = $this->get_search_by_email( $email );
				} elseif ( isset( $_REQUEST['search_reference'] ) ) {
					$reference = sanitize_text_field( wp_unslash( $_REQUEST['search_reference'] ) );
					$reference = trim( $reference );
					$order_ids = $this->get_search_by_reference( $reference );
				} elseif ( isset( $_REQUEST['shipment_send_type'] ) ) {
					$shipment_send_type = sanitize_text_field( wp_unslash( $_REQUEST['shipment_send_type'] ) );
					$order_ids          = $this->get_search_by_shipment_send_type( $shipment_send_type );
				}
			}
		} else {
			$order_ids = $this->get_total_results();
		}

		return is_array( $order_ids ) ? count( $order_ids ) : 0;
	}

	/**
	 * Get products
	 *
	 * @param int $per_page $per_page.
	 * @param int $page_number $page_number.
	 * @return array
	 */
	private function get_shipments( int $per_page = 20, int $page_number = 1 ) {

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		if ( isset( $_REQUEST['search_tracking'] ) || isset( $_REQUEST['search_order'] )
			|| isset( $_REQUEST['search_phone'] ) || isset( $_REQUEST['search_email'] )
			|| isset( $_REQUEST['search_reference'] )
			|| isset( $_REQUEST['shipment_send_type'] )
		) {

			if ( isset( $_GET['page'] ) && 'inpost-international-api' === $_GET['page'] && isset( $_GET['tab'] ) && 'shipments' === $_GET['tab'] ) {
				if ( isset( $_REQUEST['search_tracking'] ) ) {
					$tracking  = sanitize_text_field( wp_unslash( $_REQUEST['search_tracking'] ) );
					$tracking  = trim( $tracking );
					$order_ids = $this->get_search_by_tracking( $tracking );
				} elseif ( isset( $_REQUEST['search_order'] ) ) {
					$order_id  = sanitize_text_field( wp_unslash( $_REQUEST['search_order'] ) );
					$order_id  = trim( $order_id );
					$order_ids = $this->get_search_by_order( $order_id );
				} elseif ( isset( $_REQUEST['search_phone'] ) ) {
					$phone     = sanitize_text_field( wp_unslash( $_REQUEST['search_phone'] ) );
					$phone     = trim( $phone );
					$order_ids = $this->get_search_by_phone( $phone );
				} elseif ( isset( $_REQUEST['search_email'] ) ) {
					$email     = sanitize_text_field( wp_unslash( $_REQUEST['search_email'] ) );
					$email     = trim( $email );
					$order_ids = $this->get_search_by_email( $email );
				} elseif ( isset( $_REQUEST['search_reference'] ) ) {
					$reference = sanitize_text_field( wp_unslash( $_REQUEST['search_reference'] ) );
					$reference = trim( $reference );
					$order_ids = $this->get_search_by_reference( $reference );
				} elseif ( isset( $_REQUEST['shipment_send_type'] ) ) {
					$shipment_send_type = sanitize_text_field( wp_unslash( $_REQUEST['shipment_send_type'] ) );
					$order_ids          = $this->get_search_by_shipment_send_type( $shipment_send_type );
				}
			}
		} else {
			$order_ids = $this->get_non_search_results();
		}

		return is_array( $order_ids ) ? array_map( 'wc_get_order', $order_ids ) : array();
	}


	/**
	 * Column content
	 *
	 * @param  \WC_Order|WC_Order $item $item.
	 * @param string             $column_name $column_name.
	 * @return bool|string|void
	 */
	public function column_default( $item, $column_name ) {

		if ( $item && is_object( $item ) ) {

			switch ( $column_name ) {

				case 'add':
					return $this->get_shipment_id_preview_html( $item->get_id() );
				case 'order_id':
					return $this->link_to_order( $item );
				case 'order_tracking':
					return $this->get_shipment_tracking_number( $item );
				case 'status':
					return $this->get_status_preview_html( $item->get_id() );
				case 'dimensions':
					return $this->get_dimensions_preview_html( $item->get_id() );
				case 'send_method':
					return $this->get_send_method( $item->get_id() );
				case 'package_created':
					return $this->get_time_created( $item->get_id() );
				case 'package_dispatched':
					return ''; // $this->get_time_dispatched( $item->get_id() );
				case 'recipient':
					return $this->get_recipient_data( $item->get_id() );
				case 'ref_number':
					return $this->get_reference_number( $item->get_id() );
				case 'action':
					return $this->get_action_preview_html( $item->get_id() );

				default:
					return '';
			}
		}
	}

	/**
	 * Row checkbox
	 *
	 * @param \WC_Order $item $item.
	 * @return string|void
	 */
	public function column_cb( $item ) {
		return sprintf(
			'<input class="inpost_intl_check_row" type="checkbox" name="shipment[]" value="%s" />',
			$item->get_id()
		);
	}

	/**
	 * Column title
	 *
	 * @param \WC_Order $item $item.
	 * @return string
	 */
	public function column_title( $item ) {
		$actions = array();

		return sprintf( '%1$s %2$s', $item->get_id(), $this->row_actions( $actions ) );
	}

	/**
	 * Bulk actions
	 *
	 * @return array
	 */
	public function get_bulk_actions() {
		$actions = array();
		return $actions;
	}

	/**
	 * Process bulk action
	 *
	 * @return void
	 */
	public function process_bulk_action() {
	}


	/**
	 * Shipment status
	 *
	 * @param int|string $shipment_id $shipment_id.
	 * @return string
	 */
	public function get_status_preview_html( $shipment_id ) {

		$helper = new Helper();

		$status       = null;
		$output       = '';
		$package_data = $helper->get_package_meta( $shipment_id );

		if ( ! empty( $package_data['api_response']['status'] ) ) {
			$status = $package_data['api_response']['status'];
		}

		if ( $status ) {
			$output .= '<span data-shipment-id="' . $shipment_id . '" class="button-secondary shipment_status created">' . $status . '</span>';
		} else {
			$status  = esc_html__( 'Not created yet', 'inpost-international' );
			$output .= '<span data-shipment-id="' . $shipment_id . '" class="button-secondary shipment_status new">' . $status . '</span>';
		}

		return $output;
	}



	/**
	 * Get preview HTML
	 *
	 * @param int $order_id $order_id.
	 * @return false|string
	 */
	public function get_shipment_id_preview_html( $order_id ) {

		$output  = '';
		$output .= '<span data-shipment-id="' . $order_id . '" class="button-secondary shipment_id_add">+</span>';

		return $output;
	}

	/**
	 * Get action preview html
	 *
	 * @param int|string $order_id $order_id.
	 *
	 * @return string
	 * @throws \Exception Exception.
	 */
	public function get_action_preview_html( $order_id ) {
		$output = '';

		$helper             = new Helper();
		$package_data       = $helper->get_package_meta( $order_id );
		$is_package_created = ! empty( $package_data );

		if ( $is_package_created ) {
			$uuid            = '';
			$tracking_number = '';
			if ( ! empty( $package_data['api_response']['uuid'] ) ) {
				$uuid = $package_data['api_response']['uuid'];
			}

			if ( ! empty( $package_data['api_response']['trackingNumber'] ) ) {
				$tracking_number = $package_data['api_response']['trackingNumber'];
			}

			$animation_2 = inpost_intl_core()->get_plugin_images_url() . '/animation-round-small.gif';

			$output .= '<div class="btn-clone button-secondary inpost-intl-btn-shipment-action" data-uuid="' . esc_attr( $uuid ) . '" data-id="' . esc_attr( $order_id ) . '" title="Get Inpost label"><span id="inpost_intl_uuid" class="dashicons dashicons-admin-page inpost-intl-btn-shipment-action" data-uuid="' . esc_attr( $uuid ) . '" data-id="' . esc_attr( $order_id ) . '"></span></div>';

			$output .= '<div class="btn-to-scheduled button-secondary inpost-intl-btn-status-action" data-tracking="' . esc_attr( $tracking_number ) . '" data-id="' . esc_attr( $order_id ) . '" title="Get Inpost status"><span class="dashicons dashicons-clock inpost-intl-btn-status-action" data-tracking="' . esc_attr( $tracking_number ) . '" data-id="' . esc_attr( $order_id ) . '"></span></div>';
			$output .= '<span data-id="' . esc_attr( $order_id ) . '" class="inpost_intl_shipment_list_preloader"><img class="inpost_intl_preloader" src="' . esc_url( $animation_2 ) . '" alt="inpost international preloader"/></span><span data-id="' . esc_attr( $order_id ) . '" class="inpost_intl_shipment_list_status_error"></span>';

		}

		return $output;
	}


	/**
	 * Action preloader
	 *
	 * @param mixed $shipment_id $shipment_id.
	 *
	 * @return string
	 * @throws \Exception Exception.
	 */
	public function get_action_result_html( $shipment_id ) {
		return '<span class="inpost_action_result" data-id="' . esc_attr( $shipment_id ) . '">
        <img data-id="' . esc_attr( $shipment_id ) . '" class="inpost_action_result_preloader" src="' . esc_url( inpost_intl_core()->get_plugin_images_url() . '/big-round-preloader.gif' ) . '">
        </span>';
	}


	/**
	 * Render table and filters
	 *
	 * @return void
	 * @throws \Exception Exception.
	 */
	public static function render_custom_shipments_settings_page() {

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		$shipment_table = new Manage_Shipments_Table();

		$shipment_table->prepare_items();
		$current_rel_uri = add_query_arg( null, null );

		// Define allowed HTML attributes for option tag.
		$allowed_html = array(
			'option' => array(
				'value'            => true,
				'selected'         => true,
				'data-postal-code' => true,
			),
		);

		// Define allowed HTML attributes for select tag.
		$select_allowed_html = array(
			'select' => array(
				'name' => true,
				'id'   => true,
			),
            'option' => array(
                'value'            => true,
                'selected'         => true,
                'data-postal-code' => true,
                'data-id' => true,
            ),
		);
		?>
		<div class="wrap">
			<p class="inpost-intl-filter-box-shipments-pickup">
				<span class="filter-group cut-off">
					<?php
					$helper               = new Helper();
					$dispatch_points      = $helper->get_dispatch_points();
					$options_html         = '';
					$selected_postal_code = '';
					foreach ( $dispatch_points as $key => $point ) {
						$city         = ! empty( $point['city'] ) ? $point['city'] : '';
						$postal_code  = ! empty( $point['postal_code'] ) ? $point['postal_code'] : '';
						$street       = ! empty( $point['street'] ) ? $point['street'] : '';
						$house_number = ! empty( $point['building_number'] ) ? $point['building_number'] : '';
						$flat_number  = ! empty( $point['flat_number'] ) ? '-' . $point['flat_number'] : '';

						$select_text = $city . ', ' . $postal_code . ', ' . $street . ' ' . $house_number . $flat_number;

						if ( ! empty( $point['selected'] ) || 0 === intval( $key ) ) {
							$selected_postal_code = $postal_code;
							$options_html        .=
								'<option data-postal-code="' . esc_attr( $postal_code ) . '" value="' . esc_attr( $key ) . '" selected="selected">' . esc_html( $select_text ) . '</option>';
						} else {
							$options_html .= '<option data-postal-code="' . esc_attr( $postal_code ) . '" value="' . esc_attr( $key ) . '">' . esc_html( $select_text ) . '</option>';
						}
					}

					echo esc_html__( 'Place of pickup', 'inpost-international' );
					echo wp_kses(
						'<select name="inpost_intl_shipment_dispatch_point" id="inpost_intl_shipment_dispatch_point">' . $options_html . '</select>',
                        $select_allowed_html
					);

					echo '<input disabled type="text" id="inpost_intl_cutoff_postal_code" value="' . esc_attr( $selected_postal_code ) . '">';
					?>
					<?php echo '<input type="button" id="inpost_intl_cutoff_action" class="button" value="' . esc_html__( 'Get cut off time', 'inpost-international' ) . '">'; ?>

					<?php
					$animation_2 = inpost_intl_core()->get_plugin_images_url() . '/animation-round-small.gif';
					echo '<span class="inpost_intl_cut_off_preloader">
							<img class="inpost_intl_preloader" src="' . esc_url( $animation_2 ) . '" alt="inpost international preloader"/>
						</span>';

					echo esc_html__( 'Choose day and time of courier visit', 'inpost-international' );
					echo '<input type="date" class="inpost_intl_cutoff_date" value="">';
					echo '<input type="time" id="inpost_intl_cutoff_time_from" class="inpost_intl_cutoff_date" value="">';
					echo '<input type="time" id="inpost_intl_cutoff_time_api" class="inpost_intl_cutoff_date empty" disabled value="">';
					echo esc_html__( 'Quantity of shipments', 'inpost-international' );
					echo '<input type="number" min="1" step="1" id="inpost_intl_pickup_order_parcel_qty" value="">';
					echo esc_html__( 'Weight of shipments', 'inpost-international' );
					echo '<input type="number" min="0" step="0.1" id="inpost_intl_pickup_order_parcel_weight" value=""> kg';
					echo '<input disabled type="button" id="inpost_intl_create_pickup_order" class="button" value="' . esc_html__( 'Order a courier', 'inpost-international' ) . '">';
					echo '<span class="inpost_intl_pickup_order_preloader">
							<img class="inpost_intl_preloader" src="' . esc_url( $animation_2 ) . '" alt="inpost international preloader"/>
						</span>';

					?>
				</span>
				<?php
				echo '<div style="width:100%;" class="inpost-intl-prepre-box-shipments"><span id="create_pickup_order_result"></span></div>';
				?>
			</p>

			<div class="inpost_intl_manage_shipments">
				<h1><?php echo esc_html__( 'Manage shipments', 'inpost-international' ); ?></h1>
				<div id="inpost_intl_filters" class="inpost_intl_shipment_filters">
                    <?php
                    $current_page = '';
                    if( isset( $_REQUEST['page'] ) ) {
                        $current_page = sanitize_text_field( wp_unslash( $_REQUEST['page'] ) );
                    }
                    ?>
					<input type="hidden" name="page" value="<?php echo esc_attr( $current_page ); ?>" />

					<?php
					$search_tracking = ! empty( $_REQUEST['search_tracking'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['search_tracking'] ) ) ) : '';
					$search_order    = ! empty( $_REQUEST['search_order'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['search_order'] ) ) ) : '';
					$search_phone    = ! empty( $_REQUEST['search_phone'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['search_phone'] ) ) ) : '';
					$search_email    = ! empty( $_REQUEST['search_email'] ) ? esc_attr( sanitize_text_field( wp_unslash( $_REQUEST['search_email'] ) ) ) : '';

                    $country_code = 'PL';
                    $sender_options = get_option( 'inpost_international_settings_merchant' );
                    if ( ! empty( $sender_options['country'] ) ) {
                        $country_code = $sender_options['country'];
                    }

                    ?>

					<p class="inpost-intl-search-box">
						<input type="search" id="inpost-intl-search-tracking" class="inpost-intl-shipm-search-input" name="s1" placeholder="<?php echo esc_html__( 'Tracking number', 'inpost-international' ); ?>" value="<?php echo esc_attr( $search_tracking ); ?>">
						<input type="search" id="inpost-intl-search-order" class="inpost-intl-shipm-search-input" name="s2" placeholder="<?php echo esc_html__( 'Order number', 'inpost-international' ); ?>" value="<?php echo esc_attr( $search_order ); ?>">
						<input type="search" id="inpost-intl-search-phone" class="inpost-intl-shipm-search-input" name="s3" placeholder="<?php echo esc_html__( 'Phone number', 'inpost-international' ); ?>" value="<?php echo esc_attr( $search_phone ); ?>">
						<input type="search" id="inpost-intl-search-email" class="inpost-intl-shipm-search-input" name="s4" placeholder="<?php echo esc_html__( 'E-mail of receiver', 'inpost-international' ); ?>" value="<?php echo esc_attr( $search_email ); ?>">
						<input type="search" id="inpost-intl-search-reference" class="inpost-intl-shipm-search-input" name="s5" placeholder="<?php echo esc_html__( 'Reference number', 'inpost-international' ); ?>" value="">
						<input type="button" id="inpost-intl-search-shipments-submit" class="button" value="<?php echo esc_html__( 'Search shipments', 'inpost-international' ); ?>">
						<input type="button" id="inpost-intl-search-shipments-reset" class="button" value="<?php echo esc_html__( 'Reset', 'inpost-international' ); ?>">
					</p>


					<div class="inpost-intl-filter-box-shipments">
                        <div class="filter-group">
                            <?php
                            $send_methods = array(
                                'apm'     => esc_html__( 'APM/PUDO/HUB', 'inpost-international' ),
                                'courier' => esc_html__( 'Courier', 'inpost-international' ),
                            );

                            if ( 'IT' === $country_code ) {
                                $send_methods = array(
                                    'apm'     => esc_html__( 'APM/PUDO', 'inpost-international' ),
                                    'courier' => esc_html__( 'Courier', 'inpost-international' ),
                                );
                            }

                            echo '<select name="shipment_send_type" id="shipment_send_type">';
                            echo '<option value="">' . esc_html__( 'Send method', 'inpost-international' ) . '</option>';
                            foreach ( $send_methods as $value => $label ) {
                                echo '<option value="' . esc_attr( $value ) . '"';
                                if ( isset( $_GET['shipment_send_type'] ) && $value === $_GET['shipment_send_type'] ) {
                                    echo ' selected="selected"';
                                }
                                echo '>' . esc_html( $label ) . '</option>';
                            }
                            echo '</select>';
                            echo '<input type="button" name="filter_action" id="filter_action_shipments_send_method" class="button" value="' . esc_html__( 'Filter', 'inpost-international' ) . '">';
                            ?>
                        </div>

						<div class="filter-group">
							<?php
							$shipment_qtys = array(
								'5'   => '5',
								'10'  => '10',
								'20'  => '20',
								'50'  => '50',
								'100' => '100',
								'200' => '200',
								'500' => '500',
							);
							echo '<select name="shipment_qty" id="dropdown_shipment_qty">';
							echo '<option value="">' . esc_html__( 'Per page', 'inpost-international' ) . '</option>';
							foreach ( $shipment_qtys as $value => $label ) {
								echo '<option value="' . esc_attr( $value ) . '"';
								if ( isset( $_GET['shipment_qty'] ) && $value === $_GET['shipment_qty'] ) {
									echo ' selected="selected"';
								}
								echo '>' . esc_html( $label ) . '</option>';
							}
							echo '</select>';
							echo '<input type="button" name="filter_action" id="filter_action_shipments" class="button" value="Filter">';
							?>
						</div>

						<div class="filter-group">
							<?php
							echo '<input type="button" id="inpost_intl_shipments_labels_bulk" class="button" value="' . esc_html__( 'Get labels', 'inpost-international' ) . '">';
							$animation_2 = inpost_intl_core()->get_plugin_images_url() . '/animation-round-small.gif';
							echo '<span class="inpost_intl_get_labels_preloader">
								<img class="inpost_intl_preloader" src="' . esc_url( $animation_2 ) . '" alt="inpost international preloader"/>
							</span>';
							?>
						</div>

					</div>
				</div>
			</div>

			<div class="custom_shipments_table_actions">
				<?php
				$shipment_table->display();
				?>
			</div>
		</div>
		<?php
	}


	/**
	 * Generates a link to the order details page with the order number as the anchor text.
	 * Supports both HPOS and the old post meta system.
	 *
	 * @param WC_Order $item The WooCommerce order object.
	 * @return string HTML anchor tag linking to the order details page.
	 */
	public function link_to_order( $item ) {
		$order_id     = $item->get_id();
		$order_number = $item->get_order_number();

		// Check if HPOS is enabled.
		if ( 'yes' === get_option( 'woocommerce_custom_orders_table_enabled' ) ) {
			// HPOS is enabled, use the new URL structure.
			$order_url = admin_url( 'admin.php?page=wc-orders&action=edit&id=' . absint( $order_id ) );
		} else {
			// HPOS is not enabled, use the old URL structure.
			$order_url = admin_url( 'post.php?post=' . absint( $order_id ) . '&action=edit' );
		}

		$link = sprintf(
			'<a href="%s" target="_blank" class="order-view"><strong>#%s</strong></a>',
			esc_url( $order_url ),
			esc_html( $order_number )
		);

		return $link;
	}

	/**
	 * Retrieves and formats the shipment tracking number with a clickable link.
	 *
	 * This function gets the tracking number from package metadata and creates
	 * a formatted HTML link to track the shipment. If no tracking number exists,
	 * returns an empty string.
	 *
	 * @since 1.0.0
	 *
	 * @param WP_Post|WC_Order $item Order object containing the order ID.
	 *
	 * @return string
	 *
	 * @uses Helper::get_tracking_url()
	 * @uses Helper::get_package_meta()
	 */
	public function get_shipment_tracking_number( $item ) {
		$order_id = $item->get_id();

		$helper = new Helper();

		$link            = '';
		$tracking_number = '';
		$tracking_url    = $helper->get_tracking_url();

		$package_data = $helper->get_package_meta( $order_id );
		if ( ! empty( $package_data['api_response']['trackingNumber'] ) ) {
			$tracking_number    = $package_data['api_response']['trackingNumber'];
			$full_tracking_link = $tracking_url . $tracking_number;
			$link               = sprintf(
				'<a href="%s" target="_blank" class="view-tracking-details"><strong>%s</strong></a>',
				esc_url( $full_tracking_link ),
				esc_html( $tracking_number )
			);
		}

		return $link;
	}


	/**
	 * Generates HTML preview of package dimensions and weight.
	 *
	 * Retrieves package dimensions and weight from order metadata and formats them
	 * into a readable string with hidden input for weight value.
	 *
	 * @since 1.0.0
	 *
	 * @param int $order_id WooCommerce order ID.
	 *
	 * @return string Formatted dimensions string with hidden input field.
	 *                Format: "height x width x length CM, weight KG
	 *                        <input type="hidden" class="shipment_weight" data-order-id="order_id" value="weight">"
	 *                Returns empty string if no dimension data exists.
	 *
	 * @uses Helper::get_package_meta()
	 *
	 * Example return:
	 * "10 x 20 x 30 CM, 2.5 KG<input type="hidden" class="shipment_weight" data-order-id="123" value="2.5">"
	 */
	public function get_dimensions_preview_html( $order_id ) {

		$helper = new Helper();

		$dimensions = '';

		$package_data = $helper->get_package_meta( $order_id );
		if ( ! empty( $package_data['creating_args']['shipment']['parcel'] ) ) {

			$shipment = $package_data['creating_args']['shipment']['parcel'];

			$weight = ! empty( $shipment['weight']['amount'] ) ? $shipment['weight']['amount'] : '';

			if ( ! empty( $shipment['dimensions'] ) ) {
				$dim    = $shipment['dimensions'];
				$length = ! empty( $dim['length'] ) ? $dim['length'] : '';
				$width  = ! empty( $dim['width'] ) ? $dim['width'] : '';
				$height = ! empty( $dim['height'] ) ? $dim['height'] : '';

				$dimensions  = $height . ' x ' . $width . ' x ' . $length . ' CM, ' . $weight . ' KG';
				$dimensions .= '<input type="hidden" class="shipment_weight" data-order-id="' . esc_attr( $order_id ) . '" value="' . esc_attr( $weight ) . '">';

			}
		}

		return $dimensions;
	}


	/**
	 * Determines and returns the shipping method type for an order.
	 *
	 * Analyzes package metadata to determine whether the shipping method is
	 * via Courier or APM/PUDO/HUB based on the origin address configuration.
	 *
	 * @since 1.0.0
	 *
	 * @param int $order_id WooCommerce order ID.
	 *
	 * @return string Translated shipping method type.
	 *                Either 'Courier' or 'APM/PUDO/HUB'.
	 *                Returns empty string if no method is determined.
	 *
	 * @uses Helper::get_package_meta()
	 *
	 * @global string 'inpost-international' Text domain for translations
	 *
	 * Example returns:
	 * - "Courier"
	 * - "APM/PUDO/HUB"
	 * - ""
	 */
	public function get_send_method( $order_id ) {

		$helper = new Helper();

		$send_method = '';

        $sender_options = get_option( 'inpost_international_settings_merchant' );
        if ( ! empty( $sender_options['country'] ) ) {
            $country_code = $sender_options['country'];
        }

		$package_data = $helper->get_package_meta( $order_id );
		if ( ! empty( $package_data['creating_args']['shipment']['origin']['address'] ) ) {
			$send_method = esc_html__( 'Courier', 'inpost-international' );
		} elseif ( ! empty( $package_data['creating_args']['shipment']['origin']['shippingMethods'] ) ) {
			$send_method = esc_html__( 'APM/PUDO/HUB', 'inpost-international' );
            if ( 'IT' === $country_code ) {
                $send_method = esc_html__( 'APM/PUDO', 'inpost-international' );
            }
		}


		return $send_method;
	}


	public function get_time_created( $order_id ) {
		$helper = new Helper();

		$formatted_date = '';

		$package_data = $helper->get_package_meta( $order_id );
		if ( ! empty( $package_data['package_created'] ) ) {
			$timestamp = $package_data['package_created'];
			// Set locale to Polish.
			setlocale( LC_TIME, 'pl_PL.UTF-8' );
			// Format the date.
			$formatted_date = wp_date( 'j F Y H:i', $timestamp, wp_timezone() );

			// Translate month name to Polish.
			$polish_months = array(
				'January'   => 'stycznia',
				'February'  => 'lutego',
				'March'     => 'marca',
				'April'     => 'kwietnia',
				'May'       => 'maja',
				'June'      => 'czerwca',
				'July'      => 'lipca',
				'August'    => 'sierpnia',
				'September' => 'września',
				'October'   => 'października',
				'November'  => 'listopada',
				'December'  => 'grudnia',
			);

			foreach ( $polish_months as $english => $polish ) {
				$formatted_date = str_replace( $english, $polish, $formatted_date );
			}
		}

		return $formatted_date;
	}

	/**
	 * Retrieves and formats the package creation timestamp in Polish format.
	 *
	 * Converts the package creation timestamp into a formatted date string
	 * with Polish month names. Uses WordPress timezone settings.
	 *
	 * @since 1.0.0
	 *
	 * @param int $order_id WooCommerce order ID.
	 *
	 * @return string Formatted date string in Polish format.
	 *                Format: "d month_name Y H:i" (e.g., "15 stycznia 2024 14:30")
	 *                Returns empty string if no creation date exists.
	 *
	 * @uses Helper::get_package_meta()
	 * @uses wp_date()
	 * @uses wp_timezone()
	 *
	 * @example
	 * Input timestamp: 1704456000
	 * Output: "5 stycznia 2024 12:00"
	 *
	 * @global string LC_TIME Locale setting for time formatting
	 */
	public function get_time_dispatched( $order_id ) {
		$helper = new Helper();

		$formatted_date = '';

		$package_data = $helper->get_package_meta( $order_id );
		// if ( ! empty( $package_data['package_created'] ) ) {
		if ( false ) {

			$timestamp = $package_data['package_created'];
			setlocale( LC_TIME, 'pl_PL.UTF-8' );
			$formatted_date = wp_date( 'j F Y H:i', $timestamp, wp_timezone() );

			$polish_months = array(
				'January'   => 'stycznia',
				'February'  => 'lutego',
				'March'     => 'marca',
				'April'     => 'kwietnia',
				'May'       => 'maja',
				'June'      => 'czerwca',
				'July'      => 'lipca',
				'August'    => 'sierpnia',
				'September' => 'września',
				'October'   => 'października',
				'November'  => 'listopada',
				'December'  => 'grudnia',
			);

			foreach ( $polish_months as $english => $polish ) {
				$formatted_date = str_replace( $english, $polish, $formatted_date );
			}
		}

		return $formatted_date;
	}


	/**
	 * Get recipient data and generate HTML for display in a table cell.
	 *
	 * @param int $order_id The ID of the order.
	 * @return string HTML representation of recipient data.
	 */
	public function get_recipient_data( $order_id ) {
		$helper           = new Helper();
		$order            = wc_get_order( $order_id );
		$shipping_country = $order->get_shipping_country();
		$data             = '';
		$package_data     = $helper->get_package_meta( $order_id );

		if ( ! empty( $package_data['creating_args']['shipment']['recipient'] ) ) {
			$recipient  = $package_data['creating_args']['shipment']['recipient'];
			$first_name = ! empty( $recipient['firstName'] ) ? $recipient['firstName'] : '';
			$last_name  = ! empty( $recipient['lastName'] ) ? $recipient['lastName'] : '';
			$company    = ! empty( $recipient['companyName'] ) ? $recipient['companyName'] : '';
			$email      = ! empty( $recipient['email'] ) ? $recipient['email'] : '';
			$phone      = '';
			if ( ! empty( $recipient['phone']['number'] ) ) {
				$phone_prefix = ! empty( $recipient['phone']['prefix'] ) ? $recipient['phone']['prefix'] : '';
				$phone        = $phone_prefix . $recipient['phone']['number'];
			}

			$data  = '<div class="recipient-data">';
			$data .= '<p class="recipient-name"><strong>' . esc_html( $first_name . ' ' . $last_name ) . '</strong></p>';
			if ( ! empty( $company ) ) {
				$data .= '<p class="recipient-company">' . esc_html( $company ) . '</p>';
			}
			if ( ! empty( $email ) ) {
				$data .= '<p class="recipient-email"><a href="mailto:' . esc_attr( $email ) . '">' . esc_html( $email ) . '</a></p>';
			}
			if ( ! empty( $phone ) ) {
				$data .= '<p class="recipient-phone"><a href="tel:' . esc_attr( $phone ) . '">' . esc_html( $phone ) . '</a></p>';
			}
			$data .= '<p class="recipient-country">' . esc_html( $shipping_country ) . '</p>';
			$data .= '</div>';
		} else {

			$first_name       = $order->get_billing_first_name();
			$last_name        = $order->get_billing_last_name();
			$company          = $order->get_billing_company();
			$email            = $order->get_billing_email();
			$phone            = $order->get_billing_phone();
			$shipping_country = $order->get_shipping_country();

			$data  = '<div class="recipient-data">';
			$data .= '<p class="recipient-name"><strong>' . esc_html( $first_name . ' ' . $last_name ) . '</strong></p>';

			if ( ! empty( $company ) ) {
				$data .= '<p class="recipient-company">' . esc_html( $company ) . '</p>';
			}

			if ( ! empty( $email ) ) {
				$data .= '<p class="recipient-email"><a href="mailto:' . esc_attr( $email ) . '">' . esc_html( $email ) . '</a></p>';
			}

			if ( ! empty( $phone ) ) {
				$data .= '<p class="recipient-phone"><a href="tel:' . esc_attr( $phone ) . '">' . esc_html( $phone ) . '</a></p>';
			}

			$data .= '<p class="recipient-country">' . esc_html( $shipping_country ) . '</p>';
			$data .= '</div>';
		}

		return $data;
	}


	/**
	 * Retrieves the reference number from package label comment.
	 *
	 * Extracts the reference number from the shipment parcel label comment
	 * stored in the package metadata.
	 *
	 * @since 1.0.0
	 *
	 * @param int $order_id WooCommerce order ID.
	 *
	 * @return string Reference number from package label comment.
	 *                Returns empty string if no reference number exists.
	 *
	 * @uses Helper::get_package_meta()
	 *
	 * Example:
	 * - Input order_id: 123
	 * - Return: "REF123456" or ""
	 */
	public function get_reference_number( $order_id ) {
		$helper       = new Helper();
		$ref_number   = '';
		$package_data = $helper->get_package_meta( $order_id );

		if ( ! empty( $package_data['creating_args']['shipment']['parcel']['label']['comment'] ) ) {
			$ref_number = $package_data['creating_args']['shipment']['parcel']['label']['comment'];
		}

		return $ref_number;
	}


	/**
	 * Generates content for a single row of the table.
	 *
	 * @since 3.1.0
	 *
	 * @param object|array $item The current item.
	 */
	public function single_row( $item ) {
		$order_id = $item->get_id();
		echo '<tr id="inpost-int-shipment-' . esc_attr( $order_id ) . '">';
		$this->single_row_columns( $item );
		echo '</tr>';
	}

	/**
	 * Displays the table.
	 *
	 * @since 3.1.0
	 */
	public function display() {
		$singular = $this->_args['singular'];

		$this->display_tablenav( 'top' );

		$this->screen->render_screen_reader_content( 'heading_list' );
		?>
		<table class="inpost-intl wp-list-table <?php echo esc_html( implode( ' ', $this->get_table_classes() ) ); ?>">
			<?php $this->print_table_description(); ?>
			<thead>
			<tr>
				<?php $this->print_column_headers(); ?>
			</tr>
			</thead>

			<tbody id="the-list-inpost-international-shipments"
				<?php
				if ( $singular ) {
					echo " data-wp-lists='list:" . esc_html( $singular ) . "'";
				}
				?>
			>
			<?php $this->display_rows_or_placeholder(); ?>
			</tbody>

			<tfoot>
			<tr>
				<?php $this->print_column_headers( false ); ?>
			</tr>
			</tfoot>

		</table>
		<?php
		$this->display_tablenav( 'bottom' );
		// package status modal HTML.
		$img = inpost_intl_core()->get_plugin_images_url() . '/yellow.png';
		?>
		<div id="inpost_intl_status_modal" class="inpost_intl_status_modal">
			<div class="modalCover"></div>
			<div class="modalContext">
				<div class="inpost_intl_status_modal_close"></div>
				<div class="inpost_intl_status_modal_text_wrapper">
					<img id="inpost_intl_logo" src="<?php echo esc_attr( $img ); ?>">
				</div>
				<div class="inpost_intl_status_modal_title">
					<h2><?php echo esc_html__( 'Tracking number:', 'inpost-international' ); ?></h2>
					<h3><span class="inpost_intl_status_modal_tracking"></span></h3>
				</div>
				<div class="inpost_intl_status_modal_text">
				</div>
				<div class="inpost_intl_status_modal_action">
					<button id="inpost_intl_status_modal_close_button">Ok</button>
				</div>
			</div>
		</div>
		<input type="hidden" id="inpost_intl_shipment_table_nonce" value="<?php echo esc_attr( wp_create_nonce( 'inpost_international_manage_shipments' ) ); ?>">
		<?php
	}


	/**
	 * Retrieves a paginated list of order IDs with InPost International locker assignments.
	 *
	 * Performs a database query to fetch orders with InPost locker IDs, supporting both
	 * traditional WordPress post meta and WooCommerce HPOS (High-Performance Order Storage).
	 * Results can be sorted and paginated based on request parameters.
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 *
	 * @return array Array of order IDs matching the query criteria
	 *
	 * Request parameters used:
	 * - shipment_qty:     (int) Number of items per page (default: 20)
	 * - shipments_paged:  (int) Current page number (default: 1)
	 * - orderby:          (string) Sort by 'inpost_international_locker_id' or 'date_created_gmt'
	 * - order:            (string) Sort order 'ASC' or 'DESC' (default: 'DESC')
	 *
	 * @example
	 * $_REQUEST = [
	 *     'shipment_qty' => 10,
	 *     'shipments_paged' => 2,
	 *     'orderby' => 'inpost_international_locker_id',
	 *     'order' => 'ASC'
	 * ];
	 * $order_ids = $this->get_non_search_results();
	 */
	private function get_non_search_results() {
		$result = array();

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		global  $wpdb;

		$per_page    = 20;
		$page_number = 1;
		if ( ! empty( $_REQUEST['shipment_qty'] ) ) {
			$per_page = intval( sanitize_text_field( wp_unslash( $_REQUEST['shipment_qty'] ) ) );
		}
		if ( ! empty( $_REQUEST['shipments_paged'] ) ) {
			$page_number = intval( sanitize_text_field( wp_unslash( $_REQUEST['shipments_paged'] ) ) );
		}

		$offset  = ( $page_number - 1 ) * $per_page;
		$orderby = isset( $_REQUEST['orderby'] ) ? 'inpost_international_locker_id' : 'date_created_gmt';
		$order   = isset( $_REQUEST['order'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) : 'DESC';
		$order   = in_array( $order, array( 'ASC', 'DESC' ) ) ? $order : 'DESC';

		// Check if HPOS is enabled.
		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$order_by_clause = 'inpost_international_locker_id' === $orderby ? 'om.meta_value' : 'o.date_created_gmt';

			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id FROM {$wpdb->prefix}wc_orders o
						INNER JOIN {$wpdb->prefix}wc_order_operational_data od ON o.id = od.order_id
						INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
						WHERE o.type = 'shop_order'
						AND o.status IN ('wc-pending', 'wc-processing', 'wc-on-hold', 'wc-completed')
						AND om.meta_key = 'inpost_international_locker_id'
						AND om.meta_value != ''
						ORDER BY " . '%s  %s
						LIMIT %d OFFSET %d',
                $order_by_clause,
				$order,
				$per_page,
				$offset
			);

		} else {
			// Traditional Post Meta Query.
			$order_by_clause = 'inpost_international_locker_id' === $orderby ? 'pm.meta_value' : 'p.post_date';

			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID FROM {$wpdb->posts} p
						INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
						WHERE p.post_type = 'shop_order'
						AND p.post_status IN ('wc-pending', 'wc-processing', 'wc-on-hold', 'wc-completed')
						AND pm.meta_key = 'inpost_international_locker_id'
						AND pm.meta_value != ''
						ORDER BY " . '%s  %s
						LIMIT %d OFFSET %d',
                $order_by_clause,
				$order,
				$per_page,
				$offset
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Searches for a specific order with InPost International locker assignment.
	 *
	 * Performs a database query to check if a specific order ID has an associated
	 * InPost locker ID. Supports both traditional WordPress post meta and
	 * WooCommerce HPOS (High-Performance Order Storage).
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param int $order_id WooCommerce order ID to search for.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 *
	 * @return array Array containing the order ID if found with locker assignment,
	 *               empty array if not found or no locker assigned.
	 *
	 * @example
	 * // Search for order #123
	 * $result = $this->get_search_by_order(123);
	 * // Returns: [123] if found with locker, [] if not found
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 */
	private function get_search_by_order( $order_id ) {

		$result = array();

		global  $wpdb;

		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$sql = $wpdb->prepare(
				"SELECT o.id FROM {$wpdb->prefix}wc_orders o
         INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
         WHERE o.id = %d
         AND o.type = 'shop_order'
         AND om.meta_key = 'inpost_international_locker_id'
         AND om.meta_value != ''
         LIMIT 1",
				$order_id
			);
		} else {
			// Traditional Post Meta Query.
			$sql = $wpdb->prepare(
				"SELECT p.ID FROM {$wpdb->posts} p
         INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
         WHERE p.ID = %d
         AND p.post_type = 'shop_order'
         AND pm.meta_key = 'inpost_international_locker_id'
         AND pm.meta_value != ''
         LIMIT 1",
				$order_id
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Searches for orders by InPost tracking number.
	 *
	 * Performs a database query to find orders with a specific tracking number
	 * stored in the package metadata. Supports both traditional WordPress post meta
	 * and WooCommerce HPOS (High-Performance Order Storage).
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param string $tracking_number InPost tracking number to search for.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 * @uses sanitize_text_field() To sanitize input
	 * @uses wpdb::esc_like() To escape LIKE query
	 *
	 * @return array Array of order IDs that match the tracking number.
	 *               Returns empty array if no matches found.
	 *
	 * @example
	 * // Search for tracking number "123456789"
	 * $result = $this->get_search_by_tracking('123456789');
	 * // Returns: [123, 456] (order IDs with matching tracking number)
	 *
	 * Security measures:
	 * - Input sanitization using sanitize_text_field()
	 * - SQL injection prevention using wpdb::prepare() and esc_like()
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 */
	private function get_search_by_tracking( $tracking_number ) {
		global $wpdb;
		$result = array();

		$tracking_number = sanitize_text_field( $tracking_number );

		// Prepare the JSON search pattern.
		$search_pattern = '%"trackingNumber":"' . $wpdb->esc_like( $tracking_number ) . '"%';

		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id
            FROM {$wpdb->prefix}wc_orders o
            INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
            WHERE o.type = 'shop_order'
            AND om.meta_key = 'inpost_international_package'
            AND om.meta_value LIKE %s",
				$search_pattern
			);
		} else {
			// Traditional Post Meta Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID
            FROM {$wpdb->posts} p
            INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
            WHERE p.post_type = 'shop_order'
            AND pm.meta_key = 'inpost_international_package'
            AND pm.meta_value LIKE %s",
				$search_pattern
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Searches for orders by recipient's phone number.
	 *
	 * Performs a database query to find orders with a specific phone number
	 * stored in the package metadata. Supports both traditional WordPress post meta
	 * and WooCommerce HPOS (High-Performance Order Storage). Phone numbers are
	 * sanitized to contain only digits before searching.
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param string $phone_number Phone number to search for (can include formatting).
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 * @uses sanitize_text_field() To sanitize input
	 * @uses wpdb::esc_like() To escape LIKE query
	 *
	 * @return array Array of order IDs that match the phone number.
	 *               Returns empty array if no matches found.
	 *
	 * @example
	 * // Search for phone number "+48 123-456-789"
	 * $result = $this->get_search_by_phone('+48 123-456-789');
	 * // Number will be sanitized to "123456789" before searching
	 * // Returns: [123, 456] (order IDs with matching phone number)
	 *
	 * Security measures:
	 * - Input sanitization using sanitize_text_field()
	 * - Phone number cleaning (digits only)
	 * - SQL injection prevention using wpdb::prepare() and esc_like()
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 */
	private function get_search_by_phone( $phone_number ) {
		global $wpdb;
		$result       = array();
		$phone_number = sanitize_text_field( $phone_number );
		$phone_number = preg_replace( '/[^0-9]/', '', $phone_number );

		$search_pattern = '%"number":"%' . $wpdb->esc_like( $phone_number ) . '%"%';

		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id
            FROM {$wpdb->prefix}wc_orders o
            INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
            WHERE o.type = 'shop_order'
            AND om.meta_key = 'inpost_international_package'
            AND om.meta_value LIKE %s",
				$search_pattern
			);
		} else {
			// Traditional Post Meta Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID
            FROM {$wpdb->posts} p
            INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
            WHERE p.post_type = 'shop_order'
            AND pm.meta_key = 'inpost_international_package'
            AND pm.meta_value LIKE %s",
				$search_pattern
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Searches for orders by recipient's email address.
	 *
	 * Performs a database query to find orders with a specific email address
	 * stored in the package metadata. Supports both traditional WordPress post meta
	 * and WooCommerce HPOS (High-Performance Order Storage).
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param string $email Email address to search for.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 * @uses sanitize_text_field() To sanitize input
	 * @uses wpdb::esc_like() To escape LIKE query
	 *
	 * @return array Array of order IDs that match the email address.
	 *               Returns empty array if no matches found.
	 *
	 * @example
	 * // Search for email "customer@example.com"
	 * $result = $this->get_search_by_email('customer@example.com');
	 * // Returns: [123, 456] (order IDs with matching email)
	 *
	 * Security measures:
	 * - Input sanitization using sanitize_text_field()
	 * - SQL injection prevention using wpdb::prepare() and esc_like()
	 * - Partial email matching supported through LIKE query
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 *
	 * Meta key searched: 'inpost_international_package'
	 */
	private function get_search_by_email( $email ) {
		global $wpdb;
		$result = array();
		$email  = sanitize_text_field( $email );

		// Prepare the JSON search pattern.
		$search_pattern = '%"email":"%' . $wpdb->esc_like( $email ) . '%"%';

		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id
            FROM {$wpdb->prefix}wc_orders o
            INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
            WHERE o.type = 'shop_order'
            AND om.meta_key = 'inpost_international_package'
            AND om.meta_value LIKE %s",
				$search_pattern
			);
		} else {
			// Traditional Post Meta Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID
            FROM {$wpdb->posts} p
            INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
            WHERE p.post_type = 'shop_order'
            AND pm.meta_key = 'inpost_international_package'
            AND pm.meta_value LIKE %s",
				$search_pattern
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Retrieves all order IDs with InPost International locker assignments.
	 *
	 * Gets a complete list of orders that have InPost locker assignments,
	 * supporting both traditional WordPress post meta and WooCommerce HPOS.
	 * Results can be sorted based on request parameters.
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 *
	 * @return array Array of all matching order IDs
	 *
	 * Request parameters used:
	 * - orderby: (string) Sort by 'inpost_international_locker_id' or 'date_created_gmt'
	 * - order:   (string) Sort direction 'ASC' or 'DESC' (default: 'DESC')
	 *
	 * Order statuses included:
	 * - wc-pending
	 * - wc-processing
	 * - wc-on-hold
	 * - wc-completed
	 *
	 * @example
	 * $_REQUEST = [
	 *     'orderby' => 'inpost_international_locker_id',
	 *     'order' => 'ASC'
	 * ];
	 * $all_orders = $this->get_total_results();
	 *
	 * Database tables used:
	 * - HPOS: wc_orders, wc_order_operational_data, wc_orders_meta
	 * - Traditional: posts, postmeta
	 *
	 * Security measures:
	 * - Input sanitization for order direction
	 * - Validation of sort parameters
	 */
	private function get_total_results() {

        if( ! empty( $_REQUEST['nonce']) ) {
            check_ajax_referer('inpost_international_ajax', 'nonce');
        }

		global $wpdb;

		$orderby = isset( $_REQUEST['orderby'] ) ? 'inpost_international_locker_id' : 'date_created_gmt';
		$order   = isset( $_REQUEST['order'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) : 'DESC';
		$order   = in_array( $order, array( 'ASC', 'DESC' ) ) ? $order : 'DESC';

		// Check if HPOS is enabled.
		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$order_direction = in_array( strtoupper( $order ), array( 'ASC', 'DESC' ) ) ? $order : 'DESC';
			$sort_column     = $orderby === 'inpost_international_locker_id' ? 'om.meta_value' : 'o.date_created_gmt';

			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id FROM {$wpdb->prefix}wc_orders o
						INNER JOIN {$wpdb->prefix}wc_order_operational_data od ON o.id = od.order_id
						INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
						WHERE o.type = %s
						AND o.status IN (%s, %s, %s, %s)
						AND om.meta_key = %s
						AND om.meta_value != %s
						ORDER BY %s %s",
				'shop_order',
				'wc-pending',
				'wc-processing',
				'wc-on-hold',
				'wc-completed',
				'inpost_international_locker_id',
				'',
				$sort_column,
				$order_direction
			);
		} else {
			// Traditional Post Meta Query.
			$order_direction = in_array( strtoupper( $order ), array( 'ASC', 'DESC' ) ) ? $order : 'DESC';
			$sort_column     = $orderby === 'inpost_international_locker_id' ? 'pm.meta_value' : 'p.post_date';

			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID FROM {$wpdb->posts} p
						INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
						WHERE p.post_type = %s
						AND p.post_status IN (%s, %s, %s, %s)
						AND pm.meta_key = %s
						AND pm.meta_value != %s
						ORDER BY %s %s",
				'shop_order',
				'wc-pending',
				'wc-processing',
				'wc-on-hold',
				'wc-completed',
				'inpost_international_locker_id',
				'',
				$sort_column,
				$order_direction
			);
		}

		$all_orders = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $all_orders;
	}

	/**
	 * Searches for orders by reference number in package comments.
	 *
	 * Performs a database query to find orders with a specific reference number
	 * stored in the package metadata comments. Supports both traditional WordPress
	 * post meta and WooCommerce HPOS (High-Performance Order Storage).
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param string $ref Reference number to search for.
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 * @uses sanitize_text_field() To sanitize input
	 * @uses wpdb::esc_like() To escape LIKE query
	 *
	 * @return array Array of order IDs that match the reference number.
	 *               Returns empty array if no matches found.
	 *
	 * @example
	 * // Search for reference number "REF123"
	 * $result = $this->get_search_by_reference('REF123');
	 * // Returns: [123, 456] (order IDs with matching reference)
	 *
	 * Security measures:
	 * - Input sanitization using sanitize_text_field()
	 * - SQL injection prevention using wpdb::prepare() and esc_like()
	 * - Partial reference matching supported through LIKE query
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 *
	 * Meta key searched: 'inpost_international_package'
	 * JSON field searched: 'comment'
	 */
	private function get_search_by_reference( $ref ) {

		global $wpdb;
		$result = array();

		$ref = sanitize_text_field( $ref );

		// Prepare the JSON search pattern.
		$search_pattern = '%"comment":"%' . $wpdb->esc_like( $ref ) . '%"%';

		$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

		if ( $hpos_enabled ) {
			// HPOS Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT o.id
            FROM {$wpdb->prefix}wc_orders o
            INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
            WHERE o.type = 'shop_order'
            AND om.meta_key = 'inpost_international_package'
            AND om.meta_value LIKE %s",
				$search_pattern
			);
		} else {
			// Traditional Post Meta Query.
			$sql = $wpdb->prepare(
				"SELECT DISTINCT p.ID
            FROM {$wpdb->posts} p
            INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
            WHERE p.post_type = 'shop_order'
            AND pm.meta_key = 'inpost_international_package'
            AND pm.meta_value LIKE %s",
				$search_pattern
			);
		}

		$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

		return $result;
	}


	/**
	 * Searches for orders by shipment send type (courier or non-courier).
	 *
	 * Performs a cached database query to find orders based on their shipping method,
	 * distinguishing between courier and APM/PUDO/HUB deliveries. Supports both
	 * traditional WordPress post meta and WooCommerce HPOS.
	 *
	 * @since 1.0.0
	 *
	 * @access private
	 *
	 * @param string $send_type Shipping method type ('courier' or other).
	 *                         'courier' - searches for orders with address field
	 *                         other - searches for orders without address field (APM/PUDO/HUB)
	 *
	 * @global wpdb $wpdb WordPress database abstraction object
	 *
	 * @uses get_option() To check if HPOS is enabled
	 * @uses sanitize_text_field() To sanitize input
	 * @uses wp_cache_get() To retrieve cached results
	 * @uses wp_cache_set() To cache query results
	 *
	 * @return array Array of order IDs matching the send type criteria.
	 *               Returns empty array if no matches found.
	 *
	 * @example
	 * // Search for courier shipments
	 * $courier_orders = $this->get_search_by_shipment_send_type('courier');
	 *
	 * // Search for APM/PUDO/HUB shipments
	 * $apm_orders = $this->get_search_by_shipment_send_type('apm');
	 *
	 * Cache details:
	 * - Key format: 'shipment_search_' . md5(send_type)
	 * - Group: 'shipment_searches'
	 * - Expiration: 3600 seconds (1 hour)
	 *
	 * Database tables used:
	 * - HPOS: {$wpdb->prefix}wc_orders, {$wpdb->prefix}wc_orders_meta
	 * - Traditional: {$wpdb->posts}, {$wpdb->postmeta}
	 *
	 * Meta key searched: 'inpost_international_package'
	 */
	private function get_search_by_shipment_send_type( $send_type ) {
		global $wpdb;
		$send_type = sanitize_text_field( $send_type );

		// Generate a unique cache key.
		$cache_key = 'shipment_search_' . md5( $send_type );

		// Try to get cached results.
		$result = wp_cache_get( $cache_key, 'shipment_searches' );

		if ( false === $result ) {
			$hpos_enabled = get_option( 'woocommerce_custom_orders_table_enabled' ) === 'yes';

			if ( $hpos_enabled ) {
				// HPOS Query.
				$sql =
					"SELECT DISTINCT o.id
                    FROM {$wpdb->prefix}wc_orders o
                    INNER JOIN {$wpdb->prefix}wc_orders_meta om ON o.id = om.order_id
                    WHERE o.type = 'shop_order'
                    AND om.meta_key = 'inpost_international_package'";

			} else {
				// Traditional Post Meta Query.
				$sql =
					"SELECT DISTINCT p.ID
                    FROM {$wpdb->posts} p
                    INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
                    WHERE p.post_type = 'shop_order'
                    AND pm.meta_key = 'inpost_international_package'";

			}

			if ( 'courier' === $send_type ) {
				$meta_table = $hpos_enabled ? 'om' : 'pm';
				$sql       .= $wpdb->prepare( " AND %s.meta_value LIKE %s", $meta_table, '%\"address\":%' );
			} else {
				$meta_table = $hpos_enabled ? 'om' : 'pm';
				$sql       .= $wpdb->prepare( " AND %s.meta_value NOT LIKE %s", $meta_table, '%\"address\":%' );
			}

			$result = $wpdb->get_col( $sql ); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared

			wp_cache_set( $cache_key, $result, 'shipment_searches', 3600 );
		}

		return $result;
	}
}
