<?php
/**
 * Class Noesia Cs Admin Action Router.
 *
 * @package Noesia_Commerce_Suite
 */

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

/**
 * Central admin action router.
 *
 * Keeps state-changing admin/AJAX actions out of the visual admin shell while
 * reusing services from the lightweight container.
 */
class Noesia_CS_Admin_Action_Router {
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $container;
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $admin;
	/**
	 * Runtime dependency or state value.
	 *
	 * @var mixed
	 */
	private $module_registry;

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $container Container.
	 * @param mixed $admin Admin.
	 * @param mixed $module_registry Module registry.
	 */
	public function __construct( Noesia_CS_Container $container, Noesia_CS_Admin $admin, $module_registry = null ) {
		$this->container       = $container;
		$this->admin           = $admin;
		$this->module_registry = $module_registry;
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function hooks() {
		add_action( 'admin_post_noesia_cs_save_settings', array( $this, 'handle_save_settings' ) );
		add_action( 'wp_ajax_noesia_cs_save_settings_ajax', array( $this, 'handle_save_settings_ajax' ) );
		add_action( 'admin_post_noesia_cs_doctor_scan', array( $this, 'handle_doctor_scan' ) );
		add_action( 'admin_post_noesia_cs_doctor_export_issue', array( $this, 'handle_doctor_export_issue' ) );
		add_action( 'admin_post_noesia_cs_refresh_impact_map', array( $this, 'handle_refresh_impact_map' ) );
		add_action( 'wp_ajax_noesia_cs_refresh_impact_map_ajax', array( $this, 'handle_refresh_impact_map_ajax' ) );
		add_action( 'wp_ajax_noesia_cs_dashboard_top_products_ajax', array( $this, 'handle_dashboard_top_products_ajax' ) );
		add_action( 'wp_ajax_noesia_cs_admin_search', array( $this, 'handle_admin_search_ajax' ) );
		add_action( 'wp_ajax_noesia_cs_last_hour_orders', array( $this, 'handle_last_hour_orders_ajax' ) );
		add_action( 'admin_post_noesia_cs_refresh_analytics', array( $this, 'handle_refresh_analytics' ) );
		add_action( 'admin_post_noesia_cs_generate_token', array( $this, 'handle_generate_token' ) );
		add_action( 'admin_post_noesia_cs_send_test_email', array( $this, 'handle_send_test_email' ) );
		add_action( 'admin_post_noesia_cs_build_reorder_queue', array( $this, 'handle_build_reorder_queue' ) );
		add_action( 'admin_post_noesia_cs_send_reorder_test_copy', array( $this, 'handle_send_reorder_test_copy' ) );
		add_action( 'admin_post_noesia_cs_cleanup_data', array( $this, 'handle_cleanup_data' ) );
		add_action( 'admin_post_noesia_cs_regenerate_token', array( $this, 'handle_regenerate_token' ) );
		add_action( 'admin_post_noesia_cs_refresh_rewrites', array( $this, 'handle_refresh_rewrites' ) );
		add_action( 'admin_post_noesia_cs_print_qr', array( $this, 'handle_print_qr' ) );
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $key Key.
	 */
	private function service( $key ) {
		return $this->container ? $this->container->get( $key ) : null;
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $message Message.
	 */
	private function ensure_capability( $message ) {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_die( esc_html( $message ) );
		}
	}

	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $tab Tab.
	 * @param mixed $notice Notice.
	 */
	private function redirect_with_notice( $tab, $notice ) {
		$tab = sanitize_key( $tab );
		if ( in_array( $tab, array( 'product-passport-qr', 'order-care-page' ), true ) ) {
			$tab = 'order-care-hub';
		}
		if ( $this->module_registry && method_exists( $this->module_registry, 'has' ) && ! $this->module_registry->has( $tab ) ) {
			$tab = $this->module_registry->has( 'dashboard' ) ? 'dashboard' : 'settings';
		}
		wp_safe_redirect( add_query_arg( array(
			'page'              => 'noesia-commerce-suite',
			'tab'               => $tab,
			'noesia_cs_notice'  => sanitize_key( $notice ),
		), admin_url( 'admin.php' ) ) );
		exit;
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function impact_range_from_request() {
		$mode = isset( $_POST['noesia_cs_impact_date_mode'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_impact_date_mode'] ) ) : 'all'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after refresh-impact nonce verification.
		$from = isset( $_POST['noesia_cs_impact_date_from'] ) ? sanitize_text_field( wp_unslash( $_POST['noesia_cs_impact_date_from'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after refresh-impact nonce verification.
		$to   = isset( $_POST['noesia_cs_impact_date_to'] ) ? sanitize_text_field( wp_unslash( $_POST['noesia_cs_impact_date_to'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after refresh-impact nonce verification.

		if ( 'custom' !== $mode ) {
			return array(
				'mode'         => 'all',
				'from'         => '',
				'to'           => '',
				'date_after'   => '',
				'date_before'  => '',
			);
		}

		$from_valid  = $from && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $from );
		$to_valid    = $to && preg_match( '/^\d{4}-\d{2}-\d{2}$/', $to );

		return array(
			'mode'         => 'custom',
			'from'         => $from_valid ? $from : '',
			'to'           => $to_valid ? $to : '',
			'date_after'   => $from_valid ? $from . ' 00:00:00' : '',
			'date_before'  => $to_valid ? $to . ' 23:59:59' : '',
		);
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function update_impact_grouping_from_request() {
		$group_by = isset( $_POST['noesia_cs_impact_group_by'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_impact_group_by'] ) ) : 'country'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after refresh-impact nonce verification.
		if ( ! in_array( $group_by, array( 'city', 'region', 'country' ), true ) ) {
			$group_by = 'country';
		}

		$settings                         = Noesia_CS_Settings::get_all();
		$settings['impact_map_group_by']  = $group_by;
		update_option( 'noesia_cs_settings', Noesia_CS_Settings::sanitize( $settings ), false );
		return $group_by;
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function save_settings_from_request() {
		$settings = array();
		// phpcs:ignore WordPress.Security.NonceVerification.Missing -- Nonce is verified by the caller before this helper reads the settings payload.
		if ( isset( $_POST['noesia_cs_settings'] ) && is_array( $_POST['noesia_cs_settings'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized -- Nonce is verified by the caller; the settings array is allow-listed and sanitized by Noesia_CS_Settings::save().
			$settings = wp_unslash( $_POST['noesia_cs_settings'] );
		}

		$settings = wp_parse_args( $settings, Noesia_CS_Settings::get_all() );
		Noesia_CS_Settings::save( $settings );

		$analytics_service = $this->service( 'analytics_service' );
		if ( $analytics_service && method_exists( $analytics_service, 'flush_cache' ) ) {
			$analytics_service->flush_cache();
		}
	}

	/**
	 * Handles the related plugin operation.
	 */
	private function save_settings_return_url_from_request() {
		$tab = isset( $_POST['noesia_cs_tab'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_tab'] ) ) : 'settings'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after settings nonce verification.
		if ( in_array( $tab, array( 'product-passport-qr', 'order-care-page' ), true ) ) {
			$tab = 'order-care-hub';
		}

		if ( 'order-care-hub' === $tab ) {
			$section = isset( $_POST['noesia_cs_hub_section'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_hub_section'] ) ) : 'overview'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Called only after settings nonce verification.
			if ( ! in_array( $section, array( 'overview', 'core', 'smart', 'access', 'design', 'security' ), true ) ) {
				$section = 'overview';
			}

			return add_query_arg(
				array(
					'page'                   => 'noesia-commerce-suite',
					'tab'                    => 'order-care-hub',
					'noesia_cs_hub_section'  => $section,
					'noesia_cs_notice'       => 'saved',
				),
				admin_url( 'admin.php' )
			);
		}

		if ( $this->module_registry && method_exists( $this->module_registry, 'has' ) && ! $this->module_registry->has( $tab ) ) {
			$tab = $this->module_registry->has( 'dashboard' ) ? 'dashboard' : 'settings';
		}

		return add_query_arg(
			array(
				'page'              => 'noesia-commerce-suite',
				'tab'               => $tab,
				'noesia_cs_notice'  => 'saved',
			),
			admin_url( 'admin.php' )
		);
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_save_settings() {
		$this->ensure_capability( __( 'You do not have permission to manage Noesia Commerce Suite.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_save_settings' );

		$this->save_settings_from_request();
		wp_safe_redirect( $this->save_settings_return_url_from_request() );
		exit;
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_save_settings_ajax() {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to manage Noesia Commerce Suite.', 'noesia-commerce-suite' ) ), 403 );
		}

		check_ajax_referer( 'noesia_cs_save_settings' );
		$this->save_settings_from_request();

		wp_send_json_success(
			array(
				'message'     => __( 'Order Care Hub settings saved.', 'noesia-commerce-suite' ),
				'return_url'  => esc_url_raw( $this->save_settings_return_url_from_request() ),
			)
		);
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_doctor_scan() {
		$this->ensure_capability( __( 'You do not have permission to run this scan.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_doctor_scan' );
		$doctor_service = $this->service( 'doctor_service' );
		if ( $doctor_service && method_exists( $doctor_service, 'run_scan' ) ) {
			try {
				$doctor_service->run_scan();
			} catch ( Throwable $e ) {
				$this->store_doctor_scan_error_report( $e );
			}
		}
		$this->redirect_with_notice( 'ecommerce-doctor', 'scan-complete' );
	}


	/**
	 * Handles the related plugin operation.
	 *
	 * @param mixed $error Error.
	 */
	private function store_doctor_scan_error_report( $error ) {
		$message = $error instanceof Throwable ? $error->getMessage() : __( 'Unknown scan error.', 'noesia-commerce-suite' );
		$report  = array(
			'generated_at'      => time(),
			'scanned_products'  => 0,
			'severity_counts'   => array(
				'critical'          => 0,
				'high'              => 1,
				'medium'            => 0,
				'low'               => 0,
				'success'           => 0,
			),
			'checks'  => array(),
			'items'   => array(
				array(
					'severity'  => 'high',
					'title'     => __( 'Doctor scan stopped safely', 'noesia-commerce-suite' ),
					'message'   => sprintf(
						/* translators: %s: caught PHP error message. */
						__( 'The scan hit an internal error and was stopped without running cleanup actions. Error: %s', 'noesia-commerce-suite' ),
						sanitize_text_field( $message )
					),
					'count'     => 1,
					'examples'  => array(),
					'code'      => 'scan_error',
				),
			),
		);

		update_option( Noesia_CS_Doctor_Service::REPORT_OPTION, $report, false );
	}


	/**
	 * Handles the related plugin operation.
	 */
	public function handle_doctor_export_issue() {
		$this->ensure_capability( __( 'You do not have permission to export this report.', 'noesia-commerce-suite' ) );
		$code = isset( $_GET['noesia_cs_doctor_issue'] ) ? sanitize_key( wp_unslash( $_GET['noesia_cs_doctor_issue'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Needed to build the matching export nonce action before validation.
		check_admin_referer( 'noesia_cs_doctor_export_' . $code );

		$doctor_service = $this->service( 'doctor_service' );
		if ( $doctor_service && method_exists( $doctor_service, 'stream_issue_csv' ) ) {
			$doctor_service->stream_issue_csv( $code );
		}

		wp_die( esc_html__( 'Doctor export is not available.', 'noesia-commerce-suite' ) );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_refresh_impact_map() {
		$this->ensure_capability( __( 'You do not have permission to refresh the Impact Map.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_refresh_impact_map' );
		$group_by            = $this->update_impact_grouping_from_request();
		$impact_map_service  = $this->service( 'impact_map_service' );
		if ( $impact_map_service && method_exists( $impact_map_service, 'refresh_snapshot' ) ) {
			$impact_map_service->refresh_snapshot( $this->impact_range_from_request() );
		}
		$return_tab = isset( $_POST['noesia_cs_return_tab'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_return_tab'] ) ) : 'impact-map'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Refresh-impact nonce verified above.
		$this->redirect_with_notice( $return_tab, 'impact-refreshed' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_refresh_impact_map_ajax() {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to refresh the Impact Map.', 'noesia-commerce-suite' ) ), 403 );
		}
		check_ajax_referer( 'noesia_cs_refresh_impact_map' );

		$group_by            = $this->update_impact_grouping_from_request();
		$impact_map_service  = $this->service( 'impact_map_service' );
		$snapshot            = $impact_map_service && method_exists( $impact_map_service, 'refresh_snapshot' ) ? $impact_map_service->refresh_snapshot( $this->impact_range_from_request() ) : array();
		$context  = isset( $_POST['noesia_cs_impact_context'] ) ? sanitize_key( wp_unslash( $_POST['noesia_cs_impact_context'] ) ) : 'compact'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce verified above.

		ob_start();
		if ( 'admin-table' === $context ) {
			$this->admin->render_impact_admin_table( $snapshot, $group_by );
		} else {
			$this->admin->render_map_preview( $snapshot, $group_by );
		}
		$html = ob_get_clean();

		wp_send_json_success(
			array(
				'html'       => $html,
				'groupBy'    => $group_by,
				'generated'  => isset( $snapshot['generated_at'] ) ? absint( $snapshot['generated_at'] ) : 0,
			)
		);
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_dashboard_top_products_ajax() {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to view dashboard products.', 'noesia-commerce-suite' ) ), 403 );
		}
		check_ajax_referer( 'noesia_cs_dashboard_top_products', 'nonce' );

		$range = isset( $_POST['range'] ) ? sanitize_key( wp_unslash( $_POST['range'] ) ) : 'all'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce verified above.
		if ( ! in_array( $range, array( 'all', 'last_month', 'last_24h' ), true ) ) {
			$range = 'all';
		}
		$tab = isset( $_POST['tab'] ) ? sanitize_key( wp_unslash( $_POST['tab'] ) ) : 'dashboard'; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce verified above.
		if ( ! in_array( $tab, array( 'dashboard', 'intelligence-analytics' ), true ) ) {
			$tab = 'dashboard';
		}

		$analytics_service  = $this->service( 'analytics_service' );
		$items              = $analytics_service && method_exists( $analytics_service, 'get_dashboard_top_products' ) ? $analytics_service->get_dashboard_top_products( $range ) : array();

		ob_start();
		$this->admin->render_dashboard_top_products( $items, $range, $tab );
		$html = ob_get_clean();

		wp_send_json_success(
			array(
				'html'   => $html,
				'range'  => $range,
			)
		);
	}


	/**
	 * Handles the related plugin operation.
	 */
	public function handle_admin_search_ajax() {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to search commerce data.', 'noesia-commerce-suite' ) ), 403 );
		}
		check_ajax_referer( 'noesia_cs_admin_search', 'nonce' );

		$query = isset( $_POST['query'] ) ? sanitize_text_field( wp_unslash( $_POST['query'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- AJAX nonce verified above.
		$search_service = $this->service( 'admin_search_service' );
		$payload = $search_service && method_exists( $search_service, 'search' ) ? $search_service->search( $query, 5 ) : array(
			'groups'  => array(),
			'note'    => __( 'Search service unavailable.', 'noesia-commerce-suite' ),
		);

		wp_send_json_success( $payload );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_last_hour_orders_ajax() {
		if ( ! current_user_can( NOESIA_CS_CAPABILITY ) ) {
			wp_send_json_error( array( 'message' => __( 'You do not have permission to view order activity.', 'noesia-commerce-suite' ) ), 403 );
		}

		check_ajax_referer( 'noesia_cs_last_hour_orders', 'nonce' );

		$count = 0;
		if ( function_exists( 'wc_get_orders' ) && function_exists( 'wc_get_order_statuses' ) ) {
			$threshold = time() - HOUR_IN_SECONDS;
			try {
				$query = wc_get_orders(
					array(
						'limit'         => 1,
						'paginate'      => true,
						'return'        => 'ids',
						'type'          => 'shop_order',
						'status'        => array_keys( wc_get_order_statuses() ),
						'date_created'  => '>=' . $threshold,
					)
				);

				if ( is_object( $query ) && isset( $query->total ) ) {
					$count = absint( $query->total );
				} elseif ( is_array( $query ) ) {
					$count = count( $query );
				}
			} catch ( Exception $e ) {
				$count = 0;
			}
		}

		wp_send_json_success(
			array(
				'count'  => $count,
				'label'  => sprintf(
					/* translators: %d: number of orders in the last hour. */
					_n( '%d order / 1h', '%d orders / 1h', $count, 'noesia-commerce-suite' ),
					absint( $count )
				),
			)
		);
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_refresh_analytics() {
		$this->ensure_capability( __( 'You do not have permission to refresh analytics.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_refresh_analytics' );
		$analytics_service = $this->service( 'analytics_service' );
		if ( $analytics_service && method_exists( $analytics_service, 'flush_cache' ) ) {
			$analytics_service->flush_cache();
		}
		$this->redirect_with_notice( 'intelligence-analytics', 'analytics-refreshed' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_generate_token() {
		$order_id = isset( $_GET['order_id'] ) ? absint( wp_unslash( $_GET['order_id'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Order ID is required to validate the matching nonce action.
		$this->ensure_capability( __( 'You do not have permission to generate tokens.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_generate_token_' . $order_id );
		$order             = function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : null;
		$passport_service  = $this->service( 'passport_service' );
		if ( $order && $passport_service && method_exists( $passport_service, 'get_or_create_token_for_order' ) ) {
			$passport_service->get_or_create_token_for_order( $order );
		}
		wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'admin.php?page=noesia-commerce-suite&tab=order-care-hub&noesia_cs_hub_section=access' ) );
		exit;
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_send_test_email() {
		$this->ensure_capability( __( 'You do not have permission to send verification emails.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_send_test_email' );
		$recipient = isset( $_POST['noesia_cs_test_email_recipient'] ) ? sanitize_email( wp_unslash( $_POST['noesia_cs_test_email_recipient'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Admin-post nonce verified above.
		$email_service  = $this->service( 'email_service' );
		$result         = $email_service && method_exists( $email_service, 'send_test_email' ) ? $email_service->send_test_email( $recipient ) : new WP_Error( 'noesia_cs_email_service_unavailable', __( 'Email service unavailable.', 'noesia-commerce-suite' ) );
		$this->redirect_with_notice( 'emails', is_wp_error( $result ) ? 'email-failed' : 'email-sent' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_build_reorder_queue() {
		$this->ensure_capability( __( 'You do not have permission to build reorder reminders.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_build_reorder_queue' );
		$reorder_service = $this->service( 'reorder_service' );
		if ( $reorder_service && method_exists( $reorder_service, 'build_due_queue' ) ) {
			$reorder_service->build_due_queue();
		}
		$this->redirect_with_notice( 'reorder-reminders', 'reorder-built' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_process_reorder_queue() {
		$this->ensure_capability( __( 'You do not have permission to process reorder reminders.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_process_reorder_queue' );
		$reorder_service = $this->service( 'reorder_service' );
		$result = $reorder_service && method_exists( $reorder_service, 'process_due_queue' ) ? $reorder_service->process_due_queue() : array( 'inactive' => true );
		$this->redirect_with_notice( 'reorder-reminders', ! empty( $result['inactive'] ) ? 'reorder-inactive' : 'reorder-processed' );
	}


	/**
	 * Handles the related plugin operation.
	 */
	public function handle_send_reorder_test_copy() {
		$this->ensure_capability( __( 'You do not have permission to send reorder reminder test copies.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_send_reorder_test_copy' );

		$queue_key = isset( $_POST['noesia_cs_reorder_queue_key'] ) ? sanitize_text_field( wp_unslash( $_POST['noesia_cs_reorder_queue_key'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Admin-post nonce verified above.
		$recipient = isset( $_POST['noesia_cs_reorder_test_recipient'] ) ? sanitize_email( wp_unslash( $_POST['noesia_cs_reorder_test_recipient'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Admin-post nonce verified above.

		$reorder_service = $this->service( 'reorder_service' );
		if ( $queue_key && $reorder_service && method_exists( $reorder_service, 'send_test_copy_to_admin' ) ) {
			$result = $reorder_service->send_test_copy_to_admin( $queue_key, $recipient );
		} elseif ( $reorder_service && method_exists( $reorder_service, 'send_sample_test_copy_to_admin' ) ) {
			$result = $reorder_service->send_sample_test_copy_to_admin( $recipient );
		} else {
			$result = new WP_Error( 'noesia_cs_reorder_service_unavailable', __( 'Reorder reminder service unavailable.', 'noesia-commerce-suite' ) );
		}

		$this->redirect_with_notice( 'reorder-reminders', is_wp_error( $result ) ? 'reorder-test-failed' : 'reorder-test-sent' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_cleanup_data() {
		$this->ensure_capability( __( 'You do not have permission to clean operational data.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_cleanup_data' );
		$data_service = $this->service( 'data_service' );
		if ( $data_service && method_exists( $data_service, 'cleanup_operational_data' ) ) {
			$data_service->cleanup_operational_data();
		}
		$this->redirect_with_notice( 'settings', 'cleanup-complete' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_regenerate_token() {
		$order_id = isset( $_GET['order_id'] ) ? absint( wp_unslash( $_GET['order_id'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Order ID is required to validate the matching nonce action.
		$this->ensure_capability( __( 'You do not have permission to regenerate tokens.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_regenerate_token_' . $order_id );
		$order             = function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : null;
		$passport_service  = $this->service( 'passport_service' );
		if ( $order && $passport_service && method_exists( $passport_service, 'regenerate_token_for_order' ) ) {
			$passport_service->regenerate_token_for_order( $order );
		}
		wp_safe_redirect( wp_get_referer() ? wp_get_referer() : admin_url( 'admin.php?page=noesia-commerce-suite&tab=order-care-hub&noesia_cs_hub_section=access' ) );
		exit;
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_refresh_rewrites() {
		$this->ensure_capability( __( 'You do not have permission to refresh rewrite rules.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_refresh_rewrites' );
		flush_rewrite_rules();
		$this->redirect_with_notice( 'settings', 'rewrites-refreshed' );
	}

	/**
	 * Handles the related plugin operation.
	 */
	public function handle_print_qr() {
		$order_id = isset( $_GET['order_id'] ) ? absint( wp_unslash( $_GET['order_id'] ) ) : 0; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Order ID is required to validate the matching nonce action.
		$this->ensure_capability( __( 'You do not have permission to print QR package inserts.', 'noesia-commerce-suite' ) );
		check_admin_referer( 'noesia_cs_print_qr_' . $order_id );

		if ( 'yes' !== Noesia_CS_Settings::get( 'allow_printable_qr', 'no' ) ) {
			wp_die( esc_html__( 'Printable QR is disabled in Noesia Commerce Suite settings.', 'noesia-commerce-suite' ) );
		}

		$order = function_exists( 'wc_get_order' ) ? wc_get_order( $order_id ) : null;
		if ( ! $order ) {
			wp_die( esc_html__( 'Order unavailable.', 'noesia-commerce-suite' ) );
		}

		$passport_service  = $this->service( 'passport_service' );
		$url               = $passport_service && method_exists( $passport_service, 'get_care_url_for_order' ) ? $passport_service->get_care_url_for_order( $order ) : '';
		if ( ! $url ) {
			wp_die( esc_html__( 'Care URL unavailable for this order.', 'noesia-commerce-suite' ) );
		}

		wp_register_style( 'noesia-cs-print', NOESIA_CS_URL . 'assets/css/noesia-cs-print.css', array(), NOESIA_CS_VERSION );
		wp_register_script( 'noesia-cs-qrcode', NOESIA_CS_URL . 'assets/libs/qrcode/noesia-cs-qrcode.js', array(), NOESIA_CS_VERSION, false );
		wp_register_script( 'noesia-cs-public', NOESIA_CS_URL . 'assets/js/noesia-cs-public.js', array( 'noesia-cs-qrcode' ), NOESIA_CS_VERSION, false );
		wp_localize_script(
			'noesia-cs-public',
			'noesiaCommerceSuitePublic',
			array(
				'qr'         => array(
					'size'        => max( 120, min( 420, absint( Noesia_CS_Settings::get( 'qr_size', 180 ) ) ) ),
					'foreground'  => Noesia_CS_Settings::get( 'qr_foreground_color', '#111827' ),
					'background'  => Noesia_CS_Settings::get( 'qr_background_color', '#ffffff' ),
				),
			)
		);
		wp_enqueue_style( 'noesia-cs-print' );
		wp_enqueue_script( 'noesia-cs-public' );

		nocache_headers();
		Noesia_CS_Template_Loader::render(
			'admin/printable-qr.php',
			array(
				'order'             => $order,
				'url'               => $url,
				'passport_service'  => $passport_service,
			)
		);
		exit;
	}
}
