{status}_{post_type} does not run correctly?

WooCommerce has its own hooks for things like this. You shouldn’t rely on the underlying WordPress post-related hooks and functions when dealing with products and orders.

WooCommerce is moving towards using custom database tables for products and orders instead of custom post types and while there’ll be hooks etc. added for backwards compatibility, you’ll be much better situated for that transition if you use WooCommerce’s APIs.

WooCommerce has 3 hooks for handling order status transitions:

woocommerce_order_status_{status} runs when transitioning to {status} from any other status.

woocommerce_order_status_{from}_to_{to} runs when transitioning to status {to} from status {from}

woocommerce_order_status_changed runs when there’s any transition change and receives the from and to status as the 2nd and 3rd callbacks of the callback respectively.

Note that the status in all these hooks should omit the wc- prefix.

function wpse_313075_order_on_hold( $order_id, $order ) {
    // Do something.
}
add_action( 'woocommerce_order_status_on-hold', 'wpse_313075_order_on_hold', 10, 2 );

function wpse_313075_order_pending_to_on_hold( $order_id, $order ) {
    // Do something.
}
add_action( 'woocommerce_order_status_pending_to_on-hold', 'wpse_313075_order_pending_to_on_hold', 10, 2 );

function wpse_313075_order_status_changed( $order_id, $from, $to, $order ) {
    // Do something.
}
add_action( 'woocommerce_order_status_changed', 'wpse_313075_order_status_changed', 10, 4 );