<?php
/**
 * Pre-Order products list table.
 *
 * @package  YITH\PreOrder\Admin
 */

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

if ( class_exists( 'WC_Admin_List_Table_Orders', false ) ) {
	return;
}

if ( ! class_exists( 'WC_Admin_List_Table', false ) ) {
	include_once dirname( WC_PLUGIN_FILE ) . '/includes/admin/list-tables/abstract-class-wc-admin-list-table.php';
}

/**
 * WC_Admin_List_Table_Orders Class.
 */
class YITH_Pre_Order_List_Table_Orders extends WC_Admin_List_Table {

	/**
	 * Post type.
	 *
	 * @var string
	 */
	protected $list_table_type = 'shop_order';

	/**
	 * Constructor.
	 */
	public function __construct() {
		parent::__construct();
		add_action( 'admin_notices', array( $this, 'bulk_admin_notices' ) );
		add_filter( 'get_search_query', array( $this, 'search_label' ) );
		add_filter( 'query_vars', array( $this, 'add_custom_query_var' ) );
		add_action( 'parse_query', array( $this, 'search_custom_fields' ) );
		add_filter( 'handle_bulk_actions-yith-plugins_page_yith_wcpo_panel', array( $this, 'handle_bulk_actions' ), 10, 3 );
	}

	/**
	 * Show blank slate.
	 *
	 * @param string $which String which tablenav is being shown.
	 */
	public function maybe_render_blank_state( $which ) {
		global $post_type, $wp_list_table;

		if ( $post_type === $this->list_table_type && 'bottom' === $which ) {
			if ( $wp_list_table->has_items() || isset( $_GET['s'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
				return;
			}
			$this->render_blank_state();
			echo '<style type="text/css">#posts-filter .wp-list-table, #posts-filter .tablenav.top, .tablenav.bottom .actions, .wrap .subsubsub  { display: none; } #posts-filter .tablenav.bottom { height: auto; } </style>';
		}
	}

	/**
	 * Render blank state.
	 */
	protected function render_blank_state() {
		echo '<div class="woocommerce-BlankState">';

		echo '<img class="woocommerce-BlankState" src="' . esc_url( YITH_WCPO_ASSETS_URL . 'images/pre-order-sold.svg' ) . '">';

		echo '<div class="ywpo-BlankState-message woocommerce-BlankState-message">';

		echo '<span>' . esc_html__( 'No pre-orders have been placed yet.', 'yith-pre-order-for-woocommerce' ) . '</<span><br>';

		echo '<span>' . esc_html__( "But don't worry, soon you'll see something cool here :)", 'yith-pre-order-for-woocommerce' ) . '</span>';

		echo '</div>';

		echo '</div>';
	}

	/**
	 * Define primary column.
	 *
	 * @return string
	 */
	protected function get_primary_column() {
		return 'order_number';
	}

	/**
	 * Get row actions to show in the list table.
	 *
	 * @param array   $actions Array of actions.
	 * @param WP_Post $post Current post object.
	 * @return array
	 */
	protected function get_row_actions( $actions, $post ) {
		return array();
	}

	/**
	 * Define hidden columns.
	 *
	 * @return array
	 */
	protected function define_hidden_columns() {
		return array();
	}

	/**
	 * Define which columns are sortable.
	 *
	 * @param array $columns Existing columns.
	 * @return array
	 */
	public function define_sortable_columns( $columns ) {
		return array();
	}

	/**
	 * Define bulk actions.
	 *
	 * @param array $actions Existing actions.
	 * @return array
	 */
	public function define_bulk_actions( $actions ) {
		if ( isset( $actions['edit'] ) ) {
			unset( $actions['edit'] );
		}

		$actions['ywpo_complete_pre_order']     = __( 'Force completion on all the pre-order items for the selected orders', 'yith-pre-order-for-woocommerce' );
		$actions['ywpo_cancel_pre_order']       = __( 'Cancel all pre-order items for the selected orders', 'yith-pre-order-for-woocommerce' );
		$actions['ywpo_mark_pre_order_as_paid'] = __( 'Force marking the pre-orders selected as paid', 'yith-pre-order-for-woocommerce' );
		$actions['mark_processing']             = __( 'Change order status to processing', 'yith-pre-order-for-woocommerce' );
		$actions['mark_on-hold']                = __( 'Change order status to on hold', 'yith-pre-order-for-woocommerce' );
		$actions['mark_completed']              = __( 'Change order status to completed', 'yith-pre-order-for-woocommerce' );

		if ( isset( $actions['trash'] ) ) {
			// Move the 'trash' bulk action to the end.
			unset( $actions['trash'] );
			$actions['trash'] = __( 'Move order to Trash', 'yith-pre-order-for-woocommerce' );
		}

		return $actions;
	}

	/**
	 * Pre-fetch any data for the row each column has access to it. the_order global is there for bw compat.
	 *
	 * @param int $post_id Post ID being shown.
	 */
	protected function prepare_row_data( $post_id ) {
		global $the_order;

		if ( empty( $this->object ) || $this->object->get_id() !== $post_id ) {
			$this->object = wc_get_order( $post_id );
			$the_order    = $this->object;
		}
	}

	/**
	 * Render column: order_number.
	 */
	protected function render_order_number_column() {
		if ( $this->object->get_status() === 'trash' ) {
			echo '<strong>#' . esc_attr( $this->object->get_order_number() ) . '</strong>';
		} else {
			echo '<a href="' . esc_url( admin_url( 'post.php?post=' . absint( $this->object->get_id() ) ) . '&action=edit' ) . '" class="order-view"><strong>#' . esc_attr( $this->object->get_order_number() ) . '</strong></a>';
		}
	}

	/**
	 * Render column: order_date.
	 */
	protected function render_order_date_column() {
		$order_timestamp = $this->object->get_date_created() ? $this->object->get_date_created()->getTimestamp() : '';

		if ( ! $order_timestamp ) {
			echo '&ndash;';
			return;
		}

		// Check if the order was created within the last 24 hours, and not in the future.
		if ( $order_timestamp > strtotime( '-1 day', time() ) && $order_timestamp <= time() ) {
			$show_date = sprintf(
			/* translators: %s: human-readable time difference */
				_x( '%s ago', '%s = human-readable time difference', 'yith-pre-order-for-woocommerce' ),
				human_time_diff( $this->object->get_date_created()->getTimestamp(), time() )
			);
		} else {
			$show_date = $this->object->get_date_created()->date_i18n( apply_filters( 'woocommerce_admin_order_date_format', __( 'M j, Y', 'yith-pre-order-for-woocommerce' ) ) );
		}
		printf(
			'<time datetime="%1$s" title="%2$s">%3$s</time>',
			esc_attr( $this->object->get_date_created()->date( 'c' ) ),
			esc_html( $this->object->get_date_created()->date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ) ) ),
			esc_html( $show_date )
		);
	}

	/**
	 * Render column: order_status.
	 */
	protected function render_order_status_column() {
		$tooltip                 = '';
		$comment_count           = get_comment_count( $this->object->get_id() );
		$approved_comments_count = absint( $comment_count['approved'] );

		if ( $approved_comments_count ) {
			$latest_notes = wc_get_order_notes(
				array(
					'order_id' => $this->object->get_id(),
					'limit'    => 1,
					'orderby'  => 'date_created_gmt',
				)
			);

			$latest_note = current( $latest_notes );

			if ( isset( $latest_note->content ) && 1 === $approved_comments_count ) {
				$tooltip = wc_sanitize_tooltip( $latest_note->content );
			} elseif ( isset( $latest_note->content ) ) {
				/* translators: %d: notes count */
				$tooltip = wc_sanitize_tooltip( $latest_note->content . '<br/><small style="display:block">' . sprintf( _n( 'Plus %d other note', 'Plus %d other notes', ( $approved_comments_count - 1 ), 'yith-pre-order-for-woocommerce' ), $approved_comments_count - 1 ) . '</small>' );
			} else {
				/* translators: %d: notes count */
				$tooltip = wc_sanitize_tooltip( sprintf( _n( '%d note', '%d notes', $approved_comments_count, 'yith-pre-order-for-woocommerce' ), $approved_comments_count ) );
			}
		}

		if ( $tooltip ) {
			printf( '<mark class="order-status %s tips" data-tip="%s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), wp_kses_post( $tooltip ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
		} else {
			printf( '<mark class="order-status %s"><span>%s</span></mark>', esc_attr( sanitize_html_class( 'status-' . $this->object->get_status() ) ), esc_html( wc_get_order_status_name( $this->object->get_status() ) ) );
		}
	}

	/**
	 * Render column: customer.
	 */
	protected function render_customer_column() {
		$buyer = '';
		$email = '';

		if ( $this->object->get_billing_first_name() || $this->object->get_billing_last_name() ) {
			/* translators: 1: first name 2: last name */
			$buyer = trim( sprintf( _x( '%1$s %2$s', 'full name', 'yith-pre-order-for-woocommerce' ), $this->object->get_billing_first_name(), $this->object->get_billing_last_name() ) );
		} elseif ( $this->object->get_billing_company() ) {
			$buyer = trim( $this->object->get_billing_company() );
		} elseif ( $this->object->get_customer_id() ) {
			$user  = get_user_by( 'id', $this->object->get_customer_id() );
			$buyer = ucwords( $user->display_name );
		}

		if ( ! $buyer ) {
			$buyer = __( 'Guest', 'yith-pre-order-for-woocommerce' );
		}

		/**
		 * Filter buyer name in list table orders.
		 *
		 * @since 3.7.0
		 * @param string   $buyer Buyer name.
		 * @param WC_Order $order Order data.
		 */
		$buyer = apply_filters( 'woocommerce_admin_order_buyer_name', $buyer, $this->object );

		if ( $this->object->get_billing_email() ) {
			$email = $this->object->get_billing_email();
		} elseif ( $this->object->get_customer_id() ) {
			$user  = get_user_by( 'id', $this->object->get_customer_id() );
			$email = $user->user_email;
		}

		$email = sanitize_email( $email );

		echo '<div>' . esc_html( $buyer ) . '</div>';
		echo '<div><a href="mailto:' . esc_attr( $email ) . '">' . esc_attr( $email ) . '</a></div>';
	}

	/**
	 * Render column: ywpo_products.
	 */
	protected function render_ywpo_products_column() {
		$order = wc_get_order( $this->object );

		$counter = 0;
		foreach ( $order->get_items() as $item ) {
			$item_id = $item->get_id();
			if ( 'yes' === $order->get_item( $item_id )->get_meta( '_ywpo_item_preorder' ) ) {
				$status  = $order->get_item( $item_id )->get_meta( '_ywpo_item_status' );
				$message = '';
				$icon    = '';
				switch ( $status ) {
					case 'waiting':
						$message = __( 'This pre-order item is awaiting release', 'yith-pre-order-for-woocommerce' );
						$icon    = 'time-check';
						break;
					case 'completed':
						$message = __( 'This pre-order item is completed', 'yith-pre-order-for-woocommerce' );
						$icon    = 'check-alt';
						break;
					case 'cancelled':
						$message = __( 'This pre-order item is cancelled', 'yith-pre-order-for-woocommerce' );
						$icon    = 'close-alt';
						break;
				}

				if ( $counter > 1 ) {
					$counter ++;
					continue;
				}

				do_action( 'ywpo_products_column_before_product_line', $order, $item, $status, $counter, $message, $icon );

				echo '<div class="ywpo_products-product_line">';
				echo '<span class="ywpo_products-product_name">' . esc_html( $item->get_name() ) . '</span>';
				echo '</div>';

				do_action( 'ywpo_products_column_after_product_line', $order, $item, $status, $counter, $message, $icon );

				$counter ++;
			}
		}
		if ( $counter > 2 ) {
			$remaining = $counter - 2;
			// translators: %d: amount of pre-order items.
			echo '<div><i>' . sprintf( esc_html__( 'and %d more', 'yith-pre-order-for-woocommerce' ), esc_html( $remaining ) ) . '</i></div>';
		}
		$is_upon_release = ywpo_is_upon_release_order( $order ) ? 'yes' : 'no';

		do_action( 'ywpo_products_column_before_manage_products_button', $order, $counter, $is_upon_release );

		echo '<div class="ywpo_products-manage_products_button"><a class="ywpo_manage_products_button ywpo_manage_products_button-' . esc_attr( $order->get_id() )
			. '" data-order_id="' . esc_attr( $order->get_id() ) . '" data-upon_release="' . esc_attr( $is_upon_release ) . '"href="#">'
			. esc_html( _n( 'Manage product > ', 'Manage products >', $counter, 'yith-pre-order-for-woocommerce' ) ) . '</a></div>';

		do_action( 'ywpo_products_column_after_manage_products_button', $order, $counter, $is_upon_release );

	}

	/**
	 * Render column: ywpo_status.
	 */
	protected function render_ywpo_status_column() {
		$status  = $this->object->get_meta( '_ywpo_status' );
		$message = '';
		$icon    = '';
		switch ( $status ) {
			case 'waiting':
				$message = __( 'The pre-order is awaiting release', 'yith-pre-order-for-woocommerce' );
				$icon    = 'time-check';
				break;
			case 'completed':
				$message = __( 'The pre-order is completed', 'yith-pre-order-for-woocommerce' );
				$icon    = 'check-alt';
				break;
			case 'cancelled':
				$message = __( 'The pre-order is cancelled', 'yith-pre-order-for-woocommerce' );
				$icon    = 'close-alt';
				break;
		}

		if ( $message ) :
			?>
			<span class="yith-plugin-fw__action-button ywpo_status_icon">
				<a class="yith-plugin-fw__action-button__link yith-plugin-fw__tips" data-tip="<?php echo esc_attr( $message ); ?>">
					<i class="yith-plugin-fw__action-button__icon yith-icon yith-icon-<?php echo esc_attr( $icon ); ?> ywpo-<?php echo esc_attr( $status ); ?>"></i>
				</a>
			</span>
			<?php
		endif;
	}

	/**
	 * Render column: order_total.
	 */
	protected function render_order_total_column() {
		if ( $this->object->get_payment_method_title() ) {
			/* translators: %s: method */
			echo '<span class="tips" data-tip="' . esc_attr( sprintf( __( 'via %s', 'yith-pre-order-for-woocommerce' ), $this->object->get_payment_method_title() ) ) . '">' . wp_kses_post( $this->object->get_formatted_order_total() ) . '</span>';
		} else {
			echo wp_kses_post( $this->object->get_formatted_order_total() );
		}
	}

	/**
	 * Render column: ywpo_charge_type.
	 */
	protected function render_ywpo_charge_type_column() {
		$text = __( 'Upfront', 'yith-pre-order-for-woocommerce' );
		if ( ywpo_is_upon_release_order( $this->object ) ) {
			$text = __( 'Upon release', 'yith-pre-order-for-woocommerce' );
		}
		echo '<span class="tips" data-tip="'
			. esc_attr(
				sprintf(
					/* translators: %s: payment method */
					__(
						'via %s',
						'yith-pre-order-for-woocommerce'
					),
					$this->object->get_payment_method_title()
				)
			) . '">' . esc_html( $text ) . '</span>';
	}



	/**
	 * Render column: ywpo_payment.
	 */
	protected function render_ywpo_payment_column() {
		$order = $this->object;
		if ( metadata_exists( 'post', $order->get_id(), '_ywpo_pending_payment' ) ) {
			if ( 'yes' === $order->get_meta( '_ywpo_pending_payment' ) ) {
				echo '<span class="ywpo-status-span unpaid">' . esc_html__( 'Unpaid', 'yith-pre-order-for-woocommerce' ) . '</span>';
			} else {
				echo '<span class="ywpo-status-span paid">' . esc_html__( 'Paid', 'yith-pre-order-for-woocommerce' ) . '</span>';
			}
		} else {
			if ( ywpo_order_is_paid( $order ) ) {
				echo '<span class="ywpo-status-span paid">' . esc_html__( 'Paid', 'yith-pre-order-for-woocommerce' ) . '</span>';
			} else {
				echo '<span class="ywpo-status-span unpaid">' . esc_html__( 'Unpaid', 'yith-pre-order-for-woocommerce' ) . '</span>';
			}
		}
	}

	/**
	 * Render column: ywpo_actions.
	 */
	protected function render_ywpo_actions_column() {
		$actions = array();

		if ( 'waiting' === $this->object->get_meta( '_ywpo_status' ) ) {
			$actions['ywpo_complete_pre_order'] = array(
				'action'       => 'ywpo-complete',
				'title'        => __( 'Forcing completion of all pre-order items', 'yith-pre-order-for-woocommerce' ),
				'url'          => wp_nonce_url( admin_url( 'admin-ajax.php?action=ywpo_complete_pre_order&order_id=' . $this->object->get_id() ), 'ywpo-complete-pre-order' ),
				'icon'         => 'check-alt',
				'confirm_data' => array(
					'title'               => __( 'Confirm action', 'yith-pre-order-for-woocommerce' ),
					'message'             => __( 'Are you sure you want to complete this pre-order? This action will force completion on all of the pre-order items in the order, even if the release date has not been reached yet. This action cannot be undone.', 'yith-pre-order-for-woocommerce' ),
					'confirm-button'      => __( 'Complete', 'yith-pre-order-for-woocommerce' ),
					'confirm-button-type' => 'confirm',
					'cancel-button'       => __( 'Dismiss', 'yith-pre-order-for-woocommerce' ),
				),
			);
			$actions['ywpo_cancel_pre_order']   = array(
				'action'       => 'ywpo-cancel',
				'title'        => __( 'Cancel all pre-order items', 'yith-pre-order-for-woocommerce' ),
				'url'          => wp_nonce_url( admin_url( 'admin-ajax.php?action=ywpo_cancel_pre_order&order_id=' . $this->object->get_id() ), 'ywpo-cancel-pre-order' ),
				'icon'         => 'close-alt',
				'confirm_data' => array(
					'title'               => __( 'Confirm action', 'yith-pre-order-for-woocommerce' ),
					'message'             => __( 'Are you sure you want to cancel this pre-order? This action will cancel all of the pre-order items in the order and it cannot be undone.', 'yith-pre-order-for-woocommerce' ),
					'confirm-button'      => __( 'Cancel', 'yith-pre-order-for-woocommerce' ),
					'confirm-button-type' => 'delete',
					'cancel-button'       => __( 'Dismiss', 'yith-pre-order-for-woocommerce' ),
				),
			);
		}

		if ( 'yes' === $this->object->get_meta( '_ywpo_pending_payment' ) && 'cancelled' !== $this->object->get_meta( '_ywpo_status' ) ) {
			$actions['ywpo_mark_pre_order_as_paid'] = array(
				'action'       => 'ywpo-mark-as-paid',
				'title'        => __( 'Force marking this pre-order as paid', 'yith-pre-order-for-woocommerce' ),
				'url'          => wp_nonce_url( admin_url( 'admin-ajax.php?action=ywpo_mark_pre_order_as_paid&order_id=' . $this->object->get_id() ), 'ywpo-mark-pre-order-as-paid' ),
				'icon'         => 'cash',
				'confirm_data' => array(
					'title'               => __( 'Confirm action', 'yith-pre-order-for-woocommerce' ),
					'message'             => __( 'Do you want to mark this pre-order as paid? If the pre-order has been placed using an offline payment gateway and has already been paid for by the customer, you might want to use this action in order to avoid sending pending payment reminders to the customer. This action cannot be undone.', 'yith-pre-order-for-woocommerce' ),
					'confirm-button'      => __( 'Mark as paid', 'yith-pre-order-for-woocommerce' ),
					'confirm-button-type' => 'confirm',
					'cancel-button'       => __( 'Dismiss', 'yith-pre-order-for-woocommerce' ),
				),
			);
		}

		$actions = apply_filters( 'ywpo_list_table_orders_status_actions', $actions, $this->object );
		foreach ( $actions as $action ) {
			$action['type'] = 'action-button';
			yith_plugin_fw_get_component( $action );
		}
	}

	/**
	 * Handle bulk actions.
	 *
	 * @param  string $redirect_to URL to redirect to.
	 * @param  string $action      Action name.
	 * @param  array  $ids         List of ids.
	 *
	 * @return string|WP_Error
	 */
	public function handle_bulk_actions( $redirect_to, $action, $ids ) {
		$ids           = apply_filters( 'woocommerce_bulk_action_ids', array_reverse( array_map( 'absint', $ids ) ), $action, 'order' );
		$changed       = 0;
		$report_action = '';

		try {
			if ( 'mark_' === substr( $action, 0, 5 ) ) {
				$order_statuses = wc_get_order_statuses();
				$new_status     = substr( $action, 5 ); // Get the status name from action.
				$report_action  = 'marked_' . $new_status;

				// Sanity check: bail out if this is actually not a status, or is not a registered status.
				if ( isset( $order_statuses[ 'wc-' . $new_status ] ) ) {
					// Initialize payment gateways in case order has hooked status transition actions.
					WC()->payment_gateways();

					foreach ( $ids as $id ) {
						$order = wc_get_order( $id );
						$order->update_status( $new_status, __( 'Order status changed by bulk edit:', 'yith-pre-order-for-woocommerce' ), true );
						do_action( 'woocommerce_order_edit_status', $id, $new_status );
						$changed++;
					}
				}
			} elseif ( 'ywpo_complete_pre_order' === $action ) {
				$report_action = 'complete_pre_order';
				YITH_Pre_Order_Orders_Manager()::complete_pre_orders( $ids, apply_filters( 'ywpo_bulk_action_complete_pre_orders_force', true ) );
				$changed++;
			} elseif ( 'ywpo_cancel_pre_order' === $action ) {
				$report_action = 'cancel_pre_order';
				YITH_Pre_Order_Orders_Manager::cancel_pre_orders( $ids );
				$changed++;
			} elseif ( 'ywpo_mark_pre_order_as_paid' === $action ) {
				$report_action = 'mark_pre_order_as_paid';
				foreach ( $ids as $order_id ) {
					ywpo_mark_as_paid( $order_id );
				}
				$changed++;
			}
		} catch ( Exception $e ) {
			return new WP_Error( $e->getCode(), $e->getMessage() );
		}

		if ( $changed && $report_action ) {
			$redirect_to = add_query_arg(
				array(
					'post_type'   => $this->list_table_type,
					'bulk_action' => $report_action,
					'changed'     => $changed,
					'ids'         => join( ',', $ids ),
				),
				$redirect_to
			);
		}

		return esc_url_raw( $redirect_to );
	}

	/**
	 * Show confirmation message that order status changed for number of orders.
	 */
	public function bulk_admin_notices() {
		global $post_type, $pagenow;

		// Bail out if not on shop order list page.
		if ( 'admin.php' !== $pagenow || 'shop_order' !== $post_type || ! isset( $_REQUEST['bulk_action'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended
			return;
		}

		$order_statuses = wc_get_order_statuses();
		$number         = isset( $_REQUEST['changed'] ) ? absint( $_REQUEST['changed'] ) : 0;
		$bulk_action    = wc_clean( wp_unslash( $_REQUEST['bulk_action'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		if ( 'marked_' === substr( $bulk_action, 0, 7 ) ) {
			// Check if any status changes happened.
			foreach ( $order_statuses as $slug => $name ) {
				if ( 'marked_' . str_replace( 'wc-', '', $slug ) === $bulk_action ) {
					/* translators: %d: orders count */
					$message = sprintf( _n( '%d order status changed.', '%d order statuses changed.', $number, 'yith-pre-order-for-woocommerce' ), number_format_i18n( $number ) );
					echo '<div class="updated"><p>' . esc_html( $message ) . '</p></div>';
					break;
				}
			}
		}
	}

	/**
	 * See if we should render search filters or not.
	 */
	public function restrict_manage_posts() {
		if ( 'shop_order' === $this->list_table_type && isset( $_GET['page'] ) && 'yith_wcpo_panel' === $_GET['page'] ) {
			$this->render_filters();
		}
	}

	/**
	 * Render any custom filters and search inputs for the list table.
	 */
	protected function render_filters() {
		$user_string = '';
		$user_id     = '';

		if ( ! empty( $_GET['_customer_user'] ) ) { // phpcs:disable WordPress.Security.NonceVerification.Recommended
			$user_id = absint( $_GET['_customer_user'] );
			$user    = get_user_by( 'id', $user_id );

			$user_string = sprintf(
			/* translators: 1: user display name 2: user ID 3: user email */
				esc_html__( '%1$s (#%2$s &ndash; %3$s)', 'yith-pre-order-for-woocommerce' ),
				$user->display_name,
				absint( $user->ID ),
				$user->user_email
			);
		}
		?>
		<select class="wc-customer-search" name="_customer_user" data-placeholder="<?php esc_attr_e( 'Filter by registered customer', 'yith-pre-order-for-woocommerce' ); ?>" data-allow_clear="true">
			<option value="<?php echo esc_attr( $user_id ); ?>" selected="selected"><?php echo wp_kses_post( htmlspecialchars( $user_string ) ); ?></option>
		</select>
		<style>
			.yith-plugin-fw-panel-custom-sub-tab-container .tablenav .select2-container {
				width: 240px!important;
				font-size: 14px;
				margin: 0 6px 4px 1px;
			}
		</style>
		<?php
	}

	/**
	 * Handle any filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	public function request_query( $query_vars ) {
		if ( ! empty( $query_vars['page'] ) && 'yith_wcpo_panel' === $query_vars['page'] && ! empty( $query_vars['post_type'] ) && 'shop_order' === $query_vars['post_type'] ) {
			return $this->query_filters( $query_vars );
		}
		return $query_vars;
	}

	/**
	 * Handle any custom filters.
	 *
	 * @param array $query_vars Query vars.
	 * @return array
	 */
	protected function query_filters( $query_vars ) {
		global $wp_post_statuses;

		// Filter the orders by the posted customer.
		if ( ! empty( $_GET['_customer_user'] ) ) {
			$query_vars['meta_query'] = array( // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_query
				array(
					'key'     => '_customer_user',
					'value'   => (int) $_GET['_customer_user'],
					'compare' => '=',
				),
			);
		}

		// Sorting.
		if ( isset( $_GET['orderby'] ) ) {
			$sorting_order = isset( $_GET['order'] ) ? sanitize_text_field( wp_unslash( $_GET['order'] ) ) : '';
			if ( 'order_total' === $_GET['orderby'] && $sorting_order ) {
				$query_vars = array_merge(
					$query_vars,
					array(
						'meta_key' => '_order_total', // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_meta_key
						'orderby'  => 'meta_value_num',
						'order'    => $sorting_order,
					)
				);
			}
		}

		// Status.
		if ( empty( $query_vars['post_status'] ) ) {
			$post_statuses = wc_get_order_statuses();

			foreach ( $post_statuses as $status => $value ) {
				if ( isset( $wp_post_statuses[ $status ] ) && false === $wp_post_statuses[ $status ]->show_in_admin_all_list ) {
					unset( $post_statuses[ $status ] );
				}
			}

			$query_vars['post_status'] = array_keys( $post_statuses );
		}
		return $query_vars;
	}

	/**
	 * Change the label when searching orders.
	 *
	 * @param mixed $query Current search query.
	 * @return string
	 */
	public function search_label( $query ) {
		global $pagenow, $typenow;

		if ( 'admin.php' !== $pagenow || 'shop_order' !== $typenow || ! get_query_var( 'shop_order_search' ) || ! isset( $_GET['s'] ) ) { // phpcs:ignore  WordPress.Security.NonceVerification.Recommended
			return $query;
		}

		return wc_clean( wp_unslash( $_GET['s'] ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
	}

	/**
	 * Query vars for custom searches.
	 *
	 * @param mixed $public_query_vars Array of query vars.
	 * @return array
	 */
	public function add_custom_query_var( $public_query_vars ) {
		$public_query_vars[] = 'shop_order_search';
		return $public_query_vars;
	}

	/**
	 * Search custom fields as well as content.
	 *
	 * @param WP_Query $wp Query object.
	 */
	public function search_custom_fields( $wp ) {
		global $pagenow;

		if ( 'admin.php' !== $pagenow || empty( $wp->query_vars['s'] ) || 'shop_order' !== $wp->query_vars['post_type'] || ! isset( $_GET['s'] ) ) { // phpcs:ignore  WordPress.Security.NonceVerification.Recommended
			return;
		}

		$post_ids = wc_order_search( wc_clean( wp_unslash( $_GET['s'] ) ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized

		if ( ! empty( $post_ids ) ) {
			// Remove "s" - we don't want to search order name.
			unset( $wp->query_vars['s'] );

			// so we know we're doing this.
			$wp->query_vars['shop_order_search'] = true;

			// Search by found posts.
			$wp->query_vars['post__in'] = array_merge( $post_ids, array( 0 ) );
		}
	}
}
