<?php

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

global $PDFS_DIR;
$PDFS_DIR_RELATIVE = "wp-content/plugins/" . NELE_PLUGIN_NAME . "/pdfs/";
$PDFS_DIR = ABSPATH . $PDFS_DIR_RELATIVE;

add_filter('bulk_actions-edit-shop_order', 'nele_add_print_labels_action');
function nele_add_print_labels_action($actions) {
    $actions['nele_print_parcel_labels'] = __('Print Parcel Labels', 'nextlevel_delivery');
    return $actions;
}

add_action('load-edit.php', 'nele_handle_print_labels_action');
function nele_handle_print_labels_action() {
    if (! isset($_REQUEST['action']) || $_REQUEST['action'] !== 'nele_print_parcel_labels') {
        return;
    }
    if (! isset($_REQUEST['post'])) {
        write_log("nele_handle_print_labels_action: No orders selected");
        return;
    }
    $order_ids = $_REQUEST['post'];
    $parcel_ids = nele_resolve_parcel_ids_from_orders($order_ids);
    if (empty($parcel_ids)) {
        write_log("nele_handle_print_labels_action: No orders with created shipment were selected");
        return;
    }

    $parent_obj = nele_parent_obj();
    $response = nele_api_shipment_pdf_bulk($parent_obj->creds, $parcel_ids);
    if ($response->is_error) {
        write_log("nele_handle_print_labels_action: file was not generated");
        return;
    }
    $contents = $response->msg;
    if (empty($contents)) {
        write_log("nele_handle_print_labels_action: content is empty - nothing to download");
        return;
    }
    $file_name = nele_binary_to_temp_file($contents);
    if (empty($file_name)) {
        write_log("nele_handle_print_labels_action: nothing to download");
        return;
    }
    header('Content-Type: application/zip');
    header("Content-Disposition: attachment; filename=print-labels.zip");
    readfile($file_name);
    exit();
}

add_filter('manage_edit-shop_order_columns', 'nele_add_custom_parcel_column');
function nele_add_custom_parcel_column($columns) {
    $columns['nele_parcel_id'] = __('NextLevel Parcel ID', 'nextlevel_delivery');
    return $columns;
}

function nele_generate_shipment_pdf($order_id): ApiResponse {
    $pdf_url = nele_get_pdf_url($order_id);
    if (! empty($pdf_url)) {
        return new ApiResponse(array("url"=> $pdf_url));
    }
    global $PDFS_DIR, $PDFS_DIR_RELATIVE;
    $parent_obj = nele_parent_obj();
    $parcel_id = nele_get_parcel_id($order_id);
    $response = nele_api_shipment_pdf($parent_obj->creds, $parcel_id);
    if ($response->is_error) {
        write_log('nele_display_custom_parcel_column: Invalid order ID or unable to generate shipping label.');
        return new ApiResponse("Invalid order ID or unable to generate shipping label.", true, true);
    }
    $temp_file_name = nele_binary_to_temp_file($response->msg);
    if (empty($temp_file_name)) {
        write_log('nele_display_custom_parcel_column: File contents was not written.');
        return new ApiResponse("File contents was not written.", true, true);
    }
    if (! file_exists($PDFS_DIR) && mkdir($PDFS_DIR, 0755) === false) {
        write_log("nele_display_custom_parcel_column: not able to create the dir: $PDFS_DIR");
        return new ApiResponse("Not able to create the dir: $PDFS_DIR", true, true);
    }
    if (is_dir($PDFS_DIR) === false) {
        write_log("creating dir: not a dir: $PDFS_DIR");
        return new ApiResponse("Not a dir: $PDFS_DIR", true, true);
    }
    $pdf_file_name = $parcel_id . '-label.pdf';
    $abs_file_name = $PDFS_DIR . $pdf_file_name;

    if (rename($temp_file_name, $abs_file_name) === false) {
        write_log("nele_display_custom_parcel_column: error moving file from temp location: $abs_file_name");
        return new ApiResponse("Error moving file from temp location: $abs_file_name", true, true);
    }
    return new ApiResponse(array("url" => site_url($PDFS_DIR_RELATIVE . $pdf_file_name)));
}

function nele_create_pdf_if_empty($order_id): ApiResponse {
    write_log("nele_create_pdf_if_empty: started");
    $pdf_url = nele_get_pdf_url($order_id);
    if (empty($pdf_url)) {
        $response = nele_generate_shipment_pdf($order_id);
        if ($response->is_error || empty($response->msg['url'])) {
            write_log("nele_create_pdf_if_empty: pdf generation failed");
            return $response;
        }
        $pdf_url = $response->msg['url'];
        write_log("nele_create_pdf_if_empty: updating post meta with: " . $pdf_url);
        $order = wc_get_order( $order_id );
        $order->update_meta_data( '_nele_created_pdf_url', $pdf_url);
        $order->update_meta_data( '_nele_pdf_created_at', date("Y-m-d H:i:s"));
        $order->save();
        return $response;
    }
    write_log("nele_create_pdf_if_empty: set post meta to: " . $pdf_url);
    return new ApiResponse(array("url" => $pdf_url));
}

add_action('manage_shop_order_posts_custom_column', 'nele_display_custom_parcel_column');
function nele_display_custom_parcel_column($column) {
    if ($column !== 'nele_parcel_id') {
        return;
    }
    global $post;
    $parcel_id = nele_get_parcel_id($post->ID);
    if (empty($parcel_id)) {
        echo '-';
        return;
    }
    $escaped_parcel_id = esc_html($parcel_id);
    $pdf_url = nele_get_pdf_url($post->ID);
    echo $escaped_parcel_id . '<br/><a href="' . esc_url($pdf_url) . '" target="_blank">' . __('PDF', 'nextlevel_delivery') . '</a>';
}

add_action('admin_enqueue_scripts', 'nele_enqueue_orders_script');
function nele_enqueue_orders_script($hook) {
    if ('post.php' !== $hook && ! str_contains($hook, "wc-orders")) {
        return;
    }
	$inline_js = "const IS_WP_DEBUG = `" . WP_DEBUG . "`;";
	wp_add_inline_script('jquery', $inline_js);
    wp_enqueue_style('nele-spinner-css', NELE_PLUGIN_URL . 'css/spinner.css', array(), '1.0.7');
    wp_enqueue_script('nele-spinner-js', NELE_PLUGIN_URL . 'js/spinner.js', array('jquery'), '1.0.8', true);
    wp_enqueue_style('nele-orders-css', NELE_PLUGIN_URL . 'css/orders.css', array(), '1.0.17');
    wp_enqueue_script('nele-orders-script', NELE_PLUGIN_URL . 'js/orders.js', array('jquery'), '1.0.87', true);
    wp_localize_script('nele-orders-script', 'nele_orders_object', array(
        'ajax_url' => admin_url('admin-ajax.php'),
    ));
}

function nele_resolve_order_address_details($order): AddressDetails {
    $country_code = $order->get_billing_country();
    $post_code = $order->get_billing_postcode();
    $country_obj = nele_db_countries($country_code);
    $country_id = empty($country_obj) ? "" : $country_obj[0]->id;
	$state = $order->get_meta('nele_state', true);
    $city_id = $order->get_meta('nele_place_id', true);
    $place = $order->get_meta('nele_place', true);
    if (! empty($city_id)) {
        $places = nele_db_cities_by_id($city_id);
        $place = empty($places) ? $place : $places[0]->name;
    }
    $office_id = $order->get_meta('nele_office_id', true);
    $offices = nele_db_offices_by_id($office_id);
    $office = empty($offices) ? "" : $offices[0]->name;
    $street = $order->get_meta('nele_street', true);
    $street_no = $order->get_meta('nele_street_num', true);
    $complex = $order->get_meta('nele_district', true);
    $block_no = $order->get_meta('nele_block', true);
    $entrance_no = $order->get_meta('nele_entrance', true);
    $floor_no = $order->get_meta('nele_floor', true);
    $apartment_no = $order->get_meta('nele_apt', true);
    return new AddressDetails($state, $office_id, $office, $country_id, $country_code, $post_code, $city_id, $place,
        $street, $street_no, $complex, $block_no, $entrance_no, $floor_no, $apartment_no);
}

add_action('wp_ajax_create_shipment_action', 'nele_create_shipment_callback');
function nele_create_shipment_callback($return_json = true, $return_on_success = true, $order_id = null) {
    if (! isset($_POST['order_id']) && empty($order_id)) {
        write_log('nele_create_shipment_callback: Unable to get order_id in the incoming request.');
        if ($return_json === true) {
	        wp_send_json_error(array( "response" => __( 'Unable to get order_id in the incoming request.', 'nextlevel_delivery' ) ));
	        wp_die();
        }
        return;
    }
    $order_id = intval($_POST['order_id'] ?? $order_id);
    $order = wc_get_order($order_id);
    $shipping_method_id = $order->get_meta('nele_shipping_method', true);
    if (empty($shipping_method_id)) {
	    write_log('nele_create_shipment_callback: Unable to get the shipping method selected.');
        if ($return_json === true) {
		    wp_send_json_error(array( "response" => __( 'Unable to get the shipping method selected.', 'nextlevel_delivery' ) ));
		    wp_die();
        }
        return;
    }
    $address_details = nele_resolve_order_address_details($order);
    $country_obj = nele_db_countries($address_details->country);
    if (empty($country_obj)) {
	    write_log('nele_create_shipment_callback: Unable to get selected country.');
        if ($return_json === true) {
		    wp_send_json_error(array( "response" => __( 'Unable to get selected country.', 'nextlevel_delivery' ) ));
		    wp_die();
        }
        return;
    }
    $is_machine = false;
    $street = '';
    $offices = '';
    if ($address_details->ship_to_office) {
        $office_id = $address_details->office_id;
        $offices = nele_db_offices_by_id($office_id);
        $is_machine = $offices[0]->is_machine;
    } else {
        $street = $address_details->street;
    }
    if (empty($offices) && empty($street)) {
	    write_log('nele_create_shipment_callback: Neither street address nor office was found.');
        if ($return_json === true) {
	        wp_send_json_error(array( "response" => __( 'Neither street address nor office was found.', 'nextlevel_delivery' ) ));
	        wp_die();
        }
        return;
    }
	write_log("nele_create_shipment_callback: shipping_method_id=$shipping_method_id");
    $courier = nele_courier_by_shipping_method($shipping_method_id);
    write_log("nele_create_shipment_callback: courier=$courier");
    $first_name = $order->get_billing_first_name();
    $last_name = $order->get_billing_last_name();
    $receiver = "$first_name $last_name";
    $phone = $order->get_billing_phone();
    $email = $order->get_billing_email();
    nele_reset_parcel_id($order_id);
    $total_price = nele_get_order_price($order);
    $max_height = 0;
    $max_width = 0;
    $max_length = 0;
    $parent_obj = nele_parent_obj();
    foreach ($order->get_items() as $item_id => $item) {
        $product = $item->get_product();
        if ( $product->is_virtual() ) {
            continue;
        }
        $max_height = max($max_height, $product->get_height());
        $max_width = max($max_width, $product->get_width());
        $max_length = max($max_length, $product->get_length());
    }
    $total_weight = nele_get_order_weight($order);
    write_log("nele_create_shipment_callback: total_price=$total_price, weight=$total_weight");
    $parcels = new Parcels();
    $parcels->add_parcel(new Parcel(1, $total_price, $total_weight, $max_length, $max_width, $max_height));

    $currency = $country_obj[0]->currency;
    $included_shipping_price = wc_string_to_bool(nele_shipping_option_value("include_price", $shipping_method_id));
    $declared_value = wc_string_to_bool(nele_shipping_option_value("declared_value", $shipping_method_id));
    $option_raw = nele_shipping_option_value("service", $shipping_method_id);
    $option = empty($option_raw) ? 'OPEN' : $option_raw;
    $return_shipment_payer_raw = nele_shipping_option_value("payer", $shipping_method_id);
    $return_shipment_payer = empty($return_shipment_payer_raw) ? 'SENDER' : $return_shipment_payer_raw;
    $payer = strtolower($return_shipment_payer);
    $fragile = wc_string_to_bool(nele_shipping_option_value("fragile", $shipping_method_id));
    $description = nele_order_items_names($order);
    $contents = nele_order_items_sku_quantity($order);

    $creds = $parent_obj->creds;
    $response = nele_api_create_shipment($creds, $courier, $receiver, $phone, $parcels, $payer, $currency, $included_shipping_price,
        $address_details, $order_id, $description, $contents, $declared_value, $option, $return_shipment_payer, $fragile, $email, $is_machine);
    $msg = $response->msg;
    if (($response->is_error || is_string($msg))) {
	    write_log("nele_create_shipment_callback: Shipment creation failure: $msg");
        if ($return_json === true) {
	        wp_send_json_error(array( "response" => __( 'Shipment creation failure: '. $msg, 'nextlevel_delivery' ) ));
	        wp_die();
        }
        return;
    }
	$created_parcel_id = $msg->parcels[0]->awb;
    $order->update_meta_data( "_nele_created_parcel_id", $created_parcel_id);
    $order->update_meta_data( '_nele_shipment_created_at', date("Y-m-d H:i:s"));
    $order->save();
    write_log('Shipment creation succeeded. Parcel id: ' . $created_parcel_id);
    if ($return_on_success) {
        wp_send_json(array( "response" => __( 'Shipment creation succeeded. Parcel id: ' . $created_parcel_id, 'nextlevel_delivery' ) ));
        wp_die();
    }
}

add_action('wp_ajax_generate_pdf_action', 'nele_generate_pdf_callback');
function nele_generate_pdf_callback($return_json = true, $order_id = null)
{
    if (! isset($_POST['order_id']) && empty($order_id)) {
	    write_log('nele_generate_pdf_callback: Unable to get order_id in the incoming request: '.$order_id.' '.$_POST['order_id']);
        if ($return_json === true) {
	        wp_send_json_error(array("response" => __('Unable to get order_id in the incoming request.', 'nextlevel_delivery')));
	        wp_die();
        }
        return;
    }
    $order_id = intval($_POST['order_id'] ?? $order_id);
    if (empty(nele_get_parcel_id($order_id))) {
        write_log("nele_generate_pdf_callback: empty parcel_id -> creating new shipment");
        nele_create_shipment_callback($return_json, false, $order_id);
    }
    if (empty(nele_get_parcel_id($order_id))) {
	    write_log('nele_generate_pdf_callback: Please first create your shipment.');
        if ($return_json === true) {
	        wp_send_json_error(array("response" => __('Please first create your shipment.', 'nextlevel_delivery')));
	        wp_die();
        }
        return;
    }
    $response = nele_create_pdf_if_empty($order_id);
    if ($response->is_error) {
        $error = $response->msg;
	    write_log('nele_generate_pdf_callback: Please first create your shipment: '.$error);
        if ($return_json === true) {
	        wp_send_json_error(array("response" => $error));
	        wp_die();
        }
        return;
    }
    if ($return_json === true) {
        wp_send_json(array( "response" => __( 'PDF generation succeeded.', 'nextlevel_delivery' ) ));
        wp_die();
    }
}

add_action( 'woocommerce_admin_order_data_after_billing_address', 'nele_editable_order_meta_billing' );
/**
 * @throws Exception
 */
function nele_editable_order_meta_billing($order ){
    $order_id = $order->get_id();
    $parcel_id = esc_html(nele_get_parcel_id($order_id));
    $pdf_url = nele_get_pdf_url($order_id);
    $escaped_parcel_id = empty($parcel_id) ? '-' : $parcel_id;
    $order_modified_date = new DateTime($order->get_date_modified());
    $order_modified = $order_modified_date->getTimestamp();
    ?>
    <div class="address">
        <?php
        if (empty(nele_get_parcel_id($order_id)) || shipment_created_at($order_id) <= $order_modified) {
            echo '<button type="button" class="button create-shipment-button" data-order-id="' . $order_id . '">'.__("Create Shipment", "nextlevel_delivery").'</button>&nbsp';
        }
        if (empty(nele_get_pdf_url($order_id)) || pdf_created_at($order_id) <= $order_modified) {
            echo '<button type="button" class="button generate-pdf-button" data-order-id="' . $order_id . '">'.__("Generate PDF", "nextlevel_delivery").'</button>';
        }
        ?>
        <p>
            <strong><?php echo __("Delivery to", "nextlevel_delivery"); ?>:</strong>
            <?php echo nele_resolve_order_address_details($order)->ship_to_office ? 'office' : 'address' ?>
        </p>
        <p>
            <strong><?php echo __("NextLevel way-bill no", "nextlevel_delivery"); ?>:</strong>
            <?php echo empty($pdf_url) ? $escaped_parcel_id : "<a href='" . esc_url($pdf_url) . "' target='_blank'/>" . $escaped_parcel_id . "</a>"; ?>
        </p>
    </div><br/>
    <div class="edit_address" id="nele-order-settings-table">
        <?php
        $edit_buttons = '<p class="form-field"><button type="button" class="button save-changes-button button-primary" data-order-id="' . $order->get_id() . '">'.__("Save Changes", "nextlevel_delivery").'</button>&nbsp<button type="button" class="button cancel-edit-button">Cancel</button></p>';
        echo $edit_buttons;
        $parent_obj = nele_parent_obj();
        $show_state_field = wc_string_to_bool($parent_obj->get_option("show_state_field", false));
        if ($show_state_field) {
	        woocommerce_wp_text_input( array(
		        'id' => 'nele_state',
                'value' => $order->get_meta('nele_state'),
		        'label' => __('State:', 'nextlevel_delivery'),
		        'wrapper_class' => 'form-field-wide',
	        ) );
        }
        woocommerce_wp_text_input( array(
            'id' => 'nele_place',
            'value' => $order->get_meta('nele_place'),
            'label' => __('City:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field-wide',
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_place_id',
            'value' => $order->get_meta('nele_place_id'),
            'label' => __('City ID:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field-wide'
        ) );
        woocommerce_wp_checkbox( array(
            'id' => 'nele_ship_to',
            'value' => $order->get_meta('nele_ship_to'),
            'label' => __('Ship to office?', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ));
        woocommerce_wp_text_input( array(
            'id' => 'nele_office',
            'value' => $order->get_meta('nele_office'),
            'label' => __('Office:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field-wide'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_office_id',
            'value' => $order->get_meta('nele_office_id'),
            'label' => __('Office ID:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field-wide'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_street',
            'value' => $order->get_meta('nele_street'),
            'label' => __('Street:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_street_num',
            'value' => $order->get_meta('nele_street_num'),
            'label' => __('No:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_district',
            'value' => $order->get_meta('nele_district'),
            'label' => __('District:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_block',
            'value' => $order->get_meta('nele_block'),
            'label' => __('Block:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_entrance',
            'value' => $order->get_meta('nele_entrance'),
            'label' => __('Entrance:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_floor',
            'value' => $order->get_meta('nele_floor'),
            'label' => __('Floor:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        woocommerce_wp_text_input( array(
            'id' => 'nele_apt',
            'value' => $order->get_meta('nele_apt'),
            'label' => __('Apartment:', 'nextlevel_delivery'),
            'wrapper_class' => 'form-field'
        ) );
        echo $edit_buttons;
        ?>
    </div>
    <?php
}

add_action('wp_ajax_custom_save_changes_action', 'nele_custom_save_changes_callback');
/**
 * @throws WC_Data_Exception
 */
function nele_custom_save_changes_callback()
{
    write_log("nele_save_changes_callback started");
    if (! isset($_POST['order_id'])) {
        wp_send_json_error(array("response" => __('Unable to get order_id in the incoming request.', 'nextlevel_delivery')));
        wp_die();
    }
    global $nele_to_office_key, $nele_to_address_key;
    $order_id = intval($_POST['order_id']);
    write_log("nele_save_changes_callback: order_id=" . $order_id);
    $order = wc_get_order($order_id);
    $order->set_billing_first_name(wc_sanitize_textarea( $_POST[ 'billing_first_name' ] ));
    $order->set_billing_last_name(wc_sanitize_textarea( $_POST[ 'billing_last_name' ] ));
    $order->set_billing_company(wc_sanitize_textarea( $_POST[ 'billing_company' ] ));
    $order->set_billing_country(wc_sanitize_textarea( $_POST[ 'billing_country' ] ));
    $order->set_billing_postcode(wc_sanitize_textarea( $_POST[ 'billing_postcode' ] ));
    $order->set_billing_email(wc_sanitize_textarea( $_POST[ 'billing_email' ] ));
    $order->set_billing_phone(wc_sanitize_textarea( $_POST[ 'billing_phone' ] ));
    $order->set_payment_method(wc_sanitize_textarea( $_POST[ 'payment_method' ] ));
    $order->set_transaction_id(wc_sanitize_textarea( $_POST[ 'transaction_id' ] ));
    $ship_to_office = rest_sanitize_boolean($_POST['ship_to_office']);
//	$shipping_methods = $_POST[ 'shipping_method' ];
//	$shipping_method = $shipping_methods[array_key_first($shipping_methods)];
    $shipping_method = wc_sanitize_textarea($_POST[ 'csm' ]);
    write_log("nele_custom_save_changes_callback: shipping_method=$shipping_method");
    $order->update_meta_data('nele_ship_to', $ship_to_office ? $nele_to_office_key : $nele_to_address_key);
    $order->update_meta_data('nele_shipping_method', $shipping_method);
    $order->update_meta_data('nele_state', wc_sanitize_textarea( $_POST[ 'state' ] ));
    $order->update_meta_data('nele_place', wc_sanitize_textarea( $_POST[ 'place' ] ));
    $order->update_meta_data('nele_place_id', wc_sanitize_textarea( $_POST[ 'place_id' ] ) );
    $order->update_meta_data('nele_office', $ship_to_office ? wc_sanitize_textarea( $_POST[ 'office' ] ) : '' );
    $order->update_meta_data( 'nele_office_id', $ship_to_office ? wc_sanitize_textarea( $_POST[ 'office_id' ] ) : '' );
    $order->update_meta_data( 'nele_street', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'street' ] ) : '' );
    $order->update_meta_data( 'nele_street_num', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'street_num' ] ) : '' );
    $order->update_meta_data( 'nele_district', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'district' ] ) : '' );
    $order->update_meta_data( 'nele_block', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'block' ] ) : '' );
    $order->update_meta_data( 'nele_entrance', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'entrance' ] ) : '' );
    $order->update_meta_data( 'nele_floor', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'floor' ] ) : '' );
    $order->update_meta_data( 'nele_apt', ! $ship_to_office ? wc_sanitize_textarea( $_POST[ 'apt' ] ) : '' );
    nele_reset_parcel_id($order_id);
    nele_update_order_shipping_price($order_id, null);
    $order->save();
    wp_send_json(array( "response" => __( 'Changes were saved.', 'nextlevel_delivery' ) ));
    wp_die();
}

function nele_get_order_weight($order): float {
    $total_weight = 0;
	$parent_obj = nele_parent_obj();
    $default_weight = floatval($parent_obj->get_option("product_weight", "1"));
    foreach( $order->get_items() as $item_id => $product_item ){
        $quantity = intval($product_item->get_quantity());
        $product = $product_item->get_product();
        $product_weight = floatval($product->get_weight());
        if ($product_weight < PHP_FLOAT_EPSILON) {
            $product_weight = $default_weight;
        }
        $total_weight += $product_weight * $quantity;
    }
    write_log("nele_get_order_weight: total_weight=$total_weight");
    return $total_weight;
}

add_action('woocommerce_checkout_update_order_meta', 'nele_update_order_shipping_price', 10, 2);
/**
 * @throws WC_Data_Exception
 */
function nele_update_order_shipping_price($order_id, $data) {
    global $UNDEFINED_SHIPPING_PRICE, $nele_to_office_key;
	$order = wc_get_order( $order_id );
	$shipping_method_id = $order->get_meta('nele_shipping_method', true);
    if (! isset($shipping_method_id)) {
        write_log("nele_update_order_shipping_price: shipping method not set -> taking the first one");
        $order_sm = $order->get_shipping_methods();
	    $shipping_method_id = $order_sm[array_key_first($order_sm)];
    }
    $ship_to = $order->get_meta('nele_ship_to', true);
    $country_code = $order->get_billing_country();
    $postcode = $order->get_billing_postcode();
    $city = $order->get_meta('nele_place_id', true);
    $city_name = $order->get_meta('nele_place', true);
    $office = $order->get_meta('nele_office_id', true);
    $is_machine = false;
	write_log("nele_update_order_shipping_price: shipping_method_id=$shipping_method_id, ship_to=$ship_to, country_code=$country_code, postcode=$postcode, city=$city, office=$office");
    if ($ship_to === $nele_to_office_key) {
        $offices = nele_db_offices_by_id($office);
        if ($offices) {
            $is_machine = $offices[0]->is_machine;
        }
    }
    $shipping_price_old = $order->get_shipping_total();
	$include_vat = $order->get_prices_include_tax();
    $subtotal = nele_get_order_price($order);
    $weight = nele_get_order_weight($order);
    [$shipping_price, $tax] = nele_calculate_shipping_price($shipping_method_id, $ship_to, $country_code, $postcode, $city, $city_name, $office, $weight, $subtotal, $is_machine, $include_vat);
    if ($shipping_price === $shipping_price_old || $shipping_price === $UNDEFINED_SHIPPING_PRICE) {
        write_log("nele_update_order_shipping_price: shipping price was not changed");
        return;
    }
	foreach( $order->get_items( 'fee' ) as $item_id => $item ) {
		if( nele_cart_shipping_price_title() === $item['name'] ) {
			$order->remove_item($item_id);
		}
	}
    $items = $order->get_shipping_methods();
    foreach ( $items as $item_id => $item ) {
        $item->set_total($shipping_price);
    }
//    $order->set_shipping_total($shipping_price);
//    $order->set_shipping_tax($tax);
    $order->calculate_totals(); // Recalculate totals and save
}

function nele_get_order_price($order) {
	return $order->get_subtotal() + $order->get_total_tax() - $order->get_shipping_tax();
}