<?php
if (!defined('ABSPATH')) {
    exit;
}
if (!function_exists('drop_print_register_server_order_update_endpoint_client_cb')) {
    function drop_print_register_server_order_update_endpoint_client_cb()
    {
        register_rest_route('drop-print-client/v1', '/order-status-update', array(
            'methods' => WP_REST_Server::EDITABLE,
            'callback' => 'drop_print_handle_server_order_status_update_client_cb',
            'permission_callback' => 'drop_print_check_server_order_update_permissions_client_cb',
            'args' => array(
                'client_order_id' => array(
                    'validate_callback' => function ($value) {
                        return is_numeric($value) && $value > 0;
                    },
                    'sanitize_callback' => 'absint',
                    'required' => true,
                ),
                'status' => array(
                    'required' => true,
                    'type' => 'string',
                    'sanitize_callback' => 'sanitize_key'
                ),
                'server_order_id' => array('required' => false, 'type' => 'integer', 'validate_callback' => function ($p) {
                    return empty($p) || (is_numeric($p) && $p > 0);
                }, 'sanitize_callback' => 'absint'),
                'tracking_number' => array('required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field'),
                'tracking_carrier' => array('required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field'),
                'tracking_url' => array('required' => false, 'type' => 'string', 'format' => 'uri', 'sanitize_callback' => 'esc_url_raw'),
                'dispatch_date' => array('required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field'),
                'queue_id' => array('required' => false, 'type' => ['integer', 'string'], 'validate_callback' => function ($p) {
                    return empty($p) || (is_numeric($p) && $p > 0) || is_string($p);
                }, 'sanitize_callback' => 'sanitize_text_field'),
                'receipt_url' => array('required' => false, 'type' => 'string', 'format' => 'uri', 'sanitize_callback' => 'esc_url_raw'),
                'message' => array('required' => false, 'type' => 'string', 'sanitize_callback' => 'wp_kses_post'),
                'item_ids_with_errors' => array(
                    'required' => false, 'type' => 'array', 'items' => array('type' => 'integer'),
                    'validate_callback' => function ($param_array) {
                        if (!is_array($param_array)) return false;
                        foreach ($param_array as $item) {
                            if (!is_numeric($item) || absint($item) <= 0) return false;
                        }
                        return true;
                    },
                    'sanitize_callback' => function ($param_array) {
                        $sanitized_array = [];
                        if (is_array($param_array)) {
                            foreach ($param_array as $item) {
                                if (is_numeric($item) && absint($item) > 0) {
                                    $sanitized_array[] = absint($item);
                                }
                            }
                        }
                        return array_filter(array_unique($sanitized_array));
                    },
                ),
            ),
        ));
    }
}
add_action('rest_api_init', 'drop_print_register_server_order_update_endpoint_client_cb');
if (!function_exists('drop_print_check_server_order_update_permissions_client_cb')) {
    function drop_print_check_server_order_update_permissions_client_cb(WP_REST_Request $request)
    {
        $client_wp_user_id_for_auth = $request->get_param('client_wp_user_id_for_auth');
        $auth_user_id_to_use = 0;
        if (!empty($client_wp_user_id_for_auth) && absint($client_wp_user_id_for_auth) > 0) {
            $auth_user_id_to_use = absint($client_wp_user_id_for_auth);
        } else {
            $client_order_id = $request->get_param('client_order_id');
            if ($client_order_id) {
                $order = wc_get_order($client_order_id);
                if ($order) {
                    $customer_id = $order->get_customer_id();
                }
            }
        }
        if ($auth_user_id_to_use === 0) {
            $admin_users = get_users(array('role__in' => array('administrator'), 'number' => 1, 'orderby' => 'ID', 'fields' => 'ID'));
            if (!empty($admin_users)) {
                $auth_user_id_to_use = $admin_users[0];
            }
        }
        if ($auth_user_id_to_use === 0) {
            return new WP_Error('rest_cannot_determine_auth_user_order_update', __('Cannot determine user context for client-side authentication of webhook.', 'drop-print'), array('status' => 403));
        }
        $user_settings = drop_print_get_user_settings($auth_user_id_to_use);
        if (empty($user_settings) || empty($user_settings['public_key_pem_b64']) || !is_string($user_settings['public_key_pem_b64'])) {
            return new WP_Error(
                'rest_client_user_auth_config_missing_order_update',
                sprintf(__('Client authentication user (ID: %d) not configured with server public key.', 'drop-print'), $auth_user_id_to_use),
                array('status' => 403)
            );
        }
        $api_key_prefix = $request->get_header('X-Drop-Print-Client-Public-Key-Prefix');
        if (empty($api_key_prefix)) {
            return new WP_Error('rest_missing_header_cb_client', __('Missing required auth header for order update.', 'drop-print'), array('status' => 401));
        }
        $stored_public_key_b64 = $user_settings['public_key_pem_b64'];
        $stored_public_key_prefix = substr($stored_public_key_b64, 0, 42);
        if (hash_equals($stored_public_key_prefix, $api_key_prefix)) {
            return true;
        } else {
            return new WP_Error('rest_forbidden_callback_client_order_update', __('Invalid auth credentials from server callback for order update.', 'drop-print'), array('status' => 403));
        }
    }
}
if (!function_exists('drop_print_handle_server_order_status_update_client_cb')) {
    function drop_print_handle_server_order_status_update_client_cb(WP_REST_Request $request)
    {
        $client_order_id = $request->get_param('client_order_id');
        $order = wc_get_order($client_order_id);
        if (!$order) {
            return new WP_Error('order_not_found_cb_client', __('Order not found on Client site.', 'drop-print'), array('status' => 404));
        }
        $current_details = $order->get_meta('_drop_print_order_details', true);
        if (!is_array($current_details)) {
            $current_details = [];
        }
        $new_details = $current_details;
        $params_to_update = array(
            'status' => 'status', 'server_order_id' => 'server_order_id', 'tracking_number' => 'tracking_number',
            'tracking_carrier' => 'tracking_carrier', 'tracking_url' => 'tracking_url', 'dispatch_date' => 'dispatch_date',
            'queue_id' => 'queue_id', 'receipt_url' => 'receipt_url', 'message' => 'last_server_message'
        );
        $meta_changed = false;
        foreach ($params_to_update as $request_key => $meta_key) {
            $value = $request->get_param($request_key);
            if ($value !== null) {
                if (!isset($new_details[$meta_key]) || $new_details[$meta_key] !== $value) {
                    $new_details[$meta_key] = $value;
                    $meta_changed = true;
                }
            }
        }
        $new_status_from_request = $new_details['status'] ?? null;
        if ($new_status_from_request === 'file_issue_detected') {
            $item_ids_with_errors_param = $request->get_param('item_ids_with_errors');
            if ($item_ids_with_errors_param !== null && is_array($item_ids_with_errors_param)) {
                if (!isset($new_details['item_ids_with_errors']) || $new_details['item_ids_with_errors'] !== $item_ids_with_errors_param) {
                    $new_details['item_ids_with_errors'] = $item_ids_with_errors_param;
                    $meta_changed = true;
                }
            }
        } elseif (isset($new_details['item_ids_with_errors'])) {
            unset($new_details['item_ids_with_errors']);
            $meta_changed = true;
        }
        if (isset($new_details['external_api_order_id'])) {
            unset($new_details['external_api_order_id']);
            $meta_changed = true;
        }
        $new_status = $new_details['status'] ?? '';
        if ($new_status === 'cancelled') {
            $new_details['last_server_message'] = $new_details['last_server_message'] ?? __('Order cancelled on the server. You can quote again once ready.', 'drop-print');
            $new_details['quote_reenabled'] = true;
            unset($new_details['server_order_id'], $new_details['queue_id'], $new_details['receipt_url'], $new_details['tracking_number'], $new_details['tracking_carrier'], $new_details['tracking_url'], $new_details['dispatch_date'], $new_details['external_api_order_id']);
            $meta_changed = true;
            $order->add_order_note(__('Drop Print server marked this order as cancelled. Quote & Pay may be available again.', 'drop-print'));
        }
        if ($meta_changed) {
            $new_details['last_server_update'] = time();
            $order->update_meta_data('_drop_print_order_details', $new_details);
            $order->save_meta_data();
        }
        $received_tracking_number = $new_details['tracking_number'] ?? null;
        if (!empty($received_tracking_number) && in_array($new_status, ['shipped', 'completed', 'production-completed'])) {
            $received_tracking_carrier = $new_details['tracking_carrier'] ?? '';
            $received_tracking_url = $new_details['tracking_url'] ?? '';
            $received_dispatch_date_str = $new_details['dispatch_date'] ?? null;
            $date_shipped_timestamp = $received_dispatch_date_str ? strtotime($received_dispatch_date_str) : time();
            if (!$date_shipped_timestamp) {
                $date_shipped_timestamp = time();
            }
            $note_text = sprintf(
                __('Shipment tracking details received from server: %1$s - %2$s', 'drop-print'),
                esc_html($received_tracking_carrier ?: 'N/A'),
                esc_html($received_tracking_number)
            );
            $order->add_order_note($note_text);
            $tracking_provider_plugin_used = false;
            if (function_exists('wc_st_add_tracking_number')) {
                $existing_tracking_items = get_post_meta($order->get_id(), '_wc_shipment_tracking_items', true);
                if (!is_array($existing_tracking_items)) {
                    $existing_tracking_items = [];
                }
                $tracking_already_exists = false;
                foreach ($existing_tracking_items as $existing_item) {
                    if (isset($existing_item['tracking_number']) && $existing_item['tracking_number'] == $received_tracking_number) {
                        $tracking_already_exists = true;
                        break;
                    }
                }
                if (!$tracking_already_exists) {
                    wc_st_add_tracking_number($order->get_id(), $received_tracking_number, $received_tracking_carrier, $date_shipped_timestamp, $received_tracking_url);
                    $tracking_provider_plugin_used = true;
                }
            } elseif (class_exists('WC_Shipment_Tracking_Actions')) {
                $sta_instance = WC_Shipment_Tracking_Actions::instance();
                $existing_tracking_items = $sta_instance->get_tracking_items($order->get_id());
                $tracking_already_exists = false;
                foreach ($existing_tracking_items as $existing_item) {
                    if ($existing_item['tracking_number'] === $received_tracking_number) {
                        $tracking_already_exists = true;
                        break;
                    }
                }
                if (!$tracking_already_exists) {
                    $provider_slug = !empty($received_tracking_carrier) ? sanitize_title($received_tracking_carrier) : '';
                    $sta_instance->add_tracking_item($order->get_id(), [
                        'tracking_provider' => $provider_slug,
                        'custom_provider_name' => empty($provider_slug) && !empty($received_tracking_carrier) ? $received_tracking_carrier : '',
                        'tracking_number' => $received_tracking_number,
                        'tracking_link' => !empty($received_tracking_url) ? esc_url_raw($received_tracking_url) : '',
                        'date_shipped' => $date_shipped_timestamp,
                    ]);
                    $tracking_provider_plugin_used = true;
                }
            }
            if ($tracking_provider_plugin_used) {
                $order->add_order_note(__('Tracking information has also been added via the WooCommerce Shipment Tracking plugin.', 'drop-print'));
            }
            $order->save();
        }
        if ($meta_changed) {
            return new WP_REST_Response(array('success' => true, 'message' => 'Client order status meta updated.'), 200);
        } else {
            return new WP_REST_Response(array('success' => true, 'message' => 'No meta changes required for client order status.'), 200);
        }
    }
}
if (!function_exists('drop_print_server_register_user_connection_status_endpoint_client_cb')) {
    function drop_print_server_register_user_connection_status_endpoint_client_cb()
    {
        register_rest_route('drop-print-client/v1', '/user-connection-update', array(
            'methods' => WP_REST_Server::EDITABLE,
            'callback' => 'drop_print_handle_user_connection_status_update_client_cb',
            'permission_callback' => 'drop_print_check_user_connection_status_permissions_client_cb',
            'args' => array(
                'client_wp_user_id' => array(
                    'required' => true, 'validate_callback' => function ($param) {
                        return is_numeric($param) && $param > 0;
                    },
                    'sanitize_callback' => 'absint', 'description' => __('The WordPress User ID on the client site.', 'drop-print'),
                ),
                'pro_status' => array(
                    'required' => true, 'type' => 'boolean', 'description' => __('The new Pro status for the user.', 'drop-print'),
                    'sanitize_callback' => 'rest_sanitize_boolean',
                ),
                'billing_currency' => array(
                    'required' => false, 'type' => 'string', 'sanitize_callback' => 'sanitize_text_field',
                    'description' => __('Billing currency.', 'drop-print'),
                ),
                'available_media' => array(
                    'required' => false, 'type' => 'array', 'description' => __('Available media types.', 'drop-print'),
                    'items' => array('type' => 'object', 'properties' => array(
                        'id' => array('type' => 'string', 'sanitize_callback' => 'sanitize_key'),
                        'name' => array('type' => 'string', 'sanitize_callback' => 'sanitize_text_field'),
                    )),
                ),
            ),
        ));
    }
}
add_action('rest_api_init', 'drop_print_server_register_user_connection_status_endpoint_client_cb');
if (!function_exists('drop_print_check_user_connection_status_permissions_client_cb')) {
    function drop_print_check_user_connection_status_permissions_client_cb(WP_REST_Request $request)
    {
        $client_wp_user_id = $request->get_param('client_wp_user_id');
        if (empty($client_wp_user_id) || !is_numeric($client_wp_user_id) || $client_wp_user_id <= 0) {
            return new WP_Error('rest_invalid_client_user_id_user_status', __('Client WordPress User ID is missing or invalid in the request for user status update.', 'drop-print'), array('status' => 400));
        }
        $api_key_prefix = $request->get_header('X-Drop-Print-Client-Public-Key-Prefix');
        if (empty($api_key_prefix)) {
            return new WP_Error('rest_missing_auth_header_user_status', __('Missing required authentication header for user status update.', 'drop-print'), array('status' => 401));
        }
        $user_settings = drop_print_get_user_settings(absint($client_wp_user_id));
        if (empty($user_settings) || empty($user_settings['public_key_pem_b64']) || !is_string($user_settings['public_key_pem_b64'])) {
            return new WP_Error(
                'rest_client_user_auth_config_missing_user_status',
                sprintf(__('Client authentication user (ID: %d) not configured with server public key for user status update.', 'drop-print'), absint($client_wp_user_id)),
                array('status' => 403)
            );
        }
        $stored_public_key_b64 = $user_settings['public_key_pem_b64'];
        $stored_public_key_prefix = substr($stored_public_key_b64, 0, 42);
        if (hash_equals($stored_public_key_prefix, $api_key_prefix)) {
            return true;
        } else {
            return new WP_Error('rest_forbidden_user_status_update', __('Invalid authentication credentials for user status update.', 'drop-print'), array('status' => 403));
        }
    }
}
if (!function_exists('drop_print_handle_user_connection_status_update_client_cb')) {
    function drop_print_handle_user_connection_status_update_client_cb(WP_REST_Request $request)
    {
        $client_wp_user_id = $request->get_param('client_wp_user_id');
        $user = get_userdata($client_wp_user_id);
        if (!$user || !$user->exists()) {
            return new WP_Error('rest_user_not_found', __('Specified client WordPress user not found.', 'drop-print'), array('status' => 404));
        }
        $current_user_settings = drop_print_get_user_settings($client_wp_user_id);
        $meta_changed = false;
        $media_list_changed = false;
        $new_pro_status_param = $request->get_param('pro_status');
        if (isset($new_pro_status_param)) {
            $new_pro_status_bool = rest_sanitize_boolean($new_pro_status_param);
            if (!isset($current_user_settings['pro_status']) || $current_user_settings['pro_status'] !== (int) $new_pro_status_bool) {
                $current_user_settings['pro_status'] = (int) $new_pro_status_bool;
                $meta_changed = true;
            }
        }
        $new_billing_currency_param = $request->get_param('billing_currency');
        if (isset($new_billing_currency_param)) {
            $sanitized_currency = sanitize_text_field(strtoupper($new_billing_currency_param));
            if (!isset($current_user_settings['billing_currency']) || $current_user_settings['billing_currency'] !== $sanitized_currency) {
                $current_user_settings['billing_currency'] = $sanitized_currency;
                $meta_changed = true;
            }
        }
        $new_available_media_raw_param = $request->get_param('available_media');
        if (isset($new_available_media_raw_param) && is_array($new_available_media_raw_param)) {
            $sanitized_new_media = [];
            foreach ($new_available_media_raw_param as $item) {
                if (is_array($item) && isset($item['id'], $item['name']) && is_string($item['id']) && is_string($item['name'])) {
                    $sanitized_new_media[] = ['id' => sanitize_key($item['id']), 'name' => sanitize_text_field($item['name'])];
                }
            }
            if (!isset($current_user_settings['available_media']) || $current_user_settings['available_media'] !== $sanitized_new_media) {
                $current_user_settings['available_media'] = $sanitized_new_media;
                $current_user_settings['media_last_updated'] = time();
                $meta_changed = true;
                $media_list_changed = true;
            }
        }
        if ($meta_changed) {
            if (update_user_meta($client_wp_user_id, 'drop_print_user_settings', $current_user_settings)) {
                if ($media_list_changed && function_exists('drop_print_client_refresh_data_and_status')
                    && !wp_next_scheduled('drop_print_initial_user_data_sync_hook', array('user_id' => $client_wp_user_id))) {
                    wp_schedule_single_event(time() + 10, 'drop_print_initial_user_data_sync_hook', array('user_id' => $client_wp_user_id));
                }
                return new WP_REST_Response(array('success' => true, 'message' => __('User connection status updated successfully.', 'drop-print')), 200);
            } else {
                return new WP_Error('rest_user_meta_save_failed_status', __('Failed to save updated user connection status.', 'drop-print'), array('status' => 500));
            }
        } else {
            return new WP_REST_Response(array('success' => true, 'message' => __('No changes required for user connection status.', 'drop-print')), 200);
        }
    }
}
