<?php
if ( ! defined( 'ABSPATH' ) ) exit;

class OrderPickingApp {

    protected $loader;
    private static $logPath;
    private $orderedCategories;
    private $productCategories;

    public function __construct(){
        $this->load_dependencies();
        $this->define_admin_hooks();

        $this->orderedCategories = array();
        $this->productCategories = array();

        $path = wp_get_upload_dir()['basedir'];
        if (is_dir($path)) {
            $pathComplete = $path;
            $subpath      = '/orderpickingapp/logs';
            $pathComplete = $pathComplete . $subpath;

            if ( ! wp_mkdir_p( $pathComplete ) ) {
                wp_die(
                    sprintf(
                    /* translators: %s: Directory path. */
                        esc_html__(
                            'Failed to create the subdirectory: %s',
                            'order-picking-app'
                        ),
                        esc_html( $pathComplete )
                    )
                );
            }

            self::$logPath = $pathComplete;

            $logFilePath = trailingslashit( $pathComplete ) . wp_date( 'Y-m-d' ) . '.log';

            if ( ! file_exists( $logFilePath ) ) {
                // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_touch -- Local plugin log file in uploads directory.
                touch( $logFilePath );
            }
        } else {
            wp_die(
                sprintf(
                /* translators: %s: Directory path. */
                    esc_html__(
                        'Failed to create logs in directory: %s',
                        'order-picking-app'
                    ),
                    esc_html( $path )
                )
            );
        }

        add_action('woocommerce_admin_order_item_headers', array($this, 'orderpickingapp_admin_order_item_headers'));
        add_action('woocommerce_admin_order_item_values', array($this, 'orderpickingapp_admin_order_item_values'), 10, 3);

        add_filter('woocommerce_get_wp_query_args', function ($wp_query_args, $query_vars) {
            if (isset($query_vars['meta_query'])) {
                $meta_query = isset($wp_query_args['meta_query']) ? $wp_query_args['meta_query'] : [];
                $wp_query_args['meta_query'] = array_merge($meta_query, $query_vars['meta_query']);
            }
            return $wp_query_args;
        }, 10, 2);

        add_filter('woocommerce_order_data_store_cpt_get_orders_query', function ($wp_query_args, $query_vars) {
            if (isset($query_vars['meta_query'])) {
                $meta_query = isset($wp_query_args['meta_query']) ? $wp_query_args['meta_query'] : [];
                $wp_query_args['meta_query'] = array_merge($meta_query, $query_vars['meta_query']);
            }
            return $wp_query_args;
        }, 10, 2);
    }

    public
    function orderpickingapp_admin_order_item_headers()
    {
        echo '<th>' . esc_html__( 'Picking', 'order-picking-app' ) . '</th>';
    }

    public
    function orderpickingapp_admin_order_item_values($_product, $item, $item_id = null)
    {
        $picking_status = $item->get_meta('picking_status');
        $backorder = $item->get_meta('backorder');

        $user_claimed = '-';
        if( method_exists($item, 'get_order_id') ){
            $order_id = $item->get_order_id();
            $order = wc_get_order($order_id);
            $user_claimed = $order->get_meta('user_claimed');
        }

        if (isset($picking_status) && !empty($picking_status)) {
            echo '<td>';
            echo esc_html__( 'Status:', 'order-picking-app' ) . ' ' . esc_html( $picking_status );
            echo '<br>';
            echo esc_html__( 'Backorders:', 'order-picking-app' ) . ' ' . esc_html( $backorder );
            echo '<br>';
            echo esc_html__( 'Picker:', 'order-picking-app' ) . ' ' . esc_html( ucfirst( $user_claimed ) );
            echo '</td>';
        } else {
            echo '<td></td>';
        }

    }

    private
    function load_dependencies()
    {
        require_once plugin_dir_path(dirname(__FILE__)) . 'vendor/autoload.php';
        require_once plugin_dir_path(dirname(__FILE__)) . 'admin/class-orderpickingapp-admin.php';
        require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-orderpickingapp-loader.php';
        require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-feedback.php';
        require_once plugin_dir_path(dirname(__FILE__)) . 'includes/class-pickingroute.php';

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

    private
    function define_admin_hooks()
    {
        $admin = new OrderPickingApp_Admin();
        $this->loader->add_action('admin_enqueue_scripts', $admin, 'orderpickingapp_enqueue_plugin_styles_scripts');
        $this->loader->add_action('admin_menu', $admin, 'add_orderpickingapp_admin_pages');
        $this->loader->add_action('admin_init', $admin, 'display_orderpickingapp_panel_fields');
        $this->loader->add_action('admin_notices', $admin, 'orderpickingapp_missing_app_token_message');
        $this->loader->add_action('wp_ajax_save_app_settings', $admin, 'orderpickingapp_save_app_settings');
        $this->loader->add_action('wp_ajax_orderpickingapp_reset_api_key', $admin, 'orderpickingapp_reset_api_key');
        $this->loader->add_action('wp_ajax_reset_order_picking_data', $admin, 'orderpickingapp_reset_picking_data_callback');
        $this->loader->add_action('wp_ajax_create_user_account', $admin, 'orderpickingapp_create_user_account');
        $this->loader->add_action('wp_ajax_load_analytics_html', $admin, 'orderpickingapp_loadAnalyticsHTML');
        $this->loader->add_action('wp_ajax_download_csv_export', $admin, 'orderpickingapp_downloadCSVExport');
        $this->loader->add_action('init', $admin, 'add_orderpickingapp_taxonomies');

        // WordPress.org loads translations automatically for plugins hosted in the directory.
        $this->loader->add_action('rest_api_init', $this, 'orderpickingapp_register_endpoints');

        $uninstall_feedback = new OPA_Uninstall_Feedback();
    }

    public
    function run()
    {
        $this->loader->run();
    }

    public function orderpickingapp_can_access_picking_api( WP_REST_Request $request ) {

        if ( ! class_exists( 'WooCommerce' ) ) {
            return new WP_Error(
                'woocommerce_missing',
                __( 'WooCommerce not active', 'order-picking-app' ),
                array( 'status' => 400 )
            );
        }

        $token = $request->get_header( 'x-auth-token' );

        if ( empty( $token ) ) {
            $token = $request->get_param( 'token' );
        }

        $saved_token = get_option( 'orderpickingapp_apikey' );

        if ( empty( $saved_token ) || empty( $token ) ) {
            return new WP_Error(
                'rest_forbidden',
                __( 'Unauthorized', 'order-picking-app' ),
                array( 'status' => 401 )
            );
        }

        if ( ! hash_equals( (string) $saved_token, (string) $token ) ) {
            return new WP_Error(
                'rest_forbidden',
                __( 'Unauthorized', 'order-picking-app' ),
                array( 'status' => 401 )
            );
        }

        return true;
    }

    public
    function orderpickingapp_register_endpoints()
    {

        register_rest_route('picking/v1', '/get-settings', array(
            'methods' => 'GET',
            'callback' => array($this, 'getSettings'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-order-products', array(
            'methods' => 'GET',
            'callback' => array($this, 'getOrderProducts'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/pickinglist', array(
            'methods' => 'GET',
            'callback' => array($this, 'getPickingList'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/update-order-products', array(
            'methods' => 'POST',
            'callback' => array($this, 'updateOrderProducts'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/reset-order-products', array(
            'methods' => 'GET',
            'callback' => array($this, 'resetOrderProducts'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-packing-orders', array(
            'methods' => 'GET',
            'callback' => array($this, 'requestPackingOrders'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-pickup-orders', array(
            'methods' => 'GET',
            'callback' => array($this, 'requestPickupOrders'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-delivery-orders', array(
            'methods' => 'GET',
            'callback' => array($this, 'requestDeliveryOrders'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/update-order-status', array(
            'methods' => 'POST',
            'callback' => array($this, 'updateOrderStatus'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/create-order-note', array(
            'methods' => 'POST',
            'callback' => array($this, 'createOrderNote'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-categories', array(
            'methods' => 'GET',
            'callback' => array($this, 'getCategories'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-product', array(
            'methods' => 'GET',
            'callback' => array($this, 'getProduct'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));
        register_rest_route('picking/v1', '/update-product', array(
            'methods' => 'POST',
            'callback' => array($this, 'updateProduct'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/reset-picking-orders', array(
            'methods' => 'GET',
            'callback' => array($this, 'resetPickingOrders'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-customers', array(
            'methods' => 'GET',
            'callback' => array($this, 'getCustomers'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));
        register_rest_route('picking/v1', '/create-order', array(
            'methods' => 'POST',
            'callback' => array($this, 'createOrder'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));
        register_rest_route('picking/v1', '/get-order', array(
            'methods' => 'GET',
            'callback' => array($this, 'getOrder'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));
        register_rest_route('picking/v1', '/unclaim-order', array(
            'methods' => 'POST',
            'callback' => array($this, 'unClaimOrder'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));
        register_rest_route('picking/v1', '/create-batch', array(
            'methods' => 'POST',
            'callback' => array($this, 'createBatch'),
            'permission_callback' => array( $this, 'orderpickingapp_can_access_picking_api' ),
        ));

        register_rest_route('picking/v1', '/get-pos-catalog', array(
            'methods' => 'GET',
            'callback' => array($this, 'getPosCatalog'),
            'permission_callback' => array($this, 'orderpickingapp_can_access_picking_api'),
        ));

        register_rest_route('picking/v1', '/get-pos-products', array(
            'methods' => 'GET',
            'callback' => array($this, 'getPosProducts'),
            'permission_callback' => array($this, 'orderpickingapp_can_access_picking_api'),
        ));
    }

    public function getAllPickingOrders() {
        global $wpdb;

        $order_statuses               = array( 'wc-processing' );
        $orderpickingapp_order_status = get_option( 'orderpickingapp_order_status' );
        $picking_date                 = get_option( 'pickingDate' );
        $is_hpos_enabled              = $this->is_hpos_enabled();

        if ( ! empty( $orderpickingapp_order_status ) ) {
            $order_statuses = array_map( 'sanitize_key', (array) $orderpickingapp_order_status );
        }

        $cache_group = 'order-picking-app';
        $cache_key   = 'all_picking_orders_' . md5(
                wp_json_encode(
                    array(
                        'statuses' => $order_statuses,
                        'date'     => $picking_date,
                        'hpos'     => $is_hpos_enabled,
                    )
                )
            );

        $cached_order_ids = wp_cache_get( $cache_key, $cache_group );

        if ( false !== $cached_order_ids ) {
            $order_ids = $cached_order_ids;
        } else {
            $date_column    = $is_hpos_enabled ? 'date_created_gmt' : 'post_date';
            $date_sql       = '';
            $date_sql_value = null;

            if ( ! empty( $picking_date ) ) {
                $picking_date = sanitize_text_field( $picking_date );
                $datetime     = DateTime::createFromFormat( 'Y-m-d', $picking_date, wp_timezone() );

                if ( $datetime ) {
                    $date_sql       = " AND {$date_column} >= %s";
                    $date_sql_value = $datetime->format( 'Y-m-d' );
                }
            }

            $has_completed          = in_array( 'wc-completed', $order_statuses, true );
            $non_completed_statuses = array_values( array_diff( $order_statuses, array( 'wc-completed' ) ) );

            $order_ids = array();

            if ( ! empty( $non_completed_statuses ) ) {
                $status_placeholders = implode( ',', array_fill( 0, count( $non_completed_statuses ), '%s' ) );
                $query_values        = $non_completed_statuses;

                if ( null !== $date_sql_value ) {
                    $query_values[] = $date_sql_value;
                }

                if ( $is_hpos_enabled ) {
                    $sql = "
                        SELECT id
                        FROM {$wpdb->prefix}wc_orders
                        WHERE type = 'shop_order'
                            AND status IN ($status_placeholders)
                            {$date_sql}
                        LIMIT 1000
                    ";
                } else {
                    $sql = "
                        SELECT ID
                        FROM {$wpdb->posts}
                        WHERE post_type = 'shop_order'
                            AND post_status IN ($status_placeholders)
                            {$date_sql}
                        LIMIT 1000
                    ";
                }

                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Dynamic placeholders and whitelisted date column are prepared below.
                $order_ids_query = $wpdb->prepare( $sql, ...$query_values );
                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared directly above with $wpdb->prepare().
                $order_ids       = $wpdb->get_col( $order_ids_query );
            }

            if ( $has_completed ) {
                $query_values = array(
                    'picking_status',
                    'wc-completed',
                );

                if ( null !== $date_sql_value ) {
                    $query_values[] = $date_sql_value;
                }

                $query_values[] = 'completed';

                if ( $is_hpos_enabled ) {
                    $sql = "
                        SELECT o.id
                        FROM {$wpdb->prefix}wc_orders o
                        LEFT JOIN {$wpdb->prefix}wc_orders_meta m
                            ON o.id = m.order_id
                            AND m.meta_key = %s
                        WHERE o.type = 'shop_order'
                            AND o.status = %s
                            {$date_sql}
                            AND (m.meta_value IS NULL OR m.meta_value != %s)
                        LIMIT 1000
                    ";
                } else {
                    $sql = "
                        SELECT p.ID
                        FROM {$wpdb->posts} p
                        LEFT JOIN {$wpdb->postmeta} pm
                            ON p.ID = pm.post_id
                            AND pm.meta_key = %s
                        WHERE p.post_type = 'shop_order'
                            AND p.post_status = %s
                            {$date_sql}
                            AND (pm.meta_value IS NULL OR pm.meta_value != %s)
                        LIMIT 1000
                    ";
                }

                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Dynamic placeholders and whitelisted date column are prepared below.
                $completed_ids_query = $wpdb->prepare( $sql, ...$query_values );
                // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared -- Query is prepared directly above with $wpdb->prepare().
                $completed_ids       = $wpdb->get_col( $completed_ids_query );

                if ( ! empty( $completed_ids ) ) {
                    $order_ids = array_merge( $order_ids, $completed_ids );
                }
            }

            $order_ids = array_values( array_unique( array_map( 'absint', $order_ids ) ) );
            $order_ids = array_slice( $order_ids, 0, 1000 );

            wp_cache_set( $cache_key, $order_ids, $cache_group, 300 );
        }

        if ( empty( $order_ids ) ) {
            return array();
        }

        $query = new WC_Order_Query(
            array(
                'post__in' => $order_ids,
                'limit'    => count( $order_ids ),
                'orderby'  => 'date',
                'order'    => 'ASC',
            )
        );

        return $query->get_orders();
    }

    public
    function getSettings($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $all_open_orders = $this->getAllPickingOrders();

        $user_orders = array();
        $total_picking_orders = 0;
        $total_packing_orders = 0;
        $total_backorders = 0;
        $total_picking_products = 0;
        if( count($all_open_orders) > 0 ) {
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';

                    $picking_order_status = get_option('picking_order_status');
                    if( !empty($picking_order_status) ) {
                        $picking_order_status = str_replace('wc-', '', $picking_order_status);
                        $open_order->update_status($picking_order_status, 'Order Picking App | Status changed');
                        $open_order->save();
                    }
                }

                switch ($picking_status){

                    case 'picking':
                    case '':
                        $user_claimed = $open_order->get_meta('user_claimed');

                        if (isset($user_claimed) && !empty($user_claimed)) {
                            if (isset($user_orders[$user_claimed])) {
                                $user_orders[$user_claimed] = $user_orders[$user_claimed] + 1;
                            } else {
                                $user_orders[$user_claimed] = 1;
                            }
                        }

                        $total_picking_order_items = $open_order->get_items();
                        $total_picking_products += count($total_picking_order_items);

                        $total_picking_orders++;
                        break;

                    case 'packing':
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $total_backorders++;
                                break;
                            }

                        }

                        $total_packing_orders++;
                        break;
                }

            }
        }

        $plugin_data = get_plugin_data(OPA_PLUGIN_DIR.'/orderpickingapp.php');

        return new WP_REST_Response( array(
            'total_picking_orders'   => (int) $total_picking_orders,
            'total_packing_orders'   => (int) $total_packing_orders,
            'total_backorders'       => (int) $total_backorders,
            'total_picking_products' => (int) $total_picking_products,
            'plugin_version'         => $plugin_data['Version'],
            'user_orders'            => $user_orders,
        ), 200 );
    }

    public
    function updateOrderProducts($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $body = $request->get_body();
        $data = json_decode($body, true);
        if (isset($data[0]['orderid'])) {
            $data = $data[0];
        }
        $appuser = $request->get_param('appuser');

        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        if (isset($data['products']) && !empty($data['products'])) {

            $products = json_decode($data['products'], true);

            // Iterate picked products
            $order_notes_done = array();
            foreach ($products as $product) {

                $picked_amount = $product['ordered'] - $product['backorder'];

                // Iterate related orders for this product
                foreach ($product['orders'] as $order) {
                    $Order = wc_get_order($order['orderid']);

                    if (!in_array($order['orderid'], $order_notes_done)) {

                        if( $data['status'] == 'completed' ){
                            $Order->add_order_note('Order Picking App | Order packing completed by ' . $appuser . '.');
                            $auto_completed_order = get_option('auto_completed_order');
                            if (isset($data['status']) && $data['status'] == 'completed' && isset($auto_completed_order) && $auto_completed_order == 'yes') {

                                $completed_order_status = get_option('completed_order_status');
                                if( !empty($completed_order_status) ) {
                                    $completed_order_status = str_replace('wc-', '', $completed_order_status);
                                    $Order->update_status($completed_order_status, 'Order Picking App | Status changed');
                                }
                                else{
                                    $Order->update_status('completed', 'Order Picking App | Status changed');
                                }
                            }
                        }
                        else {
                            $Order->add_order_note('Order Picking App | Order picking completed by ' . $appuser . '. Order now available for packing.');

                            $shipping_methods = $Order->get_shipping_methods();
                            $order_status_mapping = get_option('packing_order_status_mapping', []);
                            if( is_array($shipping_methods) && !empty($shipping_methods) ) {
                                $first_shipping_method = reset($shipping_methods);
                                $order_shipping_method = $first_shipping_method->get_method_id();
                                if (isset($order_status_mapping[$order_shipping_method]) && !empty($order_status_mapping[$order_shipping_method])) {
                                    $new_status = $order_status_mapping[$order_shipping_method];
                                    $Order->update_status($new_status, 'Order Picking App | Status changed');
                                    $this->log('Order ' . $order['orderid'] . ' status changed for ' . $order_shipping_method . ' to ' . $new_status, 'Info');
                                }
                            }
                            elseif( isset($order_status_mapping['default']) && !empty($order_status_mapping['default']) ){
                                $new_status = $order_status_mapping['default'];
                                $Order->update_status($new_status, 'Order Picking App | Status changed');
                                $this->log('Order ' . $order['orderid'] . ' status changed for ' . $order_shipping_method . ' to ' . $new_status, 'Info');
                            }
                            else{
                                $packing_order_status = get_option('packing_order_status');
                                if( !empty($packing_order_status) ) {
                                    $packing_order_status = str_replace('wc-', '', $packing_order_status);
                                    $Order->update_status($packing_order_status, 'Order Picking App | Status changed');
                                }
                            }
                        }

                        $Order->update_meta_data('picking_status', $data['status']);
                        $Order->update_meta_data('ordernote', $data['ordernote']);
                        $this->log('Order picking completed for order:  ' . $order['orderid'] . ' by ' . $appuser, 'Info');

                        $order_notes_done[$order['orderid']] = $order['orderid'];
                    }

                    // Check for existing product inside order
                    foreach ($Order->get_items() as $item_id => $item) {
                        $product_processed_stock = $item->get_quantity();

                        // Set order item/product status to picked
                        $variation_id = $item->get_variation_id();
                        if (isset($variation_id) && !empty($variation_id)) {
                            $product_id = $variation_id;
                        } else {
                            $product_id = $item->get_product_id();
                        }

                        if (isset($product_id) && $product_id == $product['product_id']) {

                            // Eerst weight products afhandelen
                            if ($this->process_weight_product_item($Order, $item, $product)) {
                                break;
                            }

                            // Bestaande logica voor normale producten
                            if ($product['backorder'] == 0) {
                                $item->update_meta_data('picking_status', 'completed');
                                $item->update_meta_data('backorder', '0');
                            }
                            else {
                                $disable_backorders = get_option('disable_backorders');
                                if (isset($disable_backorders) && $disable_backorders == 'yes') {

                                    $original_quantity = $item->get_quantity();
                                    $original_total = $item->get_total();
                                    $original_subtotal = $item->get_subtotal();

                                    $unit_price = ($original_quantity > 0) ? round($original_total / $original_quantity, 2) : 0;
                                    $unit_subtotal = ($original_quantity > 0) ? round($original_subtotal / $original_quantity, 2) : 0;

                                    if ($product['backorder'] < 0) {
                                        $new_order_item_amount = $product_processed_stock + abs($product['backorder']);
                                    } else {
                                        $new_order_item_amount = $product_processed_stock - abs($product['backorder']);
                                    }

                                    $item->set_quantity($new_order_item_amount);

                                    $new_total = $new_order_item_amount * $unit_price;
                                    $new_subtotal = $new_order_item_amount * $unit_subtotal;

                                    $item->set_total($new_total);
                                    $item->set_subtotal($new_subtotal);

                                    $item->update_meta_data('picking_status', 'completed');
                                    $Order->add_order_note(
                                        'Order Picking App | Order item with SKU ' . $product['sku'] .
                                        ' changed from ' . $product_processed_stock . ' to ' . $new_order_item_amount
                                    );
                                }
                                elseif ($picked_amount >= $product_processed_stock) {
                                    $picked_amount = $picked_amount - $product_processed_stock;
                                    $item->update_meta_data('picking_status', 'completed');
                                    $item->update_meta_data('backorder', '0');
                                }
                                else {
                                    $item->update_meta_data('picking_status', 'backorder');
                                    $item->update_meta_data('backorder', $product['backorder']);
                                }
                            }

                            $item->save();
                            break;
                        }
                        elseif ((!isset($product_id) || empty($product_id)) && $item_id == $product['product_id']) {

                            // Eerst weight products afhandelen
                            if ($this->process_weight_product_item($Order, $item, $product)) {
                                break;
                            }

                            // Bestaande fallback logica
                            if ($product['backorder'] == 0) {
                                $item->update_meta_data('picking_status', 'completed');
                                $item->update_meta_data('backorder', '0');
                            } elseif ($picked_amount >= $product_processed_stock) {
                                $picked_amount = $picked_amount - $product_processed_stock;
                                $item->update_meta_data('picking_status', 'completed');
                                $item->update_meta_data('backorder', '0');
                            } else {
                                $item->update_meta_data('picking_status', 'backorder');
                                $item->update_meta_data('backorder', $product['backorder']);
                            }

                            $item->save();
                            break;
                        }
                    }

                    $Order->calculate_taxes();
                    $Order->calculate_totals();
                    $Order->save();
                }
            }
        }

        $all_open_orders = $this->getAllPickingOrders();

        $open_picking_orders = array();
        $total_picking_orders = 0;
        $total_packing_orders = 0;
        $total_backorders = 0;
        if( count($all_open_orders) > 0 ) {
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';
                }

                switch ($picking_status){
                    case 'picking':
                    case '':
                        $total_picking_order = $open_order;

                        $total_items = 0;
                        foreach ($total_picking_order->get_items() as $item_id => $item) {
                            $product_id = $item->get_product_id();
                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
                                $product_info = wc_get_product($product_id);
                                $product_type = $product_info->get_type();
                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                    $total_items = $total_items + $item->get_quantity();
                                }
                            } else {
                                $total_items = $total_items + $item->get_quantity();
                            }
                        }

                        $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
                        if (strlen($lastname) < 3) {
                            $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
                        }

                        $total_picking_order_id = $total_picking_order->get_id();
                        $order_number = $total_picking_order_id;
                        $custom_order_number = $total_picking_order->get_meta('_alg_wc_full_custom_order_number');
                        if( isset($custom_order_number) && !empty($custom_order_number) ){
                            $order_number = $custom_order_number;
                        }
                        else{
                            $custom_order_number = $total_picking_order->get_meta('_order_number');
                            if( isset($custom_order_number) && !empty($custom_order_number) ){
                                $order_number = $custom_order_number;
                            }
                        }

                        $order_prefix = get_option('order_prefix');
                        if (isset($order_prefix) && !empty($order_prefix)) {
                            $order_number = $order_prefix . $order_number;
                        }

                        $custom_field = '';
                        $custom_field_label = '';
                        $deliveryDate = get_post_meta($total_picking_order_id, 'delivery_date', true);
                        if( empty($deliveryDate)) {
                            $deliveryDate = get_post_meta($total_picking_order_id, '_delivery_date', true);
                        }
                        if (!empty($deliveryDate)) {
                            $deliveryDate = strtotime($deliveryDate);
                            $custom_field_label = 'Delivery';
                            $custom_field = wp_date( 'm-d', $deliveryDate );
                        }

                        $order_date = substr($total_picking_order->get_date_created(), 5, 5);
                        $order_date = apply_filters('orderpickingapp_order_date', $order_date, $total_picking_order);

                        $order_data = array(
                            'orderid'               => $total_picking_order_id,
                            'order_number'          => $order_number,
                            'date'                  => $order_date,
                            'items'                 => $total_items,
                            'total'                 => $currency_symbol . ' ' . $total_picking_order->get_total(),
                            'lastname'              => $lastname,
                            'shipping'              => $total_picking_order->get_shipping_method(),
                            'claimed_by'            => $total_picking_order->get_meta('user_claimed'),
                            'custom_field_label'    => $custom_field_label,
                            'custom_field'          => $custom_field,
                        );
                        $open_picking_orders[] = apply_filters('orderpickingapp_order_data', $order_data);

                        $total_picking_orders++;
                        break;

                    case 'packing':
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $total_backorders++;
                                break;
                            }

                        }

                        $total_packing_orders++;
                        break;
                }
            }
        }

        return new WP_REST_Response( array(
            'total_picking_orders' => (int)$total_picking_orders,
            'total_packing_orders' => (int)$total_packing_orders,
            'total_backorders' => (int)$total_backorders,
            'open_picking_orders' => $open_picking_orders
        ), 200 );
    }

    private function process_weight_product_item($Order, $item, $product) {
        $is_weight_product = $item->get_meta('_wcwp_is_weight_product', true) === 'yes';
        $has_actual_weight = isset($product['actual_weight']) && $product['actual_weight'] !== '';

        if (!$is_weight_product || !$has_actual_weight) {
            return false;
        }

        $actual_weight  = (float) wc_format_decimal($product['actual_weight']);
        $price_per_unit = (float) $item->get_meta('_wcwp_price_per_unit', true);

        if ($actual_weight <= 0 || $price_per_unit <= 0) {
            return false;
        }

        $new_total = $actual_weight * $price_per_unit;

        $item->update_meta_data('_wcwp_actual_weight', wc_format_decimal($actual_weight, 6));
        $item->update_meta_data('_wcwp_weight_status', 'weighed');

        // Quantity blijft het aantal besteleenheden
        $item->set_total($new_total);
        $item->set_subtotal($new_total);

        $item->update_meta_data('picking_status', 'completed');
        $item->update_meta_data('backorder', '0');

        $sku = isset($product['sku']) ? $product['sku'] : '';
        $unit = $item->get_meta('_wcwp_pricing_unit', true);

        $Order->add_order_note(
            'Order Picking App | Weight product ' . $sku .
            ' weighed at ' . wc_format_decimal($actual_weight, 3) . ' ' . $unit
        );

        $item->save();

        return true;
    }

    public
    function resetPickingOrders($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $appuser = $request->get_param('appuser');
        $all_open_orders = $this->getAllPickingOrders();

        if( count($all_open_orders) > 0 ) {
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';
                }

                if( $picking_status == 'picking' ) {
                    if (!empty($appuser)) {
                        $user_claimed = $open_order->get_meta('user_claimed');
                        if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
                            continue;
                        }
                    }

                    $open_order->delete_meta_data('picking_status');
                    $open_order->delete_meta_data('user_claimed');
                    $open_order->delete_meta_data('batch_id');
                    $open_order->delete_meta_data('ordernote');
                    $open_order->save();
                }
            }
        }
    }

    public
    function resetOrderProducts($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

            $orderid = $request->get_param('orderid');
            $appuser = $request->get_param('appuser');

        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        $Order = wc_get_order($orderid);
        $Order->add_order_note('Order Picking App | Order picking reset by ' . $appuser . '. Order reset to picking list.');
        $Order->delete_meta_data('picking_status');
        $this->log('Order picking reset for order:  ' . $orderid . ' by ' . $appuser, 'Info');
        foreach ($Order->get_items() as $item_id => $item) {
            $item->delete_meta_data('picking_status');
            $item->delete_meta_data('backorder');
        }
        $Order->save();

        $all_open_orders = $this->getAllPickingOrders();

        $open_picking_orders = array();
        $total_picking_orders = 0;
        $total_packing_orders = 0;
        $total_backorders = 0;
        if( count($all_open_orders) > 0 ) {
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';
                }

                switch ($picking_status){

                    case 'picking':
                    case '':
                        $total_picking_order = $open_order;

                        $total_items = 0;
                        foreach ($total_picking_order->get_items() as $item_id => $item) {
                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                                $product_id = $item->get_product_id();
                                $product_info = wc_get_product($product_id);
                                $product_type = $product_info->get_type();
                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                    $total_items = $total_items + $item->get_quantity();
                                }
                            } else {
                                $total_items = $total_items + $item->get_quantity();
                            }
                        }

                        $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
                        if (strlen($lastname) < 3) {
                            $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
                        }

                        $total_picking_order_id = $total_picking_order->get_id();
                        $order_number = $total_picking_order_id;
                        $custom_order_number = $total_picking_order->get_meta('_alg_wc_full_custom_order_number');
                        if( isset($custom_order_number) && !empty($custom_order_number) ){
                            $order_number = $custom_order_number;
                        }
                        else{
                            $custom_order_number = $total_picking_order->get_meta('_order_number');
                            if( isset($custom_order_number) && !empty($custom_order_number) ){
                                $order_number = $custom_order_number;
                            }
                        }

                        $order_prefix = get_option('order_prefix');
                        if (isset($order_prefix) && !empty($order_prefix)) {
                            $order_number = $order_prefix . $order_number;
                        }

                        $custom_field = '';
                        $custom_field_label = '';
                        $deliveryDate = get_post_meta($total_picking_order_id, 'delivery_date', true);
                        if( empty($deliveryDate)) {
                            $deliveryDate = get_post_meta($total_picking_order_id, '_delivery_date', true);
                        }
                        if (!empty($deliveryDate)) {
                            $deliveryDate = strtotime($deliveryDate);
                            $custom_field_label = 'Delivery';
                            $custom_field = wp_date( 'm-d', $deliveryDate );
                        }

                        $order_data = array(
                            'orderid'               => $total_picking_order_id,
                            'order_number'          => $order_number,
                            'date'                  => substr($total_picking_order->get_date_created(), 5, 5),
                            'items'                 => $total_items,
                            'total'                 => $currency_symbol . ' ' . $total_picking_order->get_total(),
                            'lastname'              => $lastname,
                            'shipping'              => $total_picking_order->get_shipping_method(),
                            'claimed_by'            => $total_picking_order->get_meta('user_claimed'),
                            'custom_field_label'    => $custom_field_label,
                            'custom_field'          => $custom_field,
                        );
                        $open_picking_orders[] = apply_filters('orderpickingapp_order_data', $order_data);

                        $total_picking_orders++;
                        break;

                    case 'packing':
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $total_backorders++;
                                break;
                            }

                        }

                        $total_packing_orders++;
                        break;
                }
            }
        }

        return new WP_REST_Response( array(
            'total_picking_orders' => (int)$total_picking_orders,
            'total_packing_orders' => (int)$total_packing_orders,
            'total_backorders' => (int)$total_backorders,
            'open_picking_orders' => $open_picking_orders
        ), 200 );
    }

    public
    function updateOrderStatus($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $body = $request->get_body();
        $data = json_decode($body, true);

        if (isset($data[0]['orderid'])) {
            $data = $data[0];
        }

        $auto_completed_order = get_option('auto_completed_order');
        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        if (isset($data['orderid']) && !empty($data['orderid'])) {
            $Order = wc_get_order($data['orderid']);
            if (!empty($Order)) {

                $picking_status = 'completed';
                if( $data['status'] == 'completed' ){
                    $this->log('Order packing completed for order:  ' . $data['orderid'] . ' by ' . $data['appuser'], 'Info');
                    $Order->add_order_note('Order Picking App | Order packing completed by ' . $data['appuser']);

                    $enable_pickup_list = get_option('enable_pickup_list');
                    $pickup_list_methods = get_option('pickup_list_method');
                    if (!is_array($pickup_list_methods)) {
                        $pickup_list_methods = [$pickup_list_methods];
                    }
                    if ($enable_pickup_list === 'yes' && !empty($pickup_list_methods)) {
                        foreach ($Order->get_shipping_methods() as $shipping_item) {
                            $method_key = $shipping_item->get_method_id();
                            if (in_array($method_key, $pickup_list_methods, true)) {
                                $picking_status = 'pickup';
                                break;
                            }
                        }
                    }

                    $enable_delivery_list = get_option('enable_delivery_list');
                    $delivery_list_methods = get_option('delivery_list_method', []);
                    if (!is_array($delivery_list_methods)) {
                        $delivery_list_methods = [$delivery_list_methods];
                    }
                    if ($enable_delivery_list === 'yes' && !empty($delivery_list_methods)) {
                        foreach ($Order->get_shipping_methods() as $shipping_item) {
                            $method_key = $shipping_item->get_method_id();
                            if (in_array($method_key, $delivery_list_methods, true)) {
                                $picking_status = 'delivery';
                                break;
                            }
                        }
                    }
                }

                if( $data['status'] == 'picked_up' ){
                    $Order->add_order_note('Order Picking App | Order pickup handled by ' . $data['appuser']);
                    $this->log('Order:  ' . $data['orderid'] . ' pickup handled by ' . $data['appuser'], 'Info');
                    $picking_status = 'completed';
                }

                if( $data['status'] == 'delivered' ){
                    $Order->add_order_note('Order Picking App | Order delivered by ' . $data['appuser']);
                    $this->log('Order:  ' . $data['orderid'] . ' delivered by ' . $data['appuser'], 'Info');
                    $picking_status = 'completed';
                }

                $Order->update_meta_data('picking_status', $picking_status);
                $Order->update_meta_data('packer', $data['appuser']);

                if( $data['status'] == 'completed' && isset($auto_completed_order) && $auto_completed_order == 'yes') {
                    $completed_order_status = get_option('completed_order_status');
                    if( !empty($completed_order_status) ) {
                        $completed_order_status = str_replace('wc-', '', $completed_order_status);
                        $Order->update_status($completed_order_status, 'Order Picking App | Status changed');
                    }
                    else{
                        $Order->update_status('completed', 'Order Picking App | Status changed');
                    }
                }

                $Order->save();

                $all_open_orders = $this->getAllPickingOrders();

                $open_picking_orders = array();
                $total_picking_orders = 0;
                $total_packing_orders = 0;
                $total_backorders = 0;
                if( count($all_open_orders) > 0 ) {
                    foreach ($all_open_orders as $open_order) {
                        $picking_status = $open_order->get_meta('picking_status');

                        // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                        $user_claimed = $open_order->get_meta('user_claimed');
                        if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                            $picking_status = 'picking';
                        }

                        switch ($picking_status){

                            case 'picking':
                            case '':
                                $total_picking_order = $open_order;

                                $total_items = 0;
                                foreach ($total_picking_order->get_items() as $item_id => $item) {
                                    if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                                        $product_id = $item->get_product_id();
                                        $product_info = wc_get_product($product_id);
                                        $product_type = $product_info->get_type();
                                        if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                            $total_items = $total_items + $item->get_quantity();
                                        }
                                    } else {
                                        $total_items = $total_items + $item->get_quantity();
                                    }
                                }

                                $lastname = substr($total_picking_order->get_shipping_first_name(), 0, 1) . '. ' . $total_picking_order->get_shipping_last_name();
                                if (strlen($lastname) < 3) {
                                    $lastname = substr($total_picking_order->get_billing_first_name(), 0, 1) . '. ' . $total_picking_order->get_billing_last_name();
                                }

                                $total_picking_order_id = $total_picking_order->get_id();
                                $order_number = $total_picking_order_id;
                                $custom_order_number = $total_picking_order->get_meta('_alg_wc_full_custom_order_number');
                                if( isset($custom_order_number) && !empty($custom_order_number) ){
                                    $order_number = $custom_order_number;
                                }
                                else{
                                    $custom_order_number = $total_picking_order->get_meta('_order_number');
                                    if( isset($custom_order_number) && !empty($custom_order_number) ){
                                        $order_number = $custom_order_number;
                                    }
                                }

                                $order_prefix = get_option('order_prefix');
                                if (isset($order_prefix) && !empty($order_prefix)) {
                                    $order_number = $order_prefix . $order_number;
                                }

                                $custom_field = '';
                                $custom_field_label = '';
                                $deliveryDate = get_post_meta($total_picking_order_id, 'delivery_date', true);
                                if( empty($deliveryDate)) {
                                    $deliveryDate = get_post_meta($total_picking_order_id, '_delivery_date', true);
                                }
                                if (!empty($deliveryDate)) {
                                    $deliveryDate = strtotime($deliveryDate);
                                    $custom_field_label = 'Delivery';
                                    $custom_field = wp_date( 'm-d', $deliveryDate );
                                }

                                $order_date = substr($total_picking_order->get_date_created(), 5, 5);
                                $order_date = apply_filters('orderpickingapp_order_date', $order_date, $total_picking_order);

                                $order_data = array(
                                    'orderid'               => $total_picking_order_id,
                                    'order_number'          => $order_number,
                                    'date'                  => $order_date,
                                    'items'                 => $total_items,
                                    'total'                 => $currency_symbol . ' ' . $total_picking_order->get_total(),
                                    'lastname'              => $lastname,
                                    'shipping'              => $total_picking_order->get_shipping_method(),
                                    'claimed_by'            => $total_picking_order->get_meta('user_claimed'),
                                    'custom_field_label'    => $custom_field_label,
                                    'custom_field'          => $custom_field,
                                );
                                $open_picking_orders[] = apply_filters('orderpickingapp_order_data', $order_data);

                                $total_picking_orders++;
                                break;

                            case 'packing':
                                foreach ($open_order->get_items() as $item_id => $item) {
                                    $backorder = $item->get_meta('backorder');
                                    if ($backorder !== '0' && !empty($backorder)) {
                                        $total_backorders++;
                                        break;
                                    }

                                }

                                $total_packing_orders++;
                                break;
                        }
                    }
                }

                $output = array(
                    'total_picking_orders' => (int) $total_picking_orders,
                    'total_packing_orders' => (int) $total_packing_orders,
                    'total_backorders'     => (int) $total_backorders,
                    'open_picking_orders'  => $open_picking_orders,
                );

                return new WP_REST_Response( $output, 200 );
            } else {
                return new WP_REST_Response(
                    array( 'message' => __( 'Unknown order id!', 'order-picking-app' ) ),
                    400
                );
            }
        } else {
            return new WP_REST_Response(
                array( 'message' => __( 'Missing order id!', 'order-picking-app' ) ),
                400
            );
        }
    }

    public
    function createOrderNote($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $body = $request->get_body();
        $data = json_decode($body, true);
        $orderid = $data['orderid'];
        $message = $data['message'];

        $Order = wc_get_order($orderid);
        if (!empty($Order)) {
            $Order->add_order_note($message, true, false);
            $Order->save();


            wp_send_json('Order ' . $orderid . ' note created!', 200);
        } else {
            wp_send_json('Unknown order ID: ' . $orderid, 400);
        }
    }

    public
    function unClaimOrder($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $orderid    = $request->get_param('order_id');

        $Order = wc_get_order($orderid);
        if (!empty($Order)) {
            $Order->delete_meta_data('user_claimed');
            $Order->save();

            wp_send_json('Current picker has been removed from order ' . $orderid, 200);
        } else {
            wp_send_json('Unknown order ID: ' . $orderid, 400);
        }
    }

    public
    function createOrder($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $appuser = $request->get_param('appuser');
        $customer_id = $request->get_param('customer_id');

        $body = $request->get_body();
        $data = json_decode($body, true);

        if( $customer_id === 'new' ){
            if (email_exists($data['customer_email'])) {
                $user = get_user_by('email', $data['customer_email']);
                $customer_id = $user->ID;
            }
            else {

                $username = sanitize_user($data['customer_email']);
                $password = wp_generate_password();

                // Maak een nieuwe gebruiker aan
                $customer_id = wp_insert_user([
                    'user_login' => $username,
                    'user_pass' => $password,
                    'user_email' => $data['customer_email'],
                    'display_name' => $data['customer_email'],
                    'role' => 'customer'
                ]);
                if (is_wp_error($customer_id)) {
                    $customer_id = '';
                } else {
                    update_user_meta($customer_id, 'billing_company', $data['customer_company']);
                    update_user_meta($customer_id, 'billing_email', $data['customer_email']);
                    update_user_meta($customer_id, 'billing_first_name', $data['customer_name']);
                }
            }
        }

        if( isset($customer_id) && !empty($customer_id) ) {
            $order = wc_create_order();
            $order->set_customer_id($customer_id);

            // Haal klantgegevens op
            $customer = new WC_Customer($customer_id);

            $billing = [
                'first_name' => $customer->get_billing_first_name(),
                'last_name'  => $customer->get_billing_last_name(),
                'company'    => $customer->get_billing_company(),
                'address_1'  => $customer->get_billing_address_1(),
                'address_2'  => $customer->get_billing_address_2(),
                'city'       => $customer->get_billing_city(),
                'state'      => $customer->get_billing_state(),
                'postcode'   => $customer->get_billing_postcode(),
                'country'    => $customer->get_billing_country(),
                'email'      => $customer->get_billing_email(),
                'phone'      => $customer->get_billing_phone(),
            ];
            $order->set_address($billing, 'billing');

            $shipping = [
                'first_name' => $customer->get_shipping_first_name(),
                'last_name'  => $customer->get_shipping_last_name(),
                'company'    => $customer->get_shipping_company(),
                'address_1'  => $customer->get_shipping_address_1(),
                'address_2'  => $customer->get_shipping_address_2(),
                'city'       => $customer->get_shipping_city(),
                'state'      => $customer->get_shipping_state(),
                'postcode'   => $customer->get_shipping_postcode(),
                'country'    => $customer->get_shipping_country(),
            ];
            $order->set_address($shipping, 'shipping');

            $order->set_status('wc-on-hold', 'Order created by ' . ucfirst($appuser) . ' | Order Picking App | ');

            foreach ($data['products'] as $product) {
                $wc_product = wc_get_product($product['product_id']);

                if (!$wc_product) {
                    continue;
                }

                $quantity = isset($product['ordered']) ? intval($product['ordered']) : 1;

                $item_id = $order->add_product($wc_product, $quantity);

                $note_meta_key = apply_filters(
                    'orderpickingapp_order_item_note_meta_key',
                    'orderpickingapp_order_item_note',
                    $product,
                    $order
                );

                if (!empty($product['note'])) {
                    $item = $order->get_item($item_id);

                    if ($item) {
                        $item->add_meta_data(
                            $note_meta_key,
                            sanitize_textarea_field($product['note']),
                            true
                        );

                        $item->save();
                    }
                }
            }

            $order->add_meta_data('_wc_order_attribution_source_type', 'utm');
            $order->add_meta_data('_wc_order_attribution_utm_source', 'Order Picking App');
            $order->add_order_note($data['note']);
            $order->calculate_totals();
            $order->save();

            $output = [
                'status'     => 200,
                'message'    => 'Order ' .$order->get_id(). ' created successfully.',
                'order_id'  => $order->get_id(),
            ];
            wp_send_json($output, 200);
        }
        else{
            $args = array(
                'status' => 400,
                'message' => 'Unable to create order',
            );
            wp_send_json($args, 400);
        }
    }

    public
    function getOrder($request)
    {
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $order_id   = $request->get_param('order_id');
        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        $order = wc_get_order( $order_id );
        if ( $order ) {

            $picking_status = $order->get_meta('picking_status');
            if( !empty($picking_status) && $picking_status !== 'picking' ){
                $args = array(
                    'status' => 400,
                    'message' => 'Order already picked!',
                );
                wp_send_json($args);
            }

            $batch_id = $order->get_meta('batch_id');
            if( isset($batch_id) && !empty($batch_id) ){
                $args = array(
                    'status' => 400,
                    'message' => 'Order already connected to a batch!',
                );
                wp_send_json($args);
            }

            $total_items = 0;
            foreach ($order->get_items() as $item) {
                $product_id = $item->get_product_id();
                if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
                    $product_info = wc_get_product($product_id);
                    $product_type = $product_info->get_type();
                    if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                        $total_items = $total_items + $item->get_quantity();
                    }
                } else {
                    $total_items = $total_items + $item->get_quantity();
                }
            }

            $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
            if( strlen($fullname) < 3 ){
                $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
            }

            $order_number = $order_id;
            $custom_order_number = $order->get_meta('_alg_wc_full_custom_order_number');
            if( isset($custom_order_number) && !empty($custom_order_number) ){
                $order_number = $custom_order_number;
            }
            else{
                $custom_order_number = $order->get_meta('_order_number');
                if( isset($custom_order_number) && !empty($custom_order_number) ){
                    $order_number = $custom_order_number;
                }
            }

            $order_prefix = get_option('order_prefix');
            if (isset($order_prefix) && !empty($order_prefix)) {
                $order_number = $order_prefix . $order_number;
            }

            $customer_note = $order->get_customer_note();
            $customer_note = apply_filters('orderpickingapp_order_note', $customer_note, $order_id);

            $order_date = substr($order->get_date_created(), 5, 5);
            $order_date = apply_filters('orderpickingapp_order_date', $order_date, $order);

            $order_data = array(
                'orderid'               => $order_id,
                'order_number'          => $order_number,
                'date'                  => $order_date,
                'items'                 => $total_items,
                'total'                 => $currency_symbol . ' ' . $order->get_total(),
                'fullname'              => $fullname,
                'shipping'              => $order->get_shipping_method(),
                'order_note'            => $customer_note,
            );
            $order_data = apply_filters('orderpickingapp_order_data', $order_data);

            wp_send_json($order_data, 200);
        } else {
            $args = array(
                'status' => 400,
                'message' => 'Order not found!',
            );
            wp_send_json($args);
        }
    }

    public function getPosCatalog($request)
    {
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $per_page = $request->get_param('per_page')
            ? intval($request->get_param('per_page'))
            : 40;

        $categories = get_terms(array(
            'taxonomy'   => 'product_cat',
            'hide_empty' => true,
            'orderby'    => 'name',
            'order'      => 'ASC',
        ));

        $category_data = array();
        if (!is_wp_error($categories)) {
            foreach ($categories as $category) {
                $thumbnail_id = get_term_meta($category->term_id, 'thumbnail_id', true);
                $image = $thumbnail_id ? wp_get_attachment_url($thumbnail_id) : '';

                $category_data[] = array(
                    'id'          => $category->term_id,
                    'name'        => html_entity_decode($category->name),
                    'slug'        => $category->slug,
                    'count'       => intval($category->count),
                    'parent'      => intval($category->parent),
                    'image'       => $image,
                );
            }
        }

        // Featured producten ophalen
        $featured_request = new WP_REST_Request('GET');
        $featured_request->set_param('featured', true);
        $featured_request->set_param('per_page', 100);

        $featured_response = $this->getPosProducts($featured_request, true);

        // Virtuele categorie toevoegen
        array_unshift($category_data, array(
            'id'         => 'featured',
            'name'       => 'Bestsellers',
            'slug'       => 'bestsellers',
            'count'      => count($featured_response['products']),
            'parent'     => 0,
            'image'      => '',
            'is_virtual' => true,
        ));

        $args = array(
            'status'            => 200,
            'categories'        => $category_data,
            'featured_products' => $featured_response['products'],
            'updated_at'        => current_time('c'),
        );

        wp_send_json($args, 200);
    }

    public function getPosProducts($request, $return = false)
    {
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $page        = $request->get_param('page') ? intval($request->get_param('page')) : 1;
        $per_page    = $request->get_param('per_page') ? intval($request->get_param('per_page')) : 40;
        $category_id = $request->get_param('category_id') ? intval($request->get_param('category_id')) : 0;
        $search      = $request->get_param('search') ? sanitize_text_field($request->get_param('search')) : '';

        $page     = max(1, $page);
        $per_page = min(max(1, $per_page), 100);

        $args = array(
            'status'    => array('publish'),
            'limit'     => $per_page,
            'page'      => $page,
            'paginate'  => true,
            'orderby'   => 'title',
            'order'     => 'ASC',
            'return'    => 'objects',
        );

        if (!empty($category_id)) {
            $args['product_category_id'] = array($category_id);
        }

        if ($request->get_param('featured')) {
            $args['tax_query'][] = array(
                'taxonomy' => 'product_visibility',
                'field'    => 'name',
                'terms'    => 'featured',
            );
        }

        if (!empty($search)) {
            $args['s'] = $search;
        }

        $result = wc_get_products($args);

        $products = array();

        if (!empty($result->products)) {
            foreach ($result->products as $product) {
                if (!$product) {
                    continue;
                }

                $image_id = $product->get_image_id();
                $image = $image_id ? wp_get_attachment_image_url($image_id, 'woocommerce_thumbnail') : wc_placeholder_img_src();

                $category_names = array();
                $category_ids = array();

                foreach ($product->get_category_ids() as $cat_id) {
                    $term = get_term($cat_id, 'product_cat');

                    if ($term && !is_wp_error($term)) {
                        $category_ids[] = $cat_id;
                        $category_names[] = html_entity_decode($term->name);
                    }
                }

                $price = $product->get_price();

                $productData = array(
                    'product_id'    => $product->get_id(),
                    'title'         => html_entity_decode($product->get_name()),
                    'sku'           => $product->get_sku(),
                    'barcode'       => get_post_meta($product->get_id(), '_barcode', true),
                    'price'         => $price,
                    'stock'         => $product->managing_stock()
                        ? $product->get_stock_quantity()
                        : $product->get_stock_status(),
                    'thumbnail'     => $image,
                    'category_ids'  => $category_ids,
                    'categories'    => $category_names,
                    'category'      => !empty($category_names) ? $category_names[0] : 'Other',
                );

                if ($product->is_type('variable')) {
                    $variations = array();

                    foreach ($product->get_children() as $variation_id) {
                        $variation = wc_get_product($variation_id);

                        if (!$variation || !$variation->exists()) {
                            continue;
                        }

                        $variations[] = array(
                            'product_id'     => $variation->get_id(),
                            'parent_id'      => $product->get_id(),
                            'title'          => $variation->get_name(),
                            'price'          => $variation->get_price(),
                            'stock'          => $variation->get_stock_quantity(),
                        );
                    }

                    $productData['has_variations'] = true;
                    $productData['variations'] = $variations;
                    $productData['variation_count'] = count($variations);
                } else {
                    $productData['has_variations'] = false;
                    $productData['variations'] = array();
                    $productData['variation_count'] = 0;
                }

                $products[] = $productData;
            }
        }

        $response = array(
            'status' => 200,
            'products' => $products,
            'pagination' => array(
                'page'        => $page,
                'per_page'    => $per_page,
                'total'       => isset($result->total) ? intval($result->total) : count($products),
                'total_pages' => isset($result->max_num_pages) ? intval($result->max_num_pages) : 1,
            ),
        );

        if ($return) {
            return $response;
        }

        wp_send_json($response, 200);
    }

    public
    function createBatch($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Credentials: true");
        header('Access-Control-Allow-Methods: POST');
        header('Access-Control-Max-Age: 1000');
        header('Access-Control-Allow-Headers: Origin, Content-Type, X-Auth-Token , Authorization');

        $appuser = $request->get_param('appuser');

        $body = $request->get_body();
        $data = json_decode($body, true);

        $picking_batch = get_option('picking_batch');
        if (!isset($picking_batch) || empty($picking_batch)) {
            $picking_batch = 0;
        }

        $BatchBoxCharacter = 'A';
        foreach( $data['orderids'] as $orderid ){

            $Order = wc_get_order($orderid);
            $Order->update_meta_data('claimed', 'true');
            $Order->update_meta_data('user_claimed', $appuser);
            $Order->update_meta_data('picking_status', 'picking');
            $Order->update_meta_data('batch_id', $BatchBoxCharacter . '-' . $picking_batch);
            $Order->save();

            $BatchBoxCharacter = chr(ord($BatchBoxCharacter) + 1);
        }

        $args = array(
            'status' => 200,
        );
        wp_send_json($args, 200);
    }

    public function getCustomers( $request )
    {
        header( 'Access-Control-Allow-Origin: *' );
        header( 'Access-Control-Allow-Methods: GET' );

        global $wpdb;

        $search = sanitize_text_field(
            (string) $request->get_param( 'search' )
        );

        $customers = array();

        /*
         * Zoek alleen gebruikers die WooCommerce-klantgegevens hebben.
         * Zonder zoekterm worden alle gebruikers opgehaald.
         */
        if ( $search === '' ) {
            $customer_ids = get_users(
                array(
                    'fields'  => 'ID',
                    'orderby' => 'display_name',
                    'order'   => 'ASC',
                )
            );
        } else {
            $like = '%' . $wpdb->esc_like( $search ) . '%';

            $sql = "
            SELECT DISTINCT users.ID
            FROM {$wpdb->users} AS users

            LEFT JOIN {$wpdb->usermeta} AS first_name
                ON first_name.user_id = users.ID
                AND first_name.meta_key = 'billing_first_name'

            LEFT JOIN {$wpdb->usermeta} AS last_name
                ON last_name.user_id = users.ID
                AND last_name.meta_key = 'billing_last_name'

            LEFT JOIN {$wpdb->usermeta} AS company
                ON company.user_id = users.ID
                AND company.meta_key = 'billing_company'

            LEFT JOIN {$wpdb->usermeta} AS postcode
                ON postcode.user_id = users.ID
                AND postcode.meta_key = 'billing_postcode'

            LEFT JOIN {$wpdb->usermeta} AS billing_email
                ON billing_email.user_id = users.ID
                AND billing_email.meta_key = 'billing_email'

            WHERE
                users.ID = %d
                OR users.user_email LIKE %s
                OR users.user_login LIKE %s
                OR users.display_name LIKE %s
                OR first_name.meta_value LIKE %s
                OR last_name.meta_value LIKE %s
                OR CONCAT(
                    COALESCE(first_name.meta_value, ''),
                    ' ',
                    COALESCE(last_name.meta_value, '')
                ) LIKE %s
                OR company.meta_value LIKE %s
                OR postcode.meta_value LIKE %s
                OR billing_email.meta_value LIKE %s

            ORDER BY users.display_name ASC
        ";

            // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
            $customer_ids = $wpdb->get_col(
                $wpdb->prepare(
                    $sql,
                    absint( $search ),
                    $like,
                    $like,
                    $like,
                    $like,
                    $like,
                    $like,
                    $like,
                    $like,
                    $like
                )
            );
        }

        $roles = wp_roles();

        foreach ( $customer_ids as $customer_id ) {
            $customer = new WC_Customer( $customer_id );

            if ( ! $customer->get_id() ) {
                continue;
            }

            $customer_data = $customer->get_data();
            $user_role     = $customer_data['role'] ?? '';

            if ( isset( $roles->roles[ $user_role ]['name'] ) ) {
                $user_role = translate_user_role(
                    $roles->roles[ $user_role ]['name']
                );
            }

            $customers[] = array(
                'id'         => (int) $customer_id,
                'company'    => $customer->get_billing_company(),
                'contact'    => trim(
                    $customer->get_billing_first_name()
                    . ' '
                    . $customer->get_billing_last_name()
                ),
                'postcode'   => $customer->get_billing_postcode(),
                'email'      => $customer->get_billing_email()
                    ?: $customer->get_email(),
                'user_role'  => $user_role,
            );
        }

        wp_send_json( $customers, 200 );
    }

    public
    function getOrderProducts($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $Products = array();
        $picking_amount = $request->get_param('picking_amount');
        $appuser = $request->get_param('appuser');
        $picking_batch = get_option('picking_batch');
        if (!isset($picking_batch) || empty($picking_batch)) {
            $picking_batch = 0;
        }

        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        $manual_order_assigning = get_option('manual_order_assigning');

        $orderid = $request->get_param('orderid');

        $all_open_orders = $this->getAllPickingOrders();

        $total_picking_orders = 0;
        $total_packing_orders = 0;
        $total_backorders = 0;
        $ordersClaimed = false;
        if( count($all_open_orders) > 0 ) {

            $pickup_list_methods = (array)get_option('pickup_list_method', []);
            $delivery_list_methods = (array)get_option('delivery_list_method', []);

            // Count totals
            $picking_orders = array();
            $next_order_found = false;
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met order gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';
                }

                switch ($picking_status) {

                    case 'picking':
                    case '':

                        $picking_order_id = $open_order->get_id();

                        // GET SPECIFIC ORDER
                        if (isset($orderid) && strpos($orderid, 'find_') !== false) {
                            $selected_orderid = str_replace('find_', '', $orderid);
                            if( $selected_orderid == $picking_order_id ){
                                $picking_orders[] = $open_order;
                            }
                            else{
                                $custom_order_number = $open_order->get_meta('_alg_wc_full_custom_order_number');
                                if( !isset($custom_order_number) || empty($custom_order_number) ){
                                    $custom_order_number = $open_order->get_meta('_order_number');
                                }
                                if( $selected_orderid == $custom_order_number ){
                                    $picking_orders[] = $open_order;
                                }

                                $order_shipment_tracking_items = $open_order->get_meta('_wc_shipment_tracking_items');
                                if( isset($order_shipment_tracking_items[0]['tracking_number']) && $selected_orderid == $order_shipment_tracking_items[0]['tracking_number'] ){
                                    $picking_orders[] = $open_order;
                                }
                                elseif( isset($order_shipment_tracking_items['tracking_number']) && $selected_orderid == $order_shipment_tracking_items['tracking_number'] ){
                                    $picking_orders[] = $open_order;
                                }
                            }
                        }
                        // GET NEXT ORDER (zonder extra query)
                        elseif (isset($orderid) && strpos($orderid, 'takeover') === false) {
                            if ($next_order_found) {
                                $picking_orders[] = $open_order;
                                $next_order_found = false;
                            }

                            // Controleer of de huidige order overeenkomt met de $orderid
                            if ($picking_order_id == $orderid) {
                                $next_order_found = true; // Zet de vlag om de volgende order te selecteren
                            }
                        }
                        // TAKEOVER
                        elseif (isset($orderid) && strpos($orderid, 'takeover') !== false) {
                            $selected_orderid = str_replace('takeover_', '', $orderid);

                            // Save new picking user
                            if( $selected_orderid == $picking_order_id ){
                                $picking_orders[] = $open_order;

                                $open_order->update_meta_data('user_claimed', $appuser);
                                $open_order->save();
                            }
                        }
                        // DEFAULT
                        elseif( !isset($orderid) || empty($orderid) ){
                            $picking_orders[] = $open_order;
                        }

                        $batch_id = $open_order->get_meta('batch_id');
                        if ((isset($batch_id) && !empty($batch_id)) && (isset($user_claimed) && !empty($user_claimed) && $user_claimed == $appuser)) {
                            $ordersClaimed = true;
                        }

                        // Manual order assigning
                        if (isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
                            break;
                        }

                        $total_items = 0;
                        foreach ($open_order->get_items() as $item) {
                            $product_id = $item->get_product_id();
                            if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php') && !empty($product_id)) {
                                $product_info = wc_get_product($product_id);
                                $product_type = $product_info->get_type();
                                if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                    $total_items = $total_items + $item->get_quantity();
                                }
                            } else {
                                $total_items = $total_items + $item->get_quantity();
                            }
                        }

                        $lastname = substr($open_order->get_shipping_first_name(), 0, 1) . '. ' . $open_order->get_shipping_last_name();
                        if( strlen($lastname) < 3 ){
                            $lastname = substr($open_order->get_billing_first_name(), 0, 1) . '. ' . $open_order->get_billing_last_name();
                        }

                        $order_number = $picking_order_id;
                        $custom_order_number = $open_order->get_meta('_alg_wc_full_custom_order_number');
                        if( isset($custom_order_number) && !empty($custom_order_number) ){
                            $order_number = $custom_order_number;
                        }
                        else{
                            $custom_order_number = $open_order->get_meta('_order_number');
                            if( isset($custom_order_number) && !empty($custom_order_number) ){
                                $order_number = $custom_order_number;
                            }
                        }

                        $order_prefix = get_option('order_prefix');
                        if (isset($order_prefix) && !empty($order_prefix)) {
                            $order_number = $order_prefix . $order_number;
                        }

                        $custom_field = '';
                        $custom_field_label = '';
                        $deliveryDate = get_post_meta($picking_order_id, 'delivery_date', true);
                        if( empty($deliveryDate)) {
                            $deliveryDate = get_post_meta($picking_order_id, '_delivery_date', true);
                        }
                        if (!empty($deliveryDate)) {
                            $deliveryDate = strtotime($deliveryDate);
                            $custom_field_label = 'Delivery';
                            $custom_field = wp_date( 'm-d', $deliveryDate );
                        }

                        $is_pickup = 'no';
                        if (!empty($pickup_list_methods)) {
                            foreach ($open_order->get_shipping_methods() as $shipping_item) {
                                $method_id = $shipping_item->get_method_id();
                                $instance_id = $shipping_item->get_instance_id();
                                if (in_array($method_id.':'.$instance_id, $pickup_list_methods, true)) {
                                    $is_pickup = 'yes';
                                    break;
                                }
                            }
                        }

                        $is_delivery = 'no';
                        if (!empty($delivery_list_methods)) {
                            foreach ($open_order->get_shipping_methods() as $shipping_item) {
                                $method_id = $shipping_item->get_method_id();
                                $instance_id = $shipping_item->get_instance_id();
                                if (in_array($method_id.':'.$instance_id, $delivery_list_methods, true)) {
                                    $is_delivery = 'yes';
                                    break;
                                }
                            }
                        }

                        $order_date = substr($open_order->get_date_created(), 5, 5);
                        $order_date = apply_filters('orderpickingapp_order_date', $order_date, $open_order);

                        $order_data = array(
                            'orderid'               => $picking_order_id,
                            'order_number'          => $order_number,
                            'date'                  => $order_date,
                            'items'                 => $total_items,
                            'total'                 => $currency_symbol . ' ' . $open_order->get_total(),
                            'lastname'              => $lastname,
                            'shipping'              => $open_order->get_shipping_method(),
                            'claimed_by'            => $user_claimed,
                            'custom_field_label'    => $custom_field_label,
                            'custom_field'          => $custom_field,
                            'is_pickup'             => $is_pickup,
                            'is_delivery'           => $is_delivery,
                        );
                        $open_picking_orders[] = apply_filters('orderpickingapp_order_data', $order_data);

                        $total_picking_orders++;
                        break;

                    case 'packing':
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $total_backorders++;
                                break;
                            }
                        }
                        $total_packing_orders++;
                }
            }

            $user_order_claims = array();
            if (count($picking_orders) > 0) {

                if (!$ordersClaimed) {
                    $picking_batch++;
                    update_option('picking_batch', $picking_batch);
                }

                $total_orders = 0;
                $BatchBoxCharacter = 'A';
                foreach ($picking_orders as $shop_order) {
                    $shop_order_id = $shop_order->get_id();

                    if (isset($next_shop_order) && $shop_order_id <= $next_shop_order) {
                        continue;
                    }

                    // Custom function to return true/false
                    $skip_order = apply_filters('orderpickingapp_skip_picking_order', false, $shop_order_id);
                    if ($skip_order) {
                        continue;
                    }

                    if (!empty($appuser)) {
                        $user_claimed = $shop_order->get_meta('user_claimed');

                        // Manual order assigning
                        if( isset($manual_order_assigning) && $manual_order_assigning == 'yes' && $user_claimed != $appuser) {
                            continue;
                        }

                        // Check for open picking batch and batch picking user
                        if( $picking_amount > 1 && $ordersClaimed && $user_claimed != $appuser ){
                            continue;
                        }

                        $user_order_claims[] = array(
                            'orderid' => $shop_order_id,
                            'appuser' => ucfirst($user_claimed),
                        );
                        if (isset($user_claimed) && !empty($user_claimed) && $user_claimed != $appuser) {
                            continue;
                        }
                    }

                    if ($total_orders >= $picking_amount) {
                        break;
                    }

                    $order = $shop_order;
                    $currency_code = $order->get_currency();
                    $currency_symbol = get_woocommerce_currency_symbol($currency_code);
                    $currency_symbol = html_entity_decode($currency_symbol);
                    $order_weight = 0;
                    foreach ($order->get_items() as $item_id => $item) {

                        $picking_path               = '';
                        $product_picking_locations  = array();
                        $picking_location           = '';
                        $custom_product_field_label = '';
                        $custom_product_field       = '';

                        $title = $item->get_name();
                        $product_title = explode(" - ", $title, 2)[0];

                        // Check if product no longer exist in Woocommerce
                        $product_id = $item->get_product_id();
                        if (!isset($product_id) || empty($product_id)) {
                            $categories = array('Custom products');
                            $order_cat_id = '';
                            $thumbnail = '';

                            $description = 'Product don\'t exist in Woocommerce!';
                            $product_id = $item_id;
                            $sku = (string)$item_id;

                            $quantity = $item->get_quantity();
                            $total = $item->get_total();
                            if ($quantity > 0) {
                                $price = $total / $quantity;
                                $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
                            } else {
                                $price = '-';
                            }

                            $stock = '0';
                            $quantity = $item->get_quantity();
                        } else {

                            $categories = array();

                            // YOAST COMPATIBILITY
                            $primary_product_cat = get_post_meta($product_id, '_yoast_wpseo_primary_product_cat', true);
                            if (isset($primary_product_cat) && !empty($primary_product_cat)) {
                                $primary_term = get_term($primary_product_cat);

                                if (!empty($primary_term->parent)) {
                                    $categories[] = get_term($primary_term->parent)->name;
                                }

                                $categories[] = get_term($primary_product_cat)->name;
                            } else {
                                $categories = wp_get_post_terms($product_id, 'product_cat', array("orderby" => "parent"));

                                if (isset($categories) && !empty($categories)) {
                                    $categories = wp_list_pluck($categories, 'name');
                                }
                            }

                            $categoryHierarchy = array();
                            $this->productCategories = array();
                            $product_categories = get_the_terms( $product_id, 'product_cat' );
                            if (isset($product_categories) && is_array($product_categories)) {
                                $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
                            }
                            $order_cat_id = end($this->productCategories);
                            if (count($this->productCategories) > 2) {
                                $order_cat_id = $this->productCategories[1];
                            }

                            $product_picking_locations = wp_get_post_terms(
                                $product_id,
                                'pickingroute',
                                array(
                                    'orderby' => 'parent',
                                    'order'   => 'ASC',
                                )
                            );
                            if ( ! empty( $product_picking_locations ) && ! is_wp_error( $product_picking_locations ) ) {
                                $deepest_term   = null;
                                $deepest_depth  = -1;

                                foreach ( $product_picking_locations as $term ) {
                                    $depth = count( get_ancestors( $term->term_id, 'pickingroute', 'taxonomy' ) );

                                    if ( $depth > $deepest_depth ) {
                                        $deepest_depth = $depth;
                                        $deepest_term  = $term;
                                    }
                                }

                                if ( $deepest_term ) {
                                    $order_cat_id  = $deepest_term->term_id;
                                    $picking_path  = get_term_parents_list(
                                        $order_cat_id,
                                        'pickingroute',
                                        array(
                                            'separator' => ' / ',
                                            'link'      => false,
                                            'format'    => 'name',
                                        )
                                    );
                                    $picking_path = rtrim( $picking_path, ' / ' );
                                    $picking_location = $deepest_term->name;
                                }
                            }

                            $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');

                            $variation_id = $item->get_variation_id();

                            if (isset($variation_id) && !empty($variation_id)) {
                                $product_info = wc_get_product($variation_id);
                                $product_details = $product_info->get_data();
                                $product_id = $variation_id;
                                $product_parent_id = $product_details['parent_id'];

                                $orderpickingapp_picking_location = get_post_meta($product_id, 'orderpickingapp_picking_location', true);
                                if (!empty($orderpickingapp_picking_location)) {
                                    $order_cat_id = (int)$orderpickingapp_picking_location;
                                    $picking_path = get_term_parents_list($order_cat_id, 'pickingroute', array(
                                        'separator' => '/',
                                        'link' => false,
                                        'format' => 'name',
                                    ));
                                    if (!is_wp_error($picking_path)) {
                                        $picking_path = rtrim( $picking_path, '/' );
                                        $pos = strrpos($picking_path, '/');
                                        $picking_location = $pos === false ? $picking_path : substr($picking_path, $pos + 1);
                                    }
                                }

                                $sku = $product_details['sku'];
                                if (empty($sku)) {
                                    $sku = (string)get_post_meta($product_parent_id, '_sku', true);
                                }

                                if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
                                    $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
                                }

                                if (empty($sku)) {
                                    $sku = (string)$variation_id;
                                    $barcode = '';
                                } else {
                                    $barcode = $sku;
                                }
                            } else {
                                $product_info = wc_get_product($product_id);
                                $product_details = $product_info->get_data();
                                $product_id = $item->get_product_id();
                                $product_parent_id = $item->get_product_id();

                                $sku = $product_details['sku'];

                                if (empty($sku)) {
                                    $sku = (string)$product_id;
                                    $barcode = '';
                                } else {
                                    $barcode = $sku;
                                }
                            }

                            $description = $product_details['short_description'];

                            $price = $product_info->get_price();
                            if (isset($price) && !empty($price)) {
                                $price = (float)$product_info->get_price();
                                $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
                            } else {
                                $price = '-';
                            }

                            $stock = $product_info->get_stock_quantity();
                            $quantity = $item->get_quantity();
                            $weight = $product_info->get_weight();
                        }

                        $description = strip_tags($description, '<p><a><strong><i>');
                        $description = str_replace(array("\r", "\n"), '', $description);
                        if (strlen($description) > 200) {
                            $description = substr($description, 0, 200) . '...';
                        }

                        if (isset($product_info)) {
                            $product_type = $product_info->get_type();
                            if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                $custom_product_field_label = ucfirst($product_type);
                                $custom_product_field = $title;
                                continue;
                            }
                        }

                        $meta_description = '';
                        $item_meta = $item->get_all_formatted_meta_data('');
                        if ($item_meta) {
                            foreach ($item_meta as $meta_id => $meta) {
                                if (in_array($meta->key, array('_reduced_stock')) || str_contains($meta->key, 'pa_') || is_array($meta->value) || str_contains($meta->key, '_')) {
                                    continue;
                                }
                                $meta_description .= '<p><strong>' . $meta->display_key . '</strong>: ' . $meta->value . '</p>';
                            }
                        }

                        if (!empty($meta_description)) {
                            $description = $meta_description;
                        }

                        $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
                        if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
                            $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
                        }

                        $second_barcode = '';
                        $orderpickingapp_additional_barcode_field = get_option('orderpickingapp_additional_barcode_field');
                        if (isset($orderpickingapp_additional_barcode_field) && !empty($orderpickingapp_additional_barcode_field)) {
                            $second_barcode = get_post_meta($product_id, $orderpickingapp_additional_barcode_field, true);
                            if( empty($second_barcode) ) {
                                $second_barcode = get_post_meta($product_parent_id, $orderpickingapp_additional_barcode_field, true);
                            }
                        }

                        if (strpos($thumbnail, "?")) {
                            $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                        }
                        if (!isset($thumbnail) || empty($thumbnail)) {
                            $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                        }

                        // Fallback for product picking location
                        if (!isset($picking_path) || empty($picking_path)) {
                            $categories = implode(' / ', $categories);
                        } else {
                            $categories = $picking_path;
                        }

                        $orderpickingapp_location_field = get_option('orderpickingapp_location_field');
                        if (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
                            $categories = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
                        }

                        $identifier = $product_id;
                        $disable_product_combining = get_option('disable_product_combining');
                        if (isset($disable_product_combining) && $disable_product_combining == 'yes') {
                            $identifier = $item_id;
                        }

                        $weight = (int) round( wc_get_weight( (float) $weight, 'g' ) ); // van store-unit -> g
                        $order_weight += $weight * $quantity;

                        $product_data = array(
                            'product_id' => $identifier,
                            'title' => $title,
                            'product_title' => $product_title,
                            'thumbnail' => $thumbnail,
                            'description' => $description,
                            'sku' => $sku,
                            'barcode' => $barcode,
                            'second_barcode' => $second_barcode,
                            'price' => $price,
                            'stock' => $stock,
                            'weight' => $weight,
                            'quantity' => $quantity,
                            'backorder' => 0,
                            'type' => $product_type,
                            'order_cat' => $order_cat_id,
                            'categories' => $categories,
                            'picking_path' => $picking_path,
                            'picking_location' => $picking_location,
                            'total_picking_orders' => $total_picking_orders,
                            'total_packing_orders' => $total_packing_orders,
                            'total_backorders' => $total_backorders,
                            'custom_field_label' => '',
                            'custom_field' => '',
                        );

                        // Weight Products for WooCommerce
                        $is_weight = $item->get_meta('_wcwp_is_weight_product');
                        if ($is_weight === 'yes') {
                            $product_data['weight_unit_label']      = $item->get_meta('_wcwp_order_unit_label');
                            $product_data['estimated_weight']       = (float) $item->get_meta('_wcwp_estimated_weight');
                            $product_data['weight_pricing_unit']    = $item->get_meta('_wcwp_pricing_unit');
                        }

                        $product_data = apply_filters('orderpickingapp_product_data', $product_data, $item);

                        $custom_product_field_label = apply_filters('orderpickingapp_custom_product_field_label', $custom_product_field_label, $product_id, $item_id);
                        $custom_product_field = apply_filters('orderpickingapp_custom_product_field', $custom_product_field, $product_id, $item_id);

                        if (isset($custom_product_field_label) && !empty($custom_product_field_label)) {
                            $product_data['custom_field_label'] = $custom_product_field_label;
                            $product_data['custom_field'] = $custom_product_field;
                        } elseif (isset($orderpickingapp_location_field) && !empty($orderpickingapp_location_field)) {
                            $product_data['custom_field_label'] = ucfirst(str_replace('_', '', $orderpickingapp_location_field));
                            $product_data['custom_field'] = get_post_meta($product_parent_id, $orderpickingapp_location_field, true);
                        }

                        $product_data['box_amount'] =  '';
                        $orderpickingapp_additional_box_amount_field = get_option('orderpickingapp_additional_box_amount_field');
                        if (isset($orderpickingapp_additional_box_amount_field) && !empty($orderpickingapp_additional_box_amount_field)) {
                            $product_data['box_amount'] =  get_post_meta($product_id, $orderpickingapp_additional_box_amount_field, true);
                        }

                        if (!isset($Products[$identifier]['ordered'])) {
                            $product_data['ordered'] = $item->get_quantity();
                        } else {
                            $Products[$identifier]['ordered'] = $Products[$identifier]['ordered'] + $item->get_quantity();
                        }

                        if (!isset($Products[$identifier]['unpicked'])) {
                            $product_data['unpicked'] = $item->get_quantity();
                        } else {
                            $Products[$identifier]['unpicked'] = $Products[$identifier]['unpicked'] + $item->get_quantity();
                        }

                        if (empty($product_data['stock'])) {
                            $_backorders = $item->get_meta('_backorders');
                            if ($_backorders == 'yes') {
                                $product_data['stock'] = '0';
                            } else {
                                $product_data['stock'] = $item->get_quantity();
                            }
                        } else {
                            $product_data['stock'] = $product_data['stock'] + $item->get_quantity();
                        }

                        if (isset($Products[$identifier])) {
                            if (isset($Products[$identifier]['quantity'])) {
                                $Products[$identifier]['quantity'] += $product_data['quantity'];
                            } else {
                                $Products[$identifier] = array(
                                    'quantity' => $product_data['quantity']
                                );
                            }
                        } else {
                            $Products[$identifier] = $product_data;
                        }

                        if (!isset($Products[$identifier]['orders_list'])) {
                            $Products[$identifier]['orders_list'] = '';
                        }

                        $custom_field = apply_filters('orderpickingapp_custom_order_field', '', $shop_order_id);

                        $total_items = $order->get_item_count();
                        if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                            $total_items = 0;
                            foreach ($order->get_items() as $item) {
                                $temp_product_id = $item->get_product_id();
                                if (!empty($temp_product_id)) {
                                    $product_info = wc_get_product($temp_product_id);
                                    $product_type = $product_info->get_type();
                                    if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                        $total_items++;
                                    }
                                }
                            }
                        }

                        $customer_note = $order->get_customer_note();
                        $customer_note = apply_filters('orderpickingapp_order_note', $customer_note, $shop_order_id);

                        if (!isset($Products[$identifier]['orders_list'])) {
                            $Products[$identifier] = array(
                                'orders_list' => '#' . $shop_order_id . ' '
                            );
                        } else {
                            $Products[$identifier]['orders_list'] .= '#' . $shop_order_id . ' ';
                        }

                        // Add all open picking orders to our product data
                        $Products[$identifier]['open_picking_orders'] = $open_picking_orders;

                        $BatchID = $order->get_meta('batch_id');
                        if (!isset($BatchID) || empty($BatchID)) {
                            $BatchID = $BatchBoxCharacter . '-' . $picking_batch;
                        }

                        $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
                        $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
                        if( strlen($lastname) < 3 ){
                            $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
                            $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
                        }

                        $order_number = $shop_order_id;
                        $custom_order_number = $order->get_meta('_alg_wc_full_custom_order_number');
                        if( isset($custom_order_number) && !empty($custom_order_number) ){
                            $order_number = $custom_order_number;
                        }
                        else{
                            $custom_order_number = $order->get_meta('_order_number');
                            if( isset($custom_order_number) && !empty($custom_order_number) ){
                                $order_number = $custom_order_number;
                            }
                        }

                        $order_prefix = get_option('order_prefix');
                        if (isset($order_prefix) && !empty($order_prefix)) {
                            $order_number = $order_prefix . $order_number;
                        }

                        $order_date = substr($order->get_date_created(), 5, 5);
                        $order_date = apply_filters('orderpickingapp_order_date', $order_date, $order);

                        $Products[$identifier]['orders'][] = array(
                            'orderid' => $shop_order_id,
                            'order_number' => $order_number,
                            'date' 					=> $order_date,
                            'items' 				=> $total_items,
                            'product_items' => $item->get_quantity(),
                            'total' => $currency_symbol . ' ' . $order->get_total(),
                            'weight' => $order_weight,
                            'fullname' => $fullname,
                            'lastname' => $lastname,
                            'shipping' => $order->get_shipping_method(),
                            'order_note' => $customer_note,
                            'custom_field' => $custom_field,
                            'batch_id' => $BatchID,
                            'batch_number' => preg_replace("/[^0-9]/", '', $BatchID),
                            'claimed_by' => $order->get_meta('user_claimed'),
                        );
                    }


                    // Set user claim
                    if (!empty($appuser)) {
                        $Order = wc_get_order($shop_order_id);
                        $Order->update_meta_data('claimed', 'true');

                        // Manual order assigning
                        if (!isset($manual_order_assigning) || $manual_order_assigning != 'yes') {
                            $Order->update_meta_data('user_claimed', $appuser);
                        }
                        $Order->update_meta_data('picking_status', 'picking');
                        $Order->update_meta_data('batch_id', $BatchBoxCharacter . '-' . $picking_batch);
                        $Order->add_order_note('Order Picking App | Order picking started by user: ' . $appuser);

                        $picking_order_status = get_option('picking_order_status');
                        if( !empty($picking_order_status) ) {
                            $picking_order_status = str_replace('wc-', '', $picking_order_status);
                            $Order->update_status($picking_order_status, 'Order Picking App | Status changed');
                        }

                        $Order->save();
                        $total_orders++;

                        $BatchBoxCharacter = chr(ord($BatchBoxCharacter) + 1);
                    }
                }
            }
        }

        $this->log('Retrieving open Woocommerce orders with total amount of ' . count($Products), 'Info');

        if (isset($Products) && !empty($Products)) {
            wp_send_json(array_values($Products), 200);
        } elseif (isset($user_order_claims) && !empty($user_order_claims)) {
            wp_send_json($user_order_claims, 200);
        }
        if( isset($orderid) && strpos($orderid, 'find_') !== false && empty($picking_orders)) {
            wp_send_json([]);
        }
        else {
            wp_send_json(array(
                'total_picking_orders' => $total_picking_orders,
                'total_packing_orders' => $total_packing_orders,
                'total_backorders' => $total_backorders,
            ), 200);
        }
    }

    public
    function getPickingList($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $status = $request->get_param('status');
        $all_open_orders = $this->getAllPickingOrders();

        if( count($all_open_orders) > 0 ) {
            foreach ($all_open_orders as $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor sitiatie met otrder gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && ( !isset($user_claimed) || empty($user_claimed) ) ){
                    $picking_status = 'picking';

                    $picking_order_status = get_option('picking_order_status');
                    if( !empty($picking_order_status) ) {
                        $picking_order_status = str_replace('wc-', '', $picking_order_status);
                        $open_order->update_status($picking_order_status, 'Order Picking App | Status changed');
                    }
                }

                if( isset($status) && $status == 'backorders' ){

                    if( $picking_status == 'packing' || $picking_status == 'backorders' ){

                        $contains_backorder_products = false;
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $contains_backorder_products = true;
                                break;
                            }
                        }

                        if( !$contains_backorder_products ){
                            continue;
                        }
                    }
                    else{
                        continue;
                    }
                }
                elseif( $picking_status == 'picking' || $status == 'all' || $status == 'summary' ){
                    // GO ON
                }
                else{
                    continue;
                }

                $contains_backorder_products = false;

                $currency_code = $open_order->get_currency();
                $currency_symbol = get_woocommerce_currency_symbol($currency_code);
                $currency_symbol = html_entity_decode($currency_symbol);

                $order_id = $open_order->get_id();

                $total_items = $open_order->get_item_count();
                if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                    $total_items = 0;
                    foreach ($open_order->get_items() as $item_id => $item) {
                        $product_id = $item->get_product_id();
                        $product_info = wc_get_product($product_id);
                        $product_type = $product_info->get_type();
                        if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                            $total_items++;
                        }
                    }
                }

                $lastname = substr($open_order->get_shipping_first_name(), 0, 1) . '. ' . $open_order->get_shipping_last_name();
                if( strlen($lastname) < 3 ){
                    $lastname = substr($open_order->get_billing_first_name(), 0, 1) . '. ' . $open_order->get_billing_last_name();
                }

                $customer_note = $open_order->get_customer_note();
                $customer_note = apply_filters('orderpickingapp_order_note', $customer_note, $order_id);

                $custom_field = apply_filters('orderpickingapp_custom_order_field', '', $order_id);

                $order_number = $order_id;
                $custom_order_number = $open_order->get_meta('_alg_wc_full_custom_order_number');
                if( isset($custom_order_number) && !empty($custom_order_number) ){
                    $order_number = $custom_order_number;
                }
                else{
                    $custom_order_number = $open_order->get_meta('_order_number');
                    if( isset($custom_order_number) && !empty($custom_order_number) ){
                        $order_number = $custom_order_number;
                    }
                }

                $order_prefix = get_option('order_prefix');
                if (isset($order_prefix) && !empty($order_prefix)) {
                    $order_number = $order_prefix . $order_number;
                }

                $order_datetime = str_replace('T', ' ', substr($open_order->get_date_created(), 0, 16));
                $order_datetime = apply_filters('orderpickingapp_order_datetime', $order_datetime, $open_order);

                $output[$order_id] = array(
                    'orderid' => $order_id,
                    'order_number' => $order_number,
                    'date' => $order_datetime,
                    'items' => $total_items,
                    'total' => $currency_symbol . ' ' . $open_order->get_total(),
                    'lastname' => $lastname,
                    'notes' => $customer_note,
                    'custom_field' => $custom_field,
                    'status'        => $picking_status,
                );

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

                    $product_id = $item->get_product_id();
                    if( empty($product_id) ){
                        continue;
                    }

                    // Skip none backorder items
                    if (isset($status) && $status == 'backorders') {
                        $backorder = $item->get_meta('backorder');
                        if ($backorder !== '0' && !empty($backorder)) {
                            $contains_backorder_products = true;
                        } else {
                            continue;
                        }
                    }

                    if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                        $product_info = wc_get_product($product_id);
                        $product_type = $product_info->get_type();
                        if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                            continue;
                        }
                    }

                    $title = $item->get_name();
                    $product_title = explode(" - ", $title, 2)[0];

                    $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');

                    $variation_id = $item->get_variation_id();
                    if (isset($variation_id) && !empty($variation_id)) {
                        $product_info = wc_get_product($variation_id);
                        $product_details = $product_info->get_data();

                        if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
                            $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
                        }

                        if (strpos($thumbnail, "?")) {
                            $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                        }
                        if (!isset($thumbnail) || empty($thumbnail)) {
                            $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                        }

                        $product_data = array(
                            'title' => $title,
                            'product_title' => $product_title,
                            'thumbnail' => $thumbnail,
                            'quantity' => $item->get_quantity(),
                        );
                    } else {
                        $product_info = wc_get_product($product_id);
                        if (strpos($thumbnail, "?")) {
                            $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                        }
                        if (!isset($thumbnail) || empty($thumbnail)) {
                            $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                        }

                        $product_data = array(
                            'title' => $title,
                            'product_title' => $product_title,
                            'thumbnail' => $thumbnail,
                            'quantity' => $item->get_quantity(),
                        );
                    }

                    $product_data['stock'] = $product_info->get_stock_quantity();

                    $variation_id = $item->get_variation_id();
                    if (isset($variation_id) && !empty($variation_id)) {
                        $product_info = wc_get_product($variation_id);
                        $product_details = $product_info->get_data();
                        $product_data['product_id'] = $variation_id;
                        $product_id = $variation_id;

                        $sku = $product_details['sku'];
                        if (empty($sku)) {
                            $sku = (string)get_post_meta($product_details['parent_id'], '_sku', true);
                        }

                        if (!empty($product_details['short_description'])) {
                            $product_data['description'] = $product_details['short_description'];
                        } else {
                            $product_data['description'] = $product_details['description'];
                        }


                        $product_data['sku'] = $sku;
                        $product_data['price'] = get_post_meta($product_id, '_price', true);

                        if (empty($product_data['sku'])) {
                            $product_data['sku'] = $variation_id;
                        }
                    } elseif (isset($product_id) && !empty($product_id)) {
                        $product_info = wc_get_product($product_id);
                        $product_details = $product_info->get_data();
                        $product_id = $item->get_product_id();
                        $product_data['product_id'] = $product_id;

                        $sku = $product_details['sku'];
                        if (empty($sku)) {
                            $sku = (string)get_post_meta($product_id, '_sku', true);
                        }

                        if (!empty($product_details['short_description'])) {
                            $product_data['description'] = $product_details['short_description'];
                        } else {
                            $product_data['description'] = $product_details['description'];
                        }

                        $product_data['sku'] = $sku;
                        $product_data['price'] = get_post_meta($product_id, '_price', true);

                        if (empty($product_data['sku'])) {
                            $product_data['sku'] = $product_id;
                        }
                    } else {
                        $product_data['product_id'] = $item_id;
                        $product_data['description'] = 'Product don\'t exist in Woocommerce!';
                        $product_data['sku'] = $item_id;

                        $price = $item->get_total() / $item->get_quantity();
                        if (isset($price) && !empty($price)) {
                            $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
                        } else {
                            $price = '-';
                        }
                        $product_data['price'] = $price;

                        if (empty($product_data['sku'])) {
                            $product_data['sku'] = $product_data['product_id'];
                        }
                    }

                    $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
                    $barcode = $sku;
                    if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
                        $ean_barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
                        if( !empty($ean_barcode) ){
                            $barcode = $ean_barcode;
                        }
                    }
                    $product_data['barcode'] = $barcode;

                    $product_data['second_barcode'] =  '';
                    $orderpickingapp_additional_barcode_field = get_option('orderpickingapp_additional_barcode_field');
                    if (isset($orderpickingapp_additional_barcode_field) && !empty($orderpickingapp_additional_barcode_field)) {
                        $product_data['second_barcode'] =  get_post_meta($product_id, $orderpickingapp_additional_barcode_field, true);
                    }

                    $product_data['box_amount'] =  '';
                    $orderpickingapp_additional_box_amount_field = get_option('orderpickingapp_additional_box_amount_field');
                    if (isset($orderpickingapp_additional_box_amount_field) && !empty($orderpickingapp_additional_box_amount_field)) {
                        $product_data['box_amount'] =  get_post_meta($product_id, $orderpickingapp_additional_box_amount_field, true);
                    }

                    $output[$order_id]['products'][] = $product_data;
                }

                // Remove orders without any backorder products
                if (isset($status) && $status == 'backorders' && !$contains_backorder_products) {
                    unset($output[$order_id]);
                }
            }
        }

        if (isset($output) && !empty($output)) {
            wp_send_json(array_values($output), 200);
        } else {
            wp_send_json(array(), 200);
        }
    }

    public
    function requestPackingOrders()
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $output = $this->getPackingOrders();
        wp_send_json($output, 200);
    }

    public
    function requestPickupOrders()
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $output = $this->getPackingOrders('pickup');
        wp_send_json($output, 200);
    }

    public
    function requestDeliveryOrders($request)
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $output = $this->getPackingOrders('delivery');
        wp_send_json($output,200);
    }

    public
    function getPackingOrders( $type = 'packing' )
    {

        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        $all_open_orders = $this->getAllPickingOrders();

        $total_picking_orders = 0;
        $total_packing_orders = 0;
        $total_backorders = 0;
        $total_pickup_orders = 0;
        $total_delivery_orders = 0;
        if( count($all_open_orders) > 0 ) {

            $pickup_list_methods = (array)get_option('pickup_list_method', []);
            $delivery_list_methods = (array)get_option('delivery_list_method', []);

            // COunt totals
            foreach ($all_open_orders as $order_index => $open_order) {
                $picking_status = $open_order->get_meta('picking_status');

                // Fallback voor situatie met order gemarkeerd als 'completed' maar nog niet gepickt
                $user_claimed = $open_order->get_meta('user_claimed');
                if( $picking_status == 'completed' && (!isset($user_claimed) || empty($user_claimed)) ){
                    $picking_status = 'picking';
                }

                switch ($picking_status) {

                    case 'picking':
                        $total_picking_orders++;
                        unset($all_open_orders[$order_index]);
                        break;

                    case '':
                        $total_picking_orders++;
                        unset($all_open_orders[$order_index]);
                        break;

                    case 'packing':
                        foreach ($open_order->get_items() as $item_id => $item) {
                            $backorder = $item->get_meta('backorder');
                            if ($backorder !== '0' && !empty($backorder)) {
                                $total_backorders++;
                                break;
                            }
                        }
                        $total_packing_orders++;
                        if( $type != 'packing' ) {
                            unset($all_open_orders[$order_index]);
                        }
                        break;

                    case 'pickup':
                        $total_pickup_orders++;
                        if( $type != 'pickup' ) {
                            unset($all_open_orders[$order_index]);
                        }
                        break;

                    case 'delivery':
                        $total_delivery_orders++;
                        if( $type != 'delivery' ) {
                            unset($all_open_orders[$order_index]);
                        }
                        break;

                    default:
                        unset($all_open_orders[$order_index]);
                }
            }

            $output = array();
            if( count($all_open_orders) > 0 ) {
                foreach ($all_open_orders as $open_order) {

                    $order = $open_order;
                    $packing_order_id = $order->get_id();

                    $customer_note = $order->get_customer_note();
                    $customer_note = apply_filters('orderpickingapp_order_note', $customer_note, $packing_order_id);

                    $total_items = $order->get_item_count();
                    if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                        $total_items = 0;
                        foreach ($order->get_items() as $item_id => $item) {
                            $product_id = $item->get_product_id();
                            $product_info = wc_get_product($product_id);
                            $product_type = $product_info->get_type();
                            if (!in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                $total_items++;
                            }
                        }
                    }

                    $fullname = $order->get_shipping_first_name() . ' ' . $order->get_shipping_last_name();
                    $lastname = substr($order->get_shipping_first_name(), 0, 1) . '. ' . $order->get_shipping_last_name();
                    if( strlen($lastname) < 3 ){
                        $fullname = $order->get_billing_first_name() . ' ' . $order->get_billing_last_name();
                        $lastname = substr($order->get_billing_first_name(), 0, 1) . '. ' . $order->get_billing_last_name();
                    }

                    $custom_field = apply_filters('orderpickingapp_custom_order_field', '', $packing_order_id);

                    $order_number = $packing_order_id;
                    $custom_order_number = $order->get_meta('_alg_wc_full_custom_order_number');
                    if( isset($custom_order_number) && !empty($custom_order_number) ){
                        $order_number = $custom_order_number;
                    }
                    else{
                        $custom_order_number = $order->get_meta('_order_number');
                        if( isset($custom_order_number) && !empty($custom_order_number) ){
                            $order_number = $custom_order_number;
                        }
                    }

                    $order_prefix = get_option('order_prefix');
                    if (isset($order_prefix) && !empty($order_prefix)) {
                        $order_number = $order_prefix . $order_number;
                    }

                    $ordernote = $order->get_meta('ordernote');
                    if (empty($custom_field)) {
                        $custom_field = $ordernote;
                    }

                    $is_pickup = 'no';
                    if (!empty($pickup_list_methods)) {
                        foreach ($open_order->get_shipping_methods() as $shipping_item) {
                            $method_id = $shipping_item->get_method_id();
                            $instance_id = $shipping_item->get_instance_id();
                            if (in_array($method_id.':'.$instance_id, $pickup_list_methods, true)) {
                                $is_pickup = 'yes';
                                break;
                            }
                        }
                    }

                    $is_delivery = 'no';
                    if (!empty($delivery_list_methods)) {
                        foreach ($open_order->get_shipping_methods() as $shipping_item) {
                            $method_id = $shipping_item->get_method_id();
                            $instance_id = $shipping_item->get_instance_id();
                            if (in_array($method_id.':'.$instance_id, $delivery_list_methods, true)) {
                                $is_delivery = 'yes';
                                break;
                            }
                        }
                    }

                    $order_datetime = str_replace('T', ' ', substr($order->get_date_created(), 0, 16));
                    $order_datetime = apply_filters('orderpickingapp_order_datetime', $order_datetime, $order);

                    $order_data = array(
                        'orderid' => $packing_order_id,
                        'order_number' => $order_number,
                        'datetime' => $order_datetime,
                        'date' => substr($order_datetime, 5, 5),
                        'items' => $total_items,
                        'shipping' => $order->get_shipping_method(),
                        'total' => $currency_symbol . ' ' . $order->get_total(),
                        'notes' => $customer_note,
                        'fullname' => $fullname,
                        'lastname' => $lastname,
                        'onbackorder' => 'false',
                        'batch_id' => $order->get_meta('batch_id'),
                        'total_packing_orders' => $total_packing_orders,
                        'total_picking_orders' => $total_picking_orders,
                        'total_backorders' => $total_backorders,
                        'total_pickup_orders' => $total_pickup_orders,
                        'total_delivery_orders' => $total_delivery_orders,
                        'custom_field' => $custom_field,
                        'ordernote' => $ordernote,
                        'is_pickup'             => $is_pickup,
                        'is_delivery'           => $is_delivery,
                    );
                    $output[$packing_order_id] = apply_filters('orderpickingapp_order_data', $order_data);

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

                        $product_id = $item->get_product_id();

                        if (is_plugin_active('woocommerce-product-bundles/woocommerce-product-bundles.php')) {
                            $product_info = wc_get_product($product_id);
                            $product_type = $product_info->get_type();
                            if (in_array($product_type, array('woosb', 'bundle', 'grouped'))) {
                                continue;
                            }
                        }

                        $title = $item->get_name();
                        $product_title = explode(" - ", $title, 2)[0];

                        $thumbnail = get_the_post_thumbnail_url($product_id, 'medium');

                        $variation_id = $item->get_variation_id();
                        if (isset($variation_id) && !empty($variation_id)) {
                            $product_info = wc_get_product($variation_id);
                            $product_details = $product_info->get_data();

                            if (isset($product_details['image_id']) && !empty($product_details['image_id'])) {
                                $thumbnail = wp_get_attachment_image_url($product_details['image_id']);
                            }

                            if (strpos($thumbnail, "?")) {
                                $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                            }
                            if (!isset($thumbnail) || empty($thumbnail)) {
                                $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                            }

                            $product_data = array(
                                'title'         => $title,
                                'product_title' => $product_title,
                                'thumbnail'     => $thumbnail,
                                'quantity'      => $item->get_quantity(),
                                'status'        => $item->get_meta('picking_status'),
                                'backorder'     => (int)$item->get_meta('backorder'),
                            );
                        } else {


                            if (strpos($thumbnail, "?")) {
                                $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                            }
                            if (!isset($thumbnail) || empty($thumbnail)) {
                                $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                            }

                            $product_data = array(
                                'title'         => $title,
                                'product_title' => $product_title,
                                'thumbnail'     => $thumbnail,
                                'quantity'      => $item->get_quantity(),
                                'status'        => $item->get_meta('picking_status'),
                                'backorder'     => (int)$item->get_meta('backorder'),
                            );
                        }

                        if ($product_data['backorder'] !== '0' && !empty($product_data['backorder'])) {
                            $output[$packing_order_id]['onbackorder'] = 'true';
                        }

                        $variation_id = $item->get_variation_id();
                        if (isset($variation_id) && !empty($variation_id)) {
                            $product_info = wc_get_product($variation_id);
                            $product_details = $product_info->get_data();
                            $product_data['product_id'] = $variation_id;
                            $product_id = $variation_id;

                            $sku = $product_details['sku'];
                            if (empty($sku)) {
                                $sku = (string)get_post_meta($product_details['parent_id'], '_sku', true);
                            }

                            if (!empty($product_details['short_description'])) {
                                $product_data['description'] = $product_details['short_description'];
                            } else {
                                $product_data['description'] = $product_details['description'];
                            }


                            $product_data['sku'] = $sku;
                            $product_data['price'] = get_post_meta($product_id, '_price', true);
                            $product_data['stock'] = $product_info->get_stock_quantity();
                            $product_data['weight'] = $product_info->get_weight();

                            if (empty($product_data['sku'])) {
                                $product_data['sku'] = $variation_id;
                            }
                        } elseif (isset($product_id) && !empty($product_id)) {
                            $product_info = wc_get_product($product_id);
                            $product_details = $product_info->get_data();
                            $product_id = $item->get_product_id();
                            $product_data['product_id'] = $product_id;

                            $sku = $product_details['sku'];
                            if (empty($sku)) {
                                $sku = (string)get_post_meta($product_id, '_sku', true);
                            }

                            if (!empty($product_details['short_description'])) {
                                $product_data['description'] = $product_details['short_description'];
                            } else {
                                $product_data['description'] = $product_details['description'];
                            }

                            $product_data['sku'] = $sku;
                            $product_data['price'] = get_post_meta($product_id, '_price', true);
                            $product_data['stock'] = $product_info->get_stock_quantity();
                            $product_data['weight'] = $product_info->get_weight();

                            if (empty($product_data['sku'])) {
                                $product_data['sku'] = $product_id;
                            }
                        } else {
                            $product_data['product_id'] = $item_id;
                            $product_data['description'] = 'Product don\'t exist in Woocommerce!';
                            $product_data['sku'] = $item_id;

                            $price = $item->get_total() / $item->get_quantity();
                            if (isset($price) && !empty($price)) {
                                $price = $currency_symbol . ' ' . number_format($price, 2, ",", ".");
                            } else {
                                $price = '-';
                            }
                            $product_data['price'] = $price;
                            $product_data['stock'] = $item->get_quantity();

                            if (empty($product_data['sku'])) {
                                $product_data['sku'] = $product_data['product_id'];
                            }
                        }

                        $product_data['description'] = strip_tags($product_data['description'], '<p><a><strong><i>');
                        $product_data['description'] = str_replace(array("\r", "\n"), '', $product_data['description']);
                        if (strlen($product_data['description']) > 300) {
                            $product_data['description'] = substr($product_data['description'], 0, 300) . '...';
                        }

                        // Niet aanwezig in Woocommerce
                        $product_data['product_reference'] = '';
                        $product_data['reference'] = '';

                        if (empty($product_data['stock'])) {
                            $_backorders = $item->get_meta('_backorders');
                            if ($_backorders == 'yes') {
                                $product_data['stock'] = '0';
                            } else {
                                $product_data['stock'] = $item->get_quantity();
                            }
                        }

                        $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
                        $barcode = $sku;
                        if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
                            $ean_barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
                            if( !empty($ean_barcode) ){
                                $barcode = $ean_barcode;
                            }
                        }
                        $product_data['barcode'] = $barcode;

                        $product_data['second_barcode'] =  '';
                        $orderpickingapp_additional_barcode_field = get_option('orderpickingapp_additional_barcode_field');
                        if (isset($orderpickingapp_additional_barcode_field) && !empty($orderpickingapp_additional_barcode_field)) {
                            $product_data['second_barcode'] =  get_post_meta($product_id, $orderpickingapp_additional_barcode_field, true);
                        }

                        $product_data['box_amount'] =  '';
                        $orderpickingapp_additional_box_amount_field = get_option('orderpickingapp_additional_box_amount_field');
                        if (isset($orderpickingapp_additional_box_amount_field) && !empty($orderpickingapp_additional_box_amount_field)) {
                            $product_data['box_amount'] =  get_post_meta($product_id, $orderpickingapp_additional_box_amount_field, true);
                        }

                        $identifier = $product_id;
                        $disable_product_combining = get_option('disable_product_combining');
                        if (isset($disable_product_combining) && $disable_product_combining == 'yes') {
                            $identifier = $item_id;
                        }

                        $product_data = apply_filters('orderpickingapp_product_data', $product_data, $item);

                        if (isset($output[$packing_order_id]['products'][$identifier]['quantity'])) {
                            $output[$packing_order_id]['products'][$identifier]['quantity'] += $product_data['quantity'];
                        }
                        else {
                            $output[$packing_order_id]['products'][$identifier] = $product_data;
                        }

                        $output[$packing_order_id]['products'][$identifier]['ordered'] = $output[$packing_order_id]['products'][$identifier]['quantity'];
                        $output[$packing_order_id]['products'][$identifier]['unpacked'] = $output[$packing_order_id]['products'][$identifier]['quantity'];
                    }
                }
            }
        }

        if (empty($output)) {
            $output = array(
                array(
                    'total_picking_orders'  => $total_picking_orders,
                    'total_packing_orders'  => $total_packing_orders,
                    'total_backorders'      => $total_backorders,
                    'total_pickup_orders'   => $total_pickup_orders,
                    'total_delivery_orders' => $total_delivery_orders,
                ),
            );
        }

        return $output;
    }

    public
    function log( $Message, $Type = 'Info' )
    {
        if ( empty( self::$logPath ) || ! is_dir( self::$logPath ) ) {
            return;
        }

        $log_file = trailingslashit( self::$logPath ) . wp_date( 'Y-m-d' ) . '.log';
        $line     = wp_date( 'd-m-Y H:i:s' ) . " | " . str_pad( sanitize_text_field( $Type ), 8, " ", STR_PAD_RIGHT ) . " | " . sanitize_text_field( $Message ) . "
";

        // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_file_put_contents -- Local append-only plugin log file in uploads directory.
        file_put_contents( $log_file, $line, FILE_APPEND | LOCK_EX );
    }

    public
    function getCategories($output = 'json', $taxonomy = 'product_cat')
    {

        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $categories = get_terms(
            array(
                'taxonomy'   => $taxonomy,
                'hide_empty' => false,
            )
        );
        $categoryHierarchy = array();

        if (isset($categories) && !empty($categories)) {
            $this->sort_terms_hierarchically($categories, $categoryHierarchy);
        }

        if ( 'json' === $output ) {
            wp_send_json( $this->orderedCategories );
        }
        return $this->orderedCategories;
    }

    public
    function sort_terms_hierarchically(array &$cats, array &$into, $parentId = 0)
    {
        foreach ($cats as $i => $cat) {
            if ($cat->parent == $parentId) {
                $into[$cat->term_id] = $cat;
                if ($parentId == 0) {
                    $this->orderedCategories[$cat->term_id]['name'] = $cat->name;
                    $this->orderedCategories[$cat->term_id]['count'] = $cat->count;
                    $this->orderedCategories[$cat->term_id]['children'] = array();
                    $this->productCategories[] = $cat->term_id;
                } else {
                    $this->orderedCategories[$parentId]['children'][$cat->term_id] = $cat->name;
                    $this->productCategories[] = $cat->term_id;
                }
                unset($cats[$i]);
            }
        }

        foreach ($into as $topCat) {
            $topCat->children = array();
            $this->sort_terms_hierarchically($cats, $topCat->children, $topCat->term_id);
        }
    }

    public
    function getProduct($request)
    {
        header('Access-Control-Allow-Origin: *');
        header("Access-Control-Allow-Methods: GET");

        $searchterm = $request->get_param('searchterm');

        $currency_symbol = get_woocommerce_currency_symbol();
        $currency_symbol = html_entity_decode($currency_symbol);

        // Search by sku
        $args = array(
            'post_type' => array('product', 'product_variation'),
            'post_status' => 'any',
            'posts_per_page' => -1,
            'meta_query' => array(
                'relation' => 'OR',
                array(
                    'key' => '_sku',
                    'value' => $searchterm
                ),
            ),
            'fields' => 'ids'
        );

        // Search by custom EAN field
        $orderpickingapp_ean_field = get_option('orderpickingapp_ean_field');
        if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field) && $orderpickingapp_ean_field != '_sku' ){
            $args['meta_query'][] = array(
                'key' => $orderpickingapp_ean_field,
                'value' => $searchterm
            );
        }
        $product_query = new WP_Query($args);
        $product_ids = $product_query->posts;

        // Search by product/variation id
        if (empty($product_ids)) {
            $args = array(
                'post_type' => array('product', 'product_variation'),
                'post_status' => 'any',
                'posts_per_page' => 1,
                'post__in' => (array)$searchterm,
                'fields' => 'ids'
            );
            $product_query = new WP_Query($args);
            $product_ids = $product_query->posts;
        }

        // Search by title
        if (empty($product_ids)) {
            $args = array(
                's' => $searchterm,
                'post_type' => array('product', 'product_variation'),
                'post_status' => 'any',
                'posts_per_page' => -1,
                'fields' => 'ids'
            );
            $product_query = new WP_Query($args);
            $product_ids = $product_query->posts;
        }

        $Products = array();
        $product_variations_amount = 0;
        if (isset($product_ids[0])) {
            foreach ($product_ids as $product_id) {

                $product_info = wc_get_product($product_id);

                $allocated_qty = $this->get_allocated_qty_for_product($product_info);

                $main_product_id = $product_id;
                $parent_id = $product_info->get_parent_id();
                if( $parent_id !== 0 ){
                    $main_product_id = $parent_id;
                }
                else{

                    // Skip variable parent/main product
                    $product_variations = (array)$product_info->get_children();
                    $product_variations_amount = count($product_variations);
                    if( $product_info->get_type() == 'variable' ) {

                        if( $product_variations_amount == 1 ) {
                            $product_id = $product_variations[0];
                            $product_info = wc_get_product($product_id);

                            if( empty($allocated_qty) ){
                                $allocated_qty = $this->get_allocated_qty_for_product($product_info);
                            }
                        }
                    }
                }

                $product_details = $product_info->get_data();

                $title = $product_info->get_name();

                // YOAST COMPATIBILITY
                $primary_product_cat = get_post_meta($main_product_id, '_yoast_wpseo_primary_product_cat', true);
                if (isset($primary_product_cat) && !empty($primary_product_cat)) {
                    $primary_term = get_term($primary_product_cat);

                    if (!empty($primary_term->parent)) {
                        $categories[] = get_term($primary_term->parent)->name;
                    }

                    $categories[] = get_term($primary_product_cat)->name;
                } else {
                    $categories = wp_get_post_terms($main_product_id, 'product_cat', array("orderby" => "parent"));

                    if (isset($categories) && !empty($categories)) {
                        $categories = wp_list_pluck($categories, 'name');
                    } else {
                        $categories = array();
                    }
                }

                $categoryHierarchy = array();
                $this->productCategories = array();
                $product_categories = get_the_terms( $main_product_id, 'product_cat' );

                if (isset($product_categories) && is_array($product_categories)) {
                    $this->sort_terms_hierarchically($product_categories, $categoryHierarchy);
                }

                $order_cat_id = end($this->productCategories);
                if (count($this->productCategories) > 2) {
                    $order_cat_id = $this->productCategories[1];
                }

                $picking_path = '';
                $product_picking_locations = wp_get_post_terms($main_product_id, 'pickingroute', array("orderby" => "parent"));
                if (isset($product_picking_locations) && !empty($product_picking_locations)) {
                    $order_cat_id = end($product_picking_locations)->term_id;
                    $categories = wp_list_pluck($product_picking_locations, 'name');
                    $picking_path = get_term_parents_list($order_cat_id, 'pickingroute', array('separator' => ' / ', 'link' => false, 'format' => 'name'));
                    $picking_path = rtrim($picking_path, " / ");
                }

                $thumbnail = get_the_post_thumbnail_url($main_product_id, 'medium');

                if (!empty($product_details['short_description'])) {
                    $description = $product_details['short_description'];
                } else {
                    $description = $product_details['description'];
                }

                $price = $product_info->get_price();
                if (isset($price) && !empty($price)) {
                    $price = $currency_symbol . ' ' . number_format($product_info->get_price(), 2, ",", ".");
                } else {
                    $price = '-';
                }

                $stock = $product_info->get_stock_quantity();
                if ($stock == NULL && !$product_info->managing_stock()) {
                    $stock_status = $product_info->get_stock_status();

                    if ($stock_status == 'outofstock') {
                        $stock = 'OUT_OF_STOCK';
                    } elseif ($stock_status == 'onbackorder') {
                        $stock = 'ON_BACKORDER';
                    } else {
                        $stock = 'IN_STOCK';
                    }
                }

                $description = strip_tags($description, '<p><a><strong><i>');
                $description = str_replace(array("\r", "\n"), '', $description);
                if (strlen($description) > 200) {
                    $description = substr($description, 0, 200) . '...';
                }

                if (!empty($meta_description)) {
                    $description = $meta_description;
                }


                $sku = $product_details['sku'];
                if (empty($sku)) {
                    $parent = wc_get_product($main_product_id);
                    $sku = (string)$product_id;
                    $barcode = $parent ? $parent->get_sku() : (string)$product_id;
                } else {
                    $barcode = $sku;
                }

                if (isset($orderpickingapp_ean_field) && !empty($orderpickingapp_ean_field)) {
                    $barcode = get_post_meta($product_id, $orderpickingapp_ean_field, true);
                }

                if (strpos($thumbnail, "?")) {
                    $thumbnail = substr($thumbnail, 0, strpos($thumbnail, "?"));
                }
                if (!isset($thumbnail) || empty($thumbnail)) {
                    $thumbnail = 'https://orderpickingapp.com/missing_product.jpg';
                }

                $supplier = '';
                $product_suppliers = wp_get_post_terms($main_product_id, 'orderpickingapp_supplier', array('fields' => 'names'));
                if (isset($product_suppliers) && !empty($product_suppliers)) {
                    $supplier = implode('/', $product_suppliers);
                }

                $picking_locations = [];
                $all_pickingroute_terms = get_terms(array('taxonomy' => 'pickingroute', 'orderby' => 'name'));
                if (isset($all_pickingroute_terms) && !empty($all_pickingroute_terms)) {
                    foreach( $all_pickingroute_terms as $all_pickingroute_term ){
                        $term_parents_list = get_term_parents_list($all_pickingroute_term->term_id, 'pickingroute', array('separator' => ' / ', 'link' => false, 'format' => 'name'));
                        $picking_locations[$all_pickingroute_term->term_id] = rtrim($term_parents_list, "/ ");                                }
                }

                $product_data = array(
                    'product_id'        => $product_id,
                    'title'             => $title,
                    'thumbnail'         => $thumbnail,
                    'description'       => $description,
                    'sku'               => $sku,
                    'barcode'           => $barcode,
                    'price'             => $price,
                    'stock'             => (int)$stock,
                    'allocated_qty'     => (int)$allocated_qty,
                    'order_cat'         => $order_cat_id,
                    'categories'        => implode(' / ', $categories),
                    'cost_price'        => get_post_meta($product_id, 'orderpickingapp_cost_price', true),
                    'supplier'          => $supplier,
                    'supplier_sku'      => get_post_meta($product_id, 'orderpickingapp_supplier_sku', true),
                    'picking_path' 		=> $picking_path,
                    'picking_locations'	=> $picking_locations,
                );
                $product_data = apply_filters('orderpickingapp_product_data', $product_data, []);

                $product_data['second_barcode'] =  '';
                $orderpickingapp_additional_barcode_field = get_option('orderpickingapp_additional_barcode_field');
                if (isset($orderpickingapp_additional_barcode_field) && !empty($orderpickingapp_additional_barcode_field)) {
                    $product_data['second_barcode'] =  get_post_meta($product_id, $orderpickingapp_additional_barcode_field, true);
                }

                $product_data['box_amount'] =  '';
                $orderpickingapp_additional_box_amount_field = get_option('orderpickingapp_additional_box_amount_field');
                if (isset($orderpickingapp_additional_box_amount_field) && !empty($orderpickingapp_additional_box_amount_field)) {
                    $product_data['box_amount'] =  get_post_meta($product_id, $orderpickingapp_additional_box_amount_field, true);
                }

                $Products[$product_id] = $product_data;
            }

            $Products = array_values($Products);
            wp_send_json($Products, 200);
        } else {
            $args = array(
                'status' => 400,
                'message' => 'Product with his searchterm nog found!',
            );
            wp_send_json($args);
        }
    }

    // Verbeterde versie
    public function updateProduct($request) {

        // 1. Valideer en saniteer input
        $product_id      = absint($request->get_param('productid'));
        $stock           = $request->get_param('stock');
        $picking_path_id = absint($request->get_param('picking_path_id'));
        $barcode         = sanitize_text_field($request->get_param('barcode'));

        // 2. Controleer of het product bestaat
        $product = wc_get_product($product_id);
        if ( ! $product ) {
            return new WP_Error(
                'invalid_product',
                'Product niet gevonden',
                [ 'status' => 404 ]
            );
        }

        // 3. Picking route instellen (alleen voor variaties)
        $parent_id = $product->get_parent_id();
        if ( $parent_id !== 0 && ! empty($picking_path_id) ) {
            wp_set_object_terms( $parent_id, $picking_path_id, 'pickingroute' );
        }

        // 4. Voorraad bijwerken — isset + strlen zodat 0 ook werkt
        if ( isset($stock) && strlen($stock) > 0 ) {
            $product->set_stock_quantity( intval($stock) );
            $product->update_meta_data( 'last_inventory_date', wp_date('Y-m-d H:i') );
        }

        // 5. Barcode instellen
        if ( ! empty($barcode) ) {
            $product->set_global_unique_id($barcode);
            $product->update_meta_data( '_alg_ean', $barcode );
        }

        $product->save();

        // 6. Geef een response terug
        return new WP_REST_Response(
            [ 'success' => true, 'product_id' => $product_id ],
            200
        );
    }

    function is_hpos_enabled() {
        return get_option('woocommerce_custom_orders_table_enabled') === 'yes';
    }

    function returnBytes($val)
    {
        $val = trim($val);
        $last = strtolower($val[strlen($val) - 1]);
        $val = substr($val, 0, strlen($val) - 1);
        switch ($last) {
            case 'g':
                $val *= 1024;
            case 'm':
                $val *= 1024;
            case 'k':
                $val *= 1024;
        }
        return $val;
    }

    // Bepaal gereserveerde hoeveelheid (allocated_qty) voor een product.
    public function get_allocated_qty_for_product( $product ) {
        $allocated = 0;

        $all_open_orders = $this->getAllPickingOrders();

        foreach ( $all_open_orders as $order ) {
            foreach ( $order->get_items( 'line_item' ) as $item ) {
                $li_product = $item->get_product();
                if ( ! $li_product ) { continue; }
                if ( (int) $li_product->get_id() === (int) $product->get_id() ) {
                    $allocated += (float) $item->get_quantity();
                }
            }
        }

        return max( 0.0, $allocated );
    }

}