<?php
use Dompdf\Dompdf;

function tulipwork_orderstock_check_supplier_emails($orders_by_supplier) {
    $suppliers_without_email = [];
    $processed_supplier_ids = []; // Pour suivre les fournisseurs déjà ajoutés
    foreach ($orders_by_supplier as $supplier => $items) {
        // Dans Pro, $supplier est un ID; dans la version gratuite, c'est un nom
        $supplier_id = is_numeric($supplier) ? intval($supplier) : 0;
        if (!$supplier_id) {
            // Dans la version gratuite, $supplier est un nom, récupérer l'ID
            $supplier_posts = get_posts(['post_type' => 'tulipwork_supplier', 'title' => $supplier, 'posts_per_page' => 1]);
            $supplier_id = !empty($supplier_posts) ? $supplier_posts[0]->ID : 0;
        }

        // Ignorer si $supplier_id est 0 (Unknown Supplier) ou déjà traité
        if (!$supplier_id || in_array($supplier_id, $processed_supplier_ids)) {
            continue;
        }

        // Vérifier si au moins un produit a une quantité non nulle
        $has_non_zero_quantity = false;
        foreach ($items as $item) {
            if ($item['quantity'] > 0) {
                $has_non_zero_quantity = true;
                break;
            }
        }
        if (!$has_non_zero_quantity) {
            error_log("OrderStock: Skipped supplier $supplier_id (no products with non-zero quantity)");
            continue;
        }

        $supplier_email = get_post_meta($supplier_id, '_email', true);
        // Vérifier si des adresses e-mail valides existent
        $valid_emails = [];
        if (!empty($supplier_email)) {
            $emails = array_map('trim', explode(',', $supplier_email));
            foreach ($emails as $email) {
                if (is_email($email)) {
                    $valid_emails[] = $email;
                }
            }
        }
        if (empty($valid_emails)) {
            $supplier_name = get_the_title($supplier_id);
            $edit_link = '<a href="' . esc_url(admin_url('post.php?post=' . $supplier_id . '&action=edit')) . '">' . esc_html__('Edit supplier', 'orderstock') . '</a>';
            $suppliers_without_email[] = esc_html($supplier_name) . ' (' . $edit_link . ')';
            $processed_supplier_ids[] = $supplier_id; // Marquer comme traité
        }
    }

    if (!empty($suppliers_without_email)) {
        return '<div class="notice notice-warning"><p>' . 
               esc_html__('Warning: The following suppliers have no email address specified and will not receive the order by email: ', 'orderstock') . 
               implode(', ', $suppliers_without_email) . '.</p></div>';
    }
    return '';
}

// Trier les produits par catégorie et nom
function tulipwork_orderstock_sort_order_items($items) {
    usort($items, function($a, $b) {
        // Récupérer les catégories de chaque produit
        $categories_a = wp_get_post_terms($a['product_id'], 'tulipwork_prod_cat', ['fields' => 'all']);
        $categories_b = wp_get_post_terms($b['product_id'], 'tulipwork_prod_cat', ['fields' => 'all']);
        
        // Trier les catégories par _name_lowercase et prendre la première
        $category_a = '';
        $category_b = '';
        if (!is_wp_error($categories_a) && !empty($categories_a)) {
            usort($categories_a, function($cat1, $cat2) {
                $name1 = get_term_meta($cat1->term_id, '_name_lowercase', true) ?: strtolower($cat1->name);
                $name2 = get_term_meta($cat2->term_id, '_name_lowercase', true) ?: strtolower($cat2->name);
                return strcmp($name1, $name2);
            });
            $category_a = get_term_meta($categories_a[0]->term_id, '_name_lowercase', true) ?: strtolower($categories_a[0]->name);
        }
        if (!is_wp_error($categories_b) && !empty($categories_b)) {
            usort($categories_b, function($cat1, $cat2) {
                $name1 = get_term_meta($cat1->term_id, '_name_lowercase', true) ?: strtolower($cat1->name);
                $name2 = get_term_meta($cat2->term_id, '_name_lowercase', true) ?: strtolower($cat2->name);
                return strcmp($name1, $name2);
            });
            $category_b = get_term_meta($categories_b[0]->term_id, '_name_lowercase', true) ?: strtolower($categories_b[0]->name);
        }
        
        // Si pas de catégorie, utiliser 'Uncategorized' pour un tri cohérent
        $category_a = $category_a ?: 'uncategorized';
        $category_b = $category_b ?: 'uncategorized';
        
        // Comparer les catégories
        if ($category_a !== $category_b) {
            return strcmp($category_a, $category_b);
        }
        
        // Si les catégories sont identiques, trier par nom de produit
        return strcmp(strtolower($a['product']), strtolower($b['product']));
    });
    
    return $items;
}

// Page principale "Place an Order"
function tulipwork_orderstock_order_page() {
    if (!current_user_can('tulipwork_orderstock_access_orders')) {
        wp_die(esc_html__('You do not have permission to access this page.', 'orderstock'));
    }

    $multi_store_enabled = tulipwork_orderstock_is_premium() && get_option('orderstock_pro_central_kitchen_enabled', 0);
    $selected_store = $multi_store_enabled && isset($_GET['store_filter']) ? intval($_GET['store_filter']) : 0;
    if (!apply_filters('tulipwork_orderstock_user_can_access_order_page', true, $selected_store)) {
        wp_die(esc_html__('You do not have permission to place orders for this store.', 'orderstock'));
    }

    global $wpdb;
    $success_message = '';
    $error_message = '';
    $notifications = '';
    $exclude_prices = false;

    if (!file_exists(plugin_dir_path(__DIR__) . 'vendor/autoload.php')) {
        echo '<div class="error"><p>' . esc_html__('Error: Dompdf library not found.', 'orderstock') . '</p></div>';
        return;
    }

    $suppliers = get_posts(['post_type' => 'tulipwork_supplier', 'posts_per_page' => -1]);
    $selected_supplier = isset($_GET['supplier_filter']) ? sanitize_text_field(wp_unslash($_GET['supplier_filter'])) : '';
    $transient_key = 'tulipwork_orders_' . get_current_user_id() . '_' . $selected_store;
    $manual_orders = isset($_POST['order']) ? array_map('floatval', wp_unslash($_POST['order'])) : (get_transient($transient_key) ?: []);
    $trend_score = isset($_POST['trend_score']) ? floatval($_POST['trend_score']) : 1;

    if (!isset($_POST['preview_orders']) && !isset($_POST['confirm_orders']) && !isset($_POST['apply_trend_score'])) {
        delete_transient($transient_key);
    }

    if (isset($_POST['apply_trend_score']) && 
        isset($_POST['order_nonce']) && 
        wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['order_nonce'])), 'tulipwork_order_nonce')) {
        delete_transient($transient_key);
        $args = [
            'post_type' => 'tulipwork_product',
            'posts_per_page' => -1,
            'post_status' => 'publish'
        ];
        if ($selected_supplier) {
            $args['meta_query'] = [
                'relation' => 'OR',
                [
                    'key' => '_supplier',
                    'value' => $selected_supplier,
                    'compare' => '='
                ]
            ];
            if (tulipwork_orderstock_is_premium()) {
                $args['meta_query'][] = [
                    'key' => '_suppliers',
                    'value' => $selected_supplier,
                    'compare' => 'LIKE'
                ];
            }
        }
        $products = get_posts($args);
        $new_manual_orders = [];

        foreach ($products as $product) {
            $main_supplier = get_post_meta($product->ID, '_supplier', true);
            $assigned_suppliers = tulipwork_orderstock_is_premium() ? get_post_meta($product->ID, '_suppliers', true) : [];
            if (!is_array($assigned_suppliers)) $assigned_suppliers = $main_supplier ? [$main_supplier] : [];
            $supplier = $selected_supplier ?: $main_supplier;
            if ($selected_supplier && $supplier !== $selected_supplier && !in_array($selected_supplier, $assigned_suppliers)) continue;

            $daily_sales = floatval(get_post_meta($product->ID, '_daily_sales', true));
            $stock = floatval(get_post_meta($product->ID, '_stock', true));
            $replenishment_period = floatval(get_post_meta($product->ID, '_replenishment_period', true));
            $critical_threshold = floatval(get_post_meta($product->ID, '_critical_threshold', true));
            $target_stock = floatval(get_post_meta($product->ID, '_target_stock', true));
            $packaging_quantity = floatval(get_post_meta($product->ID, '_packaging_quantity', true)) ?: 1;
            $max_quantity = floatval(get_post_meta($product->ID, '_max_quantity', true));
            $product_order_mode = get_post_meta($product->ID, '_product_order_mode', true) ?: 'default';
            $effective_mode = ($product_order_mode !== 'default') ? $product_order_mode : get_option('orderstock_order_mode', 'forecast');

            if ($effective_mode === 'forecast') {
                $quantity_to_order_raw = (($replenishment_period * $daily_sales) * $trend_score) - $stock;
            } else {
                $quantity_to_order_raw = ($stock <= $critical_threshold) ? ($target_stock * $trend_score) - $stock : 0;
            }
            $measured_units = ['kg', 'l', 'g'];
            $is_measured_unit = in_array(strtolower(get_post_meta($product->ID, '_packaging_unit', true)), $measured_units);
            if ($packaging_quantity == 0) {
                $quantity_to_order_units = $quantity_to_order_raw;
            } else {
                $quantity_to_order_units = $is_measured_unit ? $quantity_to_order_raw : ceil($quantity_to_order_raw / $packaging_quantity);
                if ($max_quantity && ($quantity_to_order_units * $packaging_quantity) > $max_quantity) {
                    $quantity_to_order_units = $is_measured_unit ? $max_quantity : floor($max_quantity / $packaging_quantity);
                }
            }
            $new_manual_orders[$product->ID] = $quantity_to_order_units;
        }

        set_transient($transient_key, $new_manual_orders, HOUR_IN_SECONDS);
        $manual_orders = $new_manual_orders;
        $success_message = '<div class="success-message">' . esc_html__('Trend Score applied successfully!', 'orderstock') . '</div>';
    }

    if (isset($_POST['preview_orders']) && 
        isset($_POST['order']) && 
        isset($_POST['order_nonce']) && 
        wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['order_nonce'])), 'tulipwork_order_nonce')) {
        $order_data = isset($_POST['order']) && is_array($_POST['order']) ? array_map('floatval', wp_unslash($_POST['order'])) : [];
        set_transient($transient_key, $order_data, HOUR_IN_SECONDS);
        $manual_orders = $order_data;
    }

    if (!tulipwork_orderstock_is_premium()) {
    do_action('tulipwork_orderstock_before_order_processing');
}

if (isset($_POST['confirm_orders']) && isset($_POST['order']) && check_admin_referer('tulipwork_order_nonce', 'order_nonce')) {
    $exclude_prices = isset($_POST['exclude_prices']) && $_POST['exclude_prices'] == 1;
    $desired_delivery_date = isset($_POST['desired_delivery_date']) ? sanitize_text_field(wp_unslash($_POST['desired_delivery_date'])) : '';
    $order_comments = isset($_POST['order_comments']) ? sanitize_textarea_field(wp_unslash($_POST['order_comments'])) : '';
    $orders_by_supplier = [];
    $order_data = isset($_POST['order']) && is_array($_POST['order']) ? array_map('floatval', wp_unslash($_POST['order'])) : [];
    $orders_processed = 0;
    $success_message = '';
    $error_message = '';

    set_transient($transient_key, $order_data, HOUR_IN_SECONDS);

    // Si Pro est actif, déléguer à orderstock_pro_extend_order_processing
    if (tulipwork_orderstock_is_premium()) {
        $pro_result = apply_filters('tulipwork_orderstock_before_order_processing', [
            'orders_processed' => 0,
            'success_message' => '',
            'error_message' => '',
            'notifications' => ''
        ]);

        $orders_processed = $pro_result['orders_processed'];
        $success_message .= $pro_result['success_message'];
        $error_message .= $pro_result['error_message'];
        $notifications .= $pro_result['notifications'];

        error_log("OrderStock: Success message after Pro processing: " . $success_message);
        error_log("OrderStock: Notifications after Pro processing: " . $notifications);
    } else {
        // Logique pour la version gratuite
        // Générer les PDF et e-mails de commande dans la langue de l'utilisateur qui passe la commande.
        $orderstock_locale_switched = switch_to_locale(get_user_locale());
        if ($orderstock_locale_switched && function_exists('orderstock_load_textdomain')) {
            unload_textdomain('orderstock');
            orderstock_load_textdomain();
        }
        foreach ($order_data as $product_id => $quantity) {
            $quantity = empty($quantity) ? 0 : floatval($quantity);
            if ($quantity > 0) {
                $product_id = intval($product_id);
                if (!get_post($product_id) || get_post_type($product_id) !== 'tulipwork_product') continue;
                $main_supplier_id = get_post_meta($product_id, '_supplier', true);
                $main_supplier_post = $main_supplier_id ? get_post($main_supplier_id) : null;
                $main_supplier = $main_supplier_post ? $main_supplier_post->post_title : __('Unknown Supplier', 'orderstock');
                $is_valid_supplier = true;
                $supplier_id = $main_supplier_id ?: '';

                if ($selected_supplier) {
                    $is_valid_supplier = ($selected_supplier == $main_supplier_id);
                    $supplier_id = $main_supplier_id;
                } else {
                    $supplier_id = $main_supplier_id ?: '';
                }

                if (!$is_valid_supplier) continue;

                $supplier_post = $supplier_id ? get_post($supplier_id) : null;
                $supplier = $supplier_post ? $supplier_post->post_title : __('Unknown Supplier', 'orderstock');

                $prices_excl_tax = get_post_meta($product_id, '_prices_excl_tax', true) ?: [];
                $price_excl_tax = isset($prices_excl_tax[$supplier_id]) ? floatval($prices_excl_tax[$supplier_id]) : 0;

                $packaging_quantity = get_post_meta($product_id, '_packaging_quantity', true) !== '' ? floatval(get_post_meta($product_id, '_packaging_quantity', true)) : 0;
                $packaging_unit = get_post_meta($product_id, '_packaging_unit', true);
                $product_title = get_the_title($product_id);
                $tax_rate = floatval(get_post_meta($product_id, '_tax_rate', true));
                $decimal_precision = intval(get_post_meta($product_id, '_decimal_precision', true)) ?: 0;
                $measured_units = ['kg', 'l', 'g'];
                $is_measured_unit = in_array(strtolower($packaging_unit), $measured_units);
                if ($packaging_quantity == 0) {
                    $adjusted_quantity = $quantity;
                    $total_units = $quantity;
                } else {
                    $adjusted_quantity = $is_measured_unit ? ($quantity > 0 && fmod($quantity, $packaging_quantity) == 0 ? $quantity : ceil($quantity / $packaging_quantity) * $packaging_quantity) : ceil($quantity);
                    $total_units = $is_measured_unit ? $adjusted_quantity : $adjusted_quantity * $packaging_quantity;
                }
                $total_excl_tax = $total_units * $price_excl_tax;
                $tax_amount = $total_excl_tax * ($tax_rate / 100);
                $total_incl_tax = $total_excl_tax + $tax_amount;
                $display_precision = $decimal_precision;
                $display_total = number_format($total_units, $display_precision, '.', '');
                $display_quantity = number_format($adjusted_quantity, $display_precision, '.', '');

$adjustment_notice = '';
if ($packaging_quantity > 0 && abs($quantity - $adjusted_quantity) > 0.0001 && $quantity > 0) {
    $raw_quantity_display = rtrim(number_format($quantity, max($decimal_precision, 2), '.', ''), '0');
    if ($is_measured_unit) {
        $adjustment_notice = sprintf(
            esc_html__('Product %s: Quantity adjusted from %s to %s %s to respect supplier packaging.', 'orderstock'),
            esc_html($product_title),
            esc_html($raw_quantity_display),
            esc_html($display_total),
            esc_html($packaging_unit ?: __('units', 'orderstock'))
        );
    } else {
        $adjustment_notice = sprintf(
            esc_html__('Product %s: Quantity adjusted from %s to %s (%s %s) to respect supplier packaging.', 'orderstock'),
            esc_html($product_title),
            esc_html($raw_quantity_display),
            esc_html($display_quantity),
            esc_html($display_total),
            esc_html($packaging_unit ?: __('units', 'orderstock'))
        );
    }
    error_log("OrderStock: Product $product_id, notification='$adjustment_notice'");
}

                $categories = wp_get_post_terms($product_id, 'tulipwork_prod_cat', ['fields' => 'names']);
                $category_list = !empty($categories) && !is_wp_error($categories) ? implode(', ', $categories) : 'Uncategorized';

            $orders_by_supplier[$supplier_id][] = [
                'product_id' => $product_id,
                'product' => $product_title,
                'quantity' => $display_quantity,
                'raw_quantity' => $quantity,
                'total' => $display_total,
                'unit' => $packaging_unit,
                'packaging_quantity' => $packaging_quantity,
                'price_excl_tax' => $price_excl_tax,
                'tax_rate' => $tax_rate,
                'total_excl_tax' => $total_excl_tax,
                'tax_amount' => $tax_amount,
                'total_incl_tax' => $total_incl_tax,
                'categories' => $category_list,
                'adjustment_notice' => $adjustment_notice
            ];
            }
        }

        // Generate and display email warning directly
        $email_warning = tulipwork_orderstock_check_supplier_emails($orders_by_supplier);
        if (!empty($email_warning)) {
            echo '<div class="orderstock-notifications">' . wp_kses_post($email_warning) . '</div>';
        }

        // Collect adjustment notices
        $adjustment_notices = '';
        foreach ($orders_by_supplier as $supplier_id => $items) {
            foreach ($items as $item) {
                if (!empty($item['adjustment_notice'])) {
                    $adjustment_notices .= '<div class="notice notice-info"><p>' . esc_html($item['adjustment_notice']) . '</p></div>';
                }
            }
        }
        if (!empty($adjustment_notices)) {
            echo '<div class="orderstock-notifications">' . wp_kses_post($adjustment_notices) . '</div>';
        }

        // Logique de génération de PDF pour la version gratuite
        $admin_emails_raw = get_option('tulipwork_orderstock_admin_emails', '');
        $admin_emails = !empty($admin_emails_raw) ? explode(',', $admin_emails_raw) : [get_option('admin_email')];
        $upload_dir_info = wp_upload_dir();
        $upload_dir = $upload_dir_info['basedir'] . '/tulipwork_orderstock/';
        if (!is_dir($upload_dir)) wp_mkdir_p($upload_dir);

        $company_name = get_option('tulipwork_orderstock_company_name', '');
        $company_address = get_option('tulipwork_orderstock_company_address', '');
        $company_phone = get_option('tulipwork_orderstock_company_phone', '');
        $company_email = get_option('tulipwork_orderstock_company_email', '');
        $company_opening_hours = get_option('tulipwork_orderstock_company_opening_hours', '');

        if ($multi_store_enabled && $selected_store) {
            $company_name = get_the_title($selected_store);
            $company_address = get_post_meta($selected_store, '_delivery_address', true) ?: $company_address;
            $company_phone = get_post_meta($selected_store, '_phone', true) ?: $company_phone;
            $company_email = get_post_meta($selected_store, '_email', true) ?: $company_email;
            $company_opening_hours = get_post_meta($selected_store, '_opening_hours', true) ?: $company_opening_hours;
        }

        $temp_files = [];
        foreach ($orders_by_supplier as $supplier_id => $items) {
            $items = tulipwork_orderstock_sort_order_items($items);
            $supplier_total_excl_tax = array_sum(array_column($items, 'total_excl_tax'));
            $supplier_tax_amounts = [];
            foreach ($items as $item) {
                $tax_rate_key = number_format($item['tax_rate'], 1, '.', '');
                $supplier_tax_amounts[$tax_rate_key] = ($supplier_tax_amounts[$tax_rate_key] ?? 0) + $item['tax_amount'];
            }
            $supplier_total_incl_tax = array_sum(array_column($items, 'total_incl_tax'));

            $dompdf = new Dompdf();

            $supplier_post = $supplier_id ? get_post($supplier_id) : null;
            $supplier = $supplier_post ? $supplier_post->post_title : __('Unknown Supplier', 'orderstock');
            $supplier_address = get_post_meta($supplier_id, '_address', true);
            $supplier_phone = get_post_meta($supplier_id, '_phone', true);
            $supplier_email = get_post_meta($supplier_id, '_email', true);

            $html = '<!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <title>' . esc_html__('Order for', 'orderstock') . ' ' . esc_html($supplier) . '</title>
                <style>
                    body { font-family: Arial, sans-serif; margin: 10mm; font-size: 10pt; }
                    h1 { font-size: 16pt; margin: 0 0 10px 0; }
                    h2 { font-size: 14pt; margin: 15px 0 5px 0; }
                    p { margin: 5px 0; font-size: 10pt; }
                    table { width: 100%; border-collapse: collapse; margin-bottom: 15px; font-size: 10pt; page-break-inside: auto; }
                    th, td { border: 1px solid #000; padding: 4px; text-align: left; }
                    th { background-color: #f0f0f0; font-weight: bold; }
                    tr { page-break-inside: avoid; page-break-after: auto; }
                    thead { display: table-header-group; }
                    h2 { page-break-before: avoid; }
                    table { page-break-before: auto; page-break-after: auto; }
                </style>
            </head>
            <body>';

            $html .= '<h1>' . esc_html__('Order for', 'orderstock') . ' ' . esc_html($supplier) . '</h1>';
            $html .= '<p>' . esc_html__('Order Date:', 'orderstock') . ' ' . esc_html(tulipwork_orderstock_i18n_datetime()) . '</p>';
            if (!empty($desired_delivery_date)) {
                $dd_ts = strtotime($desired_delivery_date);
                $dd_display = $dd_ts ? date_i18n(__('F j, Y', 'orderstock'), $dd_ts) : $desired_delivery_date;
                $html .= '<p style="font-weight:bold;text-decoration:underline;">' . esc_html__('Desired Delivery Date:', 'orderstock') . ' ' . esc_html($dd_display) . '</p>';
            }
            $html .= '<h2>' . esc_html__('Supplier Information', 'orderstock') . '</h2>';
            $html .= '<p><strong>' . esc_html__('Name:', 'orderstock') . '</strong> ' . esc_html($supplier) . '</p>';
            if ($supplier_address) $html .= '<p><strong>' . esc_html__('Address:', 'orderstock') . '</strong> ' . nl2br(esc_html($supplier_address)) . '</p>';
            if ($supplier_phone) $html .= '<p><strong>' . esc_html__('Phone:', 'orderstock') . '</strong> ' . esc_html($supplier_phone) . '</p>';
            if ($supplier_email) {
                $emails = array_map('trim', explode(',', $supplier_email));
                $valid_emails = array_filter($emails, 'is_email');
                if (!empty($valid_emails)) {
                    $html .= '<p><strong>' . esc_html__('Email:', 'orderstock') . '</strong> ' . esc_html(implode(', ', $valid_emails)) . '</p>';
                }
            }
            $html .= '<h2>' . esc_html__('Company Information', 'orderstock') . '</h2>';
            $html .= '<p><strong>' . esc_html__('Name:', 'orderstock') . '</strong> ' . esc_html($company_name) . '</p>';
            $html .= '<p><strong>' . esc_html__('Delivery Address:', 'orderstock') . '</strong> ' . nl2br(esc_html($company_address)) . '</p>';
            if ($company_opening_hours) $html .= '<p><strong>' . esc_html__('Opening Hours:', 'orderstock') . '</strong> ' . nl2br(esc_html($company_opening_hours)) . '</p>';
            if ($company_phone) $html .= '<p><strong>' . esc_html__('Phone:', 'orderstock') . '</strong> ' . esc_html($company_phone) . '</p>';
            if ($company_email) $html .= '<p><strong>' . esc_html__('Email:', 'orderstock') . '</strong> ' . esc_html($company_email) . '</p>';
            $html .= '<h2>' . esc_html__('Order Details', 'orderstock') . '</h2>';

            if ($exclude_prices) {
                $html .= '<table>';
                $html .= '<thead><tr><th>' . esc_html__('Product', 'orderstock') . '</th><th>' . esc_html__('Quantity', 'orderstock') . '</th></tr></thead>';
                $html .= '<tbody>';
                foreach ($items as $index => $item) {
                    $product_id = $item['product_id'];
                    $quantity = floatval($item['quantity']);
                    $total = floatval($item['total']);
                    $unit = $item['unit'] ?: 'unit';
                    $packaging_quantity = floatval(get_post_meta($product_id, '_packaging_quantity', true)) ?: 0;
                    $decimal_precision = intval(get_post_meta($product_id, '_decimal_precision', true)) ?: 0;
                    $measured_units = ['kg', 'l', 'g'];
                    $is_measured_unit = in_array(strtolower($unit), $measured_units);
                    $display_total = tulipwork_orderstock_i18n_number($total);
                    $unit_display = ($unit === 'unit') ? ($total > 1 ? __('units', 'orderstock') : __('unit', 'orderstock')) : $unit;

                    if ($is_measured_unit && $packaging_quantity > 0) {
                        $display_packaging_quantity = tulipwork_orderstock_i18n_number($packaging_quantity);
                        $quantity_display = sprintf(__('%1$s %2$s total (%3$s x %4$s %5$s)', 'orderstock'), $display_total, $unit, $quantity, $display_packaging_quantity, $unit);
                    } elseif ($packaging_quantity > 1) {
                        $quantity_display = sprintf(__('%1$s (%2$s %3$s total)', 'orderstock'), $quantity, $display_total, $unit_display);
                    } else {
                        $quantity_display = "$display_total $unit_display";
                    }
                    $html .= '<tr><td>' . esc_html($item['product']) . '</td><td>' . esc_html($quantity_display) . '</td></tr>';
                }
                $html .= '</tbody></table>';
            } else {
                $html .= '<table>';
                $html .= '<thead><tr><th>' . esc_html__('Product', 'orderstock') . '</th><th>' . esc_html__('Quantity', 'orderstock') . '</th><th>' . esc_html__('Price Excl. Tax', 'orderstock') . '</th><th>' . esc_html__('Tax Rate', 'orderstock') . '</th><th>' . esc_html__('Total Excl. Tax', 'orderstock') . '</th></tr></thead>';
                $html .= '<tbody>';
                foreach ($items as $item) {
                    $product_id = $item['product_id'];
$quantity = floatval($item['quantity']);
$total = floatval($item['total']);
$unit = $item['unit'] ?: 'unit';
$packaging_quantity = floatval(get_post_meta($product_id, '_packaging_quantity', true)) ?: 0;
$decimal_precision = intval(get_post_meta($product_id, '_decimal_precision', true)) ?: 0;
$measured_units = ['kg', 'l', 'g'];
$is_measured_unit = in_array(strtolower($unit), $measured_units);
$display_total = tulipwork_orderstock_i18n_number($total);
$unit_display = ($unit === 'unit') ? ($total > 1 ? __('units', 'orderstock') : __('unit', 'orderstock')) : $unit;
if ($is_measured_unit && $packaging_quantity > 0) {
    $display_packaging_quantity = tulipwork_orderstock_i18n_number($packaging_quantity);
    $calculated_quantity = $total / $packaging_quantity; // Calculer le nombre de paquets
    $display_calculated_quantity = number_format_i18n($calculated_quantity, 0); // Pas de décimales pour le nombre de paquets
    $quantity_display = sprintf(__('%1$s %2$s total (%3$s x %4$s %5$s)', 'orderstock'), $display_total, $unit, $display_calculated_quantity, $display_packaging_quantity, $unit);
} elseif ($is_measured_unit) {
    $quantity_display = sprintf(__('%1$s %2$s total', 'orderstock'), $display_total, $unit);
} elseif ($packaging_quantity > 1) {
    $quantity_display = sprintf(__('%1$s (%2$s %3$s total)', 'orderstock'), $quantity, $display_total, $unit_display);
} else {
    $quantity_display = "$display_total $unit_display";
}
                    $html .= '<tr>';
                    $html .= '<td>' . esc_html($item['product']) . '</td>';
                    $html .= '<td>' . esc_html($quantity_display) . '</td>';
                    $html .= '<td>' . esc_html(number_format_i18n($item['price_excl_tax'], 2)) . '</td>';
                    $html .= '<td>' . esc_html($item['tax_rate'] == 0 ? esc_html__('No Tax', 'orderstock') : number_format($item['tax_rate'], 1, '.', '') . '%') . '</td>';
                    $html .= '<td>' . esc_html(number_format_i18n($item['total_excl_tax'], 2)) . '</td>';
                    $html .= '</tr>';
                }
                $html .= '<tr><td colspan="4"><strong>' . esc_html__('Total Excl. Tax', 'orderstock') . '</strong></td><td><strong>' . esc_html(number_format_i18n($supplier_total_excl_tax, 2)) . '</strong></td></tr>';
                foreach ($supplier_tax_amounts as $rate => $amount) {
                    $html .= '<tr><td colspan="4"><strong>' . esc_html__('VAT', 'orderstock') . ' ' . esc_html($rate) . '%</strong></td><td><strong>' . esc_html(number_format_i18n($amount, 2)) . '</strong></td></tr>';
                }
                $html .= '<tr><td colspan="4"><strong>' . esc_html__('Total Incl. Tax', 'orderstock') . '</strong></td><td><strong>' . esc_html(number_format_i18n($supplier_total_incl_tax, 2)) . '</strong></td></tr>';
                $html .= '</tbody></table>';
            }

            if (!empty($order_comments)) {
                $html .= '<h2>' . esc_html__('Comments:', 'orderstock') . '</h2>';
                $html .= '<p>' . nl2br(esc_html($order_comments)) . '</p>';
            }

            $html .= '</body></html>';

            try {
                // Désactiver temporairement les avertissements PHP
                $error_reporting = error_reporting();
                error_reporting($error_reporting & ~E_NOTICE & ~E_WARNING);
                
                $dompdf->loadHtml(apply_filters('tulipwork_orderstock_order_pdf_content', $html, $supplier_id, $items, $exclude_prices));
                $dompdf->setPaper('A4', 'portrait');
                $dompdf->render();
                $pdf_content = $dompdf->output();
                
                // Restaurer le niveau de rapport d'erreurs
                error_reporting($error_reporting);
                
                if ($pdf_content === false || $pdf_content === null) {
                    error_log("OrderStock: PDF generation failed for supplier $supplier | HTML length: " . strlen($html));
                    throw new Exception('Failed to generate valid PDF content');
                }
                error_log("OrderStock: PDF generated successfully for supplier $supplier | Content length: " . strlen($pdf_content));
            } catch (Exception $e) {
                error_log("OrderStock: Failed to generate PDF for supplier $supplier: " . $e->getMessage() . " | HTML length: " . strlen($html));
                $error_message .= '<div class="error-message">' . esc_html__('Failed to generate PDF content for supplier: ', 'orderstock') . esc_html($supplier) . '</div>';
                continue;
            }

            // Suffixe aléatoire : le fichier reste 7 jours dans uploads (durée des jetons),
            // un nom basé sur le seul horodatage serait devinable par URL directe.
            $pdf_filename = 'order_' . sanitize_title($supplier) . '_' . time() . '_' . wp_generate_password(12, false) . '.pdf';
            $pdf_file = $upload_dir . $pdf_filename;
            if (!file_put_contents($pdf_file, $pdf_content)) {
                $error_message .= '<div class="error-message">' . esc_html__('Failed to save PDF file for supplier: ', 'orderstock') . ' (check folder permissions)</div>';
                continue;
            }

            $valid_supplier_emails = [];
            if (!empty($supplier_email)) {
                $emails = array_map('trim', explode(',', $supplier_email));
                foreach ($emails as $email) {
                    if (is_email($email)) {
                        $valid_supplier_emails[] = $email;
                    }
                }
            }
            // Inclure le(s) e-mail(s) de l'entreprise / du magasin pour qu'il reçoive une copie de sa commande.
            $company_emails = array_filter(array_map('trim', explode(',', (string) $company_email)), 'is_email');
            $recipients = array_merge($admin_emails, $company_emails, $valid_supplier_emails);
            $recipients = array_unique(array_filter($recipients));
            if (empty($recipients)) {
                $error_message .= '<div class="error-message">' . esc_html__('No valid email recipients for supplier: ', 'orderstock') . esc_html($supplier) . '</div>';
                wp_delete_file($pdf_file);
                continue;
            }

            $attachments = [$pdf_file];
            // Email texte brut : décoder TOUTES les entités, apostrophes comprises
            // (ENT_QUOTES). Le décodage par défaut (ENT_NOQUOTES) laissait passer
            // &#039; — « 2 rue Jeanne d&#039;Arc » dans le corps du mail, et un nom
            // d'entreprise à apostrophe aurait encodé le sujet.
            $subject = wp_specialchars_decode(sprintf(__('New Order from %s', 'orderstock'), $company_name), ENT_QUOTES);
            // Ajouter les horaires d'ouverture juste sous l'adresse de livraison (sans modifier le gabarit traduit).
            $mail_delivery_address = esc_html($company_address);
            if ($company_opening_hours) {
                $mail_delivery_address .= "\n- " . __('Opening Hours:', 'orderstock') . ' ' . esc_html($company_opening_hours);
            }
            $message = sprintf(
                __("Dear supplier,\n\nPlease find attached the order details from %1\$s.\n\nCompany Information:\n- Name: %1\$s\n- Delivery Address: %2\$s\n- Phone: %3\$s\n- Email: %4\$s\n\nThank you,\n%1\$s Team", 'orderstock'),
                esc_html($company_name),
                $mail_delivery_address,
                esc_html($company_phone),
                esc_html($company_email)
            );
            $message = wp_specialchars_decode($message, ENT_QUOTES);

            // Lien de confirmation de réception pour le fournisseur.
            $confirm_token = tulipwork_orderstock_store_confirm_token([
                'recipients'      => $recipients,
                'supplier_emails' => $valid_supplier_emails,
                'company_name'    => $company_name,
                'supplier_name'   => $supplier,
                'locale'          => get_user_locale(),
            ]);
            $message .= "\n\n" . tulipwork_orderstock_order_email_confirmation_text(tulipwork_orderstock_confirm_url($confirm_token));

            $mail_sent = wp_mail($recipients, $subject, $message, tulipwork_orderstock_reply_to_header($company_email), $attachments);
            if ($mail_sent) {
                $orders_processed++;
                $download_url = add_query_arg(
                    [
                        'action' => 'tulipwork_orderstock_download_pdf',
                        'filename' => $pdf_filename,
                        'supplier_id' => $supplier_id,
                    ],
                    admin_url('admin-ajax.php')
                );
                $download_url = wp_nonce_url($download_url, 'tulipwork_orderstock_download_pdf');

                $pdf_token = wp_generate_uuid4();
                $pdf_tokens = get_option('tulipwork_orderstock_pdf_tokens', []);
                $pdf_tokens[$pdf_token] = [
                    'file' => $pdf_file,
                    'filename' => $pdf_filename,
                    'expires' => time() + (7 * DAY_IN_SECONDS)
                ];
                update_option('tulipwork_orderstock_pdf_tokens', $pdf_tokens);
                error_log("OrderStock: Stored PDF token $pdf_token for file: $pdf_file");

                $whatsapp_url = add_query_arg('tulipwork_pdf_download', $pdf_token, home_url('/'));
                $whatsapp_message = sprintf(
                    __('New order from %s for %s. Download the order details here: %s', 'orderstock'),
                    $company_name,
                    $supplier,
                    $whatsapp_url
                );

                $success_message .= '<div class="orderstock-notice orderstock-notice--success">' . 
                                    sprintf(esc_html__('Order for %s sent successfully.', 'orderstock'), esc_html($supplier)) . 
                                    // target=_blank : en PWA iOS (standalone), un PDF ouvert dans la vue courante n'a aucun bouton retour et bloque l'app ; _blank ouvre le panneau Safari intégré avec un bouton OK. Symptôme si retiré : PDF plein écran sans retour possible dans la web app.
                                    ' <a href="' . esc_url($download_url) . '" target="_blank" rel="noopener" data-filename="' . esc_attr($pdf_filename) . '" class="orderstock-share-download button button-secondary">' . esc_html__('Download PDF', 'orderstock') . '</a>' .
                                    ' <a href="https://wa.me/?text=' . rawurlencode($whatsapp_message) . '" target="_blank" class="button button-secondary">' . esc_html__('Share via WhatsApp', 'orderstock') . '</a>' . 
                                    '</div>';
            } else {
                $error_message .= '<div class="error-message">' . esc_html__('Failed to send email for supplier: ', 'orderstock') . esc_html($supplier) . '</div>';
                wp_delete_file($pdf_file);
            }
        }

        if ($orders_processed > 0) {
            $success_message = ($orders_processed > 1 ? '<div class="orderstock-notice orderstock-notice--success">' . 
                               sprintf(esc_html__('Orders sent successfully for %d supplier(s)!', 'orderstock'), $orders_processed) . 
                               '</div>' : '') . $success_message;
            delete_transient($transient_key);
        } else if (empty($error_message) && !empty($orders_by_supplier)) {
            $error_message = '<div class="orderstock-notice orderstock-notice--error">' . esc_html__('No orders were processed successfully.', 'orderstock') . '</div>';
        }

        error_log("OrderStock: Final success message: " . $success_message);
        error_log("OrderStock: Final error message: " . $error_message);
        if (!empty($orderstock_locale_switched)) restore_previous_locale();
    }
}

    wp_enqueue_style('tulipwork_orderstock-admin-css', plugins_url('orderstock/includes/css/orderstock-admin.css'), [], OrderStock::get_version());

    ?>
    <div class="wrap">
        <h1><?php esc_html_e('Place an Order', 'orderstock'); ?></h1>
        <div class="order-filters">
        <?php do_action('tulipwork_orderstock_order_page_before_form'); ?>
        <form method="get" action="">
            <input type="hidden" name="page" value="tulipwork_orderstock-order">
            <?php if ($multi_store_enabled) { ?>
                <input type="hidden" name="store_filter" value="<?php echo esc_attr($selected_store); ?>">
            <?php } ?>
            <label for="supplier_filter"><?php esc_html_e('Filter by Supplier', 'orderstock'); ?>:</label>
            <select id="supplier_filter" name="supplier_filter" onchange="this.form.submit()">
                <option value=""><?php esc_html_e('All Suppliers', 'orderstock'); ?></option>
                <?php foreach ($suppliers as $supplier) { ?>
                    <option value="<?php echo esc_attr($supplier->ID); ?>" <?php selected($selected_supplier, $supplier->ID); ?>><?php echo esc_html($supplier->post_title); ?></option>
                <?php } ?>
            </select>
        </form>
        <?php if ($multi_store_enabled && !$selected_store) { ?>
            <p style="color: #d63638;"><?php esc_html_e('Please select a store to view and order products.', 'orderstock'); ?></p>
        <?php } else { ?>
            <form method="post" action="">
                <?php wp_nonce_field('tulipwork_order_nonce', 'order_nonce'); ?>
                    <label for="trend_score"><?php esc_html_e('Trend Score', 'orderstock'); ?>:</label>
                    <input type="number" id="trend_score" name="trend_score" value="<?php echo esc_attr($trend_score); ?>" step="0.1" min="0" />
                    <input type="submit" name="apply_trend_score" class="button button-secondary" value="<?php esc_attr_e('Apply Trend Score', 'orderstock'); ?>" style="margin-left: 10px;" />
                    <small style="margin-left: 10px;">
                        <?php esc_html_e('Adjusts order quantities based on trends (e.g., 1.2 = +20%, 0.8 = -20%). Default is 1.', 'orderstock'); ?>
                    </small>
                </div>
                <?php if ($success_message) echo wp_kses_post($success_message); ?>
                <?php if ($error_message) echo wp_kses_post($error_message); ?>
                <?php if ($notifications) echo wp_kses_post($notifications); ?>
                <?php
                    if (!tulipwork_orderstock_is_premium()) {
                        $args = [
                            'post_type' => 'tulipwork_product',
                            'posts_per_page' => -1,
                            'post_status' => 'publish',
                            'orderby' => 'title',
                            'order' => 'ASC'
                        ];
                        if ($selected_supplier) {
                            $args['meta_query'] = [
                                'relation' => 'OR',
                                [
                                    'key' => '_supplier',
                                    'value' => $selected_supplier,
                                    'compare' => '='
                                ],
                                [
                                    'key' => '_supplier',
                                    'compare' => 'NOT EXISTS'
                                ]
                            ];
                        }
                        $products = get_posts($args);
                    
                        $sorted_products = [];
                        foreach ($products as $product) {
                            $categories = wp_get_post_terms($product->ID, 'tulipwork_prod_cat', ['fields' => 'all']);
                            $category_name = 'uncategorized';
                            if (!is_wp_error($categories) && !empty($categories)) {
                                usort($categories, function($cat1, $cat2) {
                                    $name1 = get_term_meta($cat1->term_id, '_name_lowercase', true) ?: strtolower($cat1->name);
                                    $name2 = get_term_meta($cat2->term_id, '_name_lowercase', true) ?: strtolower($cat2->name);
                                    return strcmp($name1, $name2);
                                });
                                $category_name = get_term_meta($categories[0]->term_id, '_name_lowercase', true) ?: strtolower($categories[0]->name);
                            }
                            $sorted_products[] = [
                                'product' => $product,
                                'category' => $category_name,
                                'title' => strtolower($product->post_title)
                            ];
                        }
                    
                        usort($sorted_products, function($a, $b) {
                            if ($a['category'] !== $b['category']) {
                                return strcmp($a['category'], $b['category']);
                            }
                            return strcmp($a['title'], $b['title']);
                        });
                    
                        if (!empty($sorted_products)) {
                            $global_order_mode = get_option('orderstock_order_mode', 'forecast');
                            $order_mode = $global_order_mode;
                            ?>
                            <h2><?php esc_html_e('All Products', 'orderstock'); ?></h2>
                            <p class="orderstock-info">
                                <?php 
                                $mode_label = ($global_order_mode === 'forecast') ? __('Forecast Mode', 'orderstock') : __('Threshold Mode', 'orderstock');
                                esc_html_e('Global calculation mode: ', 'orderstock');
                                echo esc_html($mode_label);
                                ?>
                                <br>
                                <?php 
                                if ($global_order_mode === 'forecast') {
                                    esc_html_e('Quantities are estimated as: (Replenishment Period × Daily Sales × Trend Score) - Current Stock, adjusted for packaging and max quantity.', 'orderstock');
                                } else {
                                    esc_html_e('Quantities are estimated as: (Target Stock × Trend Score) - Current Stock (if Current Stock < Critical Threshold), adjusted for packaging and max quantity.', 'orderstock');
                                }
                                ?>
                                <br>
                                <?php esc_html_e('Product-specific modes override global settings.', 'orderstock'); ?>
                            </p>
                            <table class="wp-list-table widefat fixed striped">
                                <thead>
                                    <tr>
                                        <th><?php esc_html_e('Product', 'orderstock'); ?></th>
                                        <th class="order-page-categories"><?php esc_html_e('Categories', 'orderstock'); ?></th>
                                        <th class="order-page-packaging"><?php esc_html_e('Packaging', 'orderstock'); ?></th>
                                        <th class="order-page-price-excl-tax"><?php esc_html_e('Price Excl. Tax', 'orderstock'); ?></th>
                                        <th><?php esc_html_e('Current Stock', 'orderstock'); ?></th>
                                        <th><?php esc_html_e('Quantity to Order', 'orderstock'); ?></th>
                                        <th class="order-page-calc-mode"><?php esc_html_e('Calculation Mode', 'orderstock'); ?></th>
                                        <th class="order-page-supplier"><?php esc_html_e('Main Supplier', 'orderstock'); ?></th>
                                    </tr>
                                </thead>
                                <tbody>
                                <?php 
                                foreach ($sorted_products as $sorted_product) {
                                    $product = $sorted_product['product'];
                                    $main_supplier = get_post_meta($product->ID, '_supplier', true);
                                    $supplier_post = $main_supplier ? get_post($main_supplier) : null;
                                    $supplier_name = $supplier_post ? $supplier_post->post_title : esc_html__('Unknown Supplier', 'orderstock');
                    
                                    if ($selected_supplier && $main_supplier && $main_supplier !== $selected_supplier) {
                                        continue;
                                    }
                    
                                    $prices_excl_tax = get_post_meta($product->ID, '_prices_excl_tax', true) ?: [];
                                    $price_excl_tax = isset($prices_excl_tax[$selected_supplier ?: $main_supplier]) ? floatval($prices_excl_tax[$selected_supplier ?: $main_supplier]) : 0;
                                    $daily_sales = floatval(get_post_meta($product->ID, '_daily_sales', true));
                                    $stock = floatval(get_post_meta($product->ID, '_stock', true));
                                    $replenishment_period = floatval(get_post_meta($product->ID, '_replenishment_period', true));
                                    $critical_threshold = floatval(get_post_meta($product->ID, '_critical_threshold', true));
                                    $target_stock = floatval(get_post_meta($product->ID, '_target_stock', true));
                                    $packaging_unit = get_post_meta($product->ID, '_packaging_unit', true);
                                    $packaging_quantity = get_post_meta($product->ID, '_packaging_quantity', true) !== '' ? floatval(get_post_meta($product->ID, '_packaging_quantity', true)) : 0;
                                    $max_quantity = floatval(get_post_meta($product->ID, '_max_quantity', true));
                                    $decimal_precision = intval(get_post_meta($product->ID, '_decimal_precision', true)) ?: 0;
                                    $product_order_mode = get_post_meta($product->ID, '_product_order_mode', true) ?: 'default';
                                    $effective_mode = ($product_order_mode !== 'default') ? $product_order_mode : $order_mode;
                                    $display_packaging_quantity = number_format($packaging_quantity, $decimal_precision, '.', '');
                    
                                    $display_stock = number_format($stock, $decimal_precision, '.', '');
                    
                                    $measured_units = ['kg', 'l', 'g'];
                                    $is_measured_unit = in_array(strtolower($packaging_unit), $measured_units);
                    
                                    if ($effective_mode === 'forecast') {
                                        $quantity_to_order_raw = (($replenishment_period * $daily_sales) * $trend_score) - $stock;
                                    } else {
                                        $quantity_to_order_raw = ($stock <= $critical_threshold) ? ($target_stock * $trend_score) - $stock : 0;
                                    }
                                    if ($quantity_to_order_raw < 0) $quantity_to_order_raw = 0;
                    
                                    if ($packaging_quantity == 0) {
                                        $quantity_to_order_units = $quantity_to_order_raw;
                                        $manual_quantity = isset($manual_orders[$product->ID]) ? floatval($manual_orders[$product->ID]) : $quantity_to_order_units;
                                        $adjusted_manual_quantity = $manual_quantity;
                                        $total_quantity = $manual_quantity;
                                    } else {
                                        $quantity_to_order_units = $is_measured_unit ? $quantity_to_order_raw : ceil($quantity_to_order_raw / $packaging_quantity);
                                        if ($max_quantity && ($quantity_to_order_units * $packaging_quantity) > $max_quantity) {
                                            $quantity_to_order_units = $is_measured_unit ? $max_quantity : floor($max_quantity / $packaging_quantity);
                                        }
                                        $manual_quantity = isset($manual_orders[$product->ID]) ? floatval($manual_orders[$product->ID]) : ($is_measured_unit ? $quantity_to_order_units : $quantity_to_order_units);
                                        $adjusted_manual_quantity = $is_measured_unit ? ($manual_quantity > 0 && fmod($manual_quantity, $packaging_quantity) == 0 ? $manual_quantity : ceil($manual_quantity / $packaging_quantity) * $packaging_quantity) : $manual_quantity;
                                        $total_quantity = $is_measured_unit ? $adjusted_manual_quantity : $adjusted_manual_quantity * $packaging_quantity;
                                    }
                    
                                    $display_precision = $decimal_precision;
                                    $display_total_quantity = number_format($total_quantity, $display_precision, '.', '');
                                    $display_manual_quantity = number_format($adjusted_manual_quantity, $display_precision, '.', '');
                                    $unit_display = ($packaging_unit === 'unit') ? (floatval($total_quantity) > 1 ? __('units', 'orderstock') : __('unit', 'orderstock')) : ($packaging_unit ?: 'N/A');
                                    $unit_singular = ($packaging_unit === 'unit') ? __('unit', 'orderstock') : ($packaging_unit ?: 'N/A');
                                    $unit_plural   = ($packaging_unit === 'unit') ? __('units', 'orderstock') : ($packaging_unit ?: 'N/A');
                                    global $wp_locale;
                                    $decimal_sep   = isset($wp_locale->number_format['decimal_point']) ? $wp_locale->number_format['decimal_point'] : '.';
                                    $thousands_sep = isset($wp_locale->number_format['thousands_sep']) ? $wp_locale->number_format['thousands_sep'] : '';
                                    error_log("OrderStock: Product {$product->ID}, manual_quantity=$manual_quantity, adjusted_manual_quantity=$adjusted_manual_quantity, total_quantity=$total_quantity, display_manual_quantity=$display_manual_quantity, display_total_quantity=$display_total_quantity, display_precision=$display_precision, is_measured_unit=" . ($is_measured_unit ? 'true' : 'false'));
                                    $categories = wp_get_post_terms($product->ID, 'tulipwork_prod_cat', ['fields' => 'names']);
                                    $category_list = !empty($categories) && !is_wp_error($categories) ? implode(', ', $categories) : esc_html__('Uncategorized', 'orderstock');
                                    $display_packaging_quantity = tulipwork_orderstock_i18n_number(floor($packaging_quantity) == $packaging_quantity ? number_format($packaging_quantity, 0, '.', '') : rtrim(number_format($packaging_quantity, 2, '.', ''), '0'));
                                    $packaging_unit_labels = [
                                        'unit' => __('units', 'orderstock'),
                                        'pack' => __('packs', 'orderstock'),
                                        'box'  => __('boxes', 'orderstock'),
                                        'kg'   => __('kg', 'orderstock'),
                                        'L'    => __('L', 'orderstock'),
                                    ];
                                    $packaging_hint_unit = $packaging_unit_labels[$packaging_unit] ?? $packaging_unit;
                                    ?>
                                    <tr>
                                        <td>
                                            <?php echo esc_html($product->post_title); ?>
                                            <?php if ($packaging_quantity > 0) : ?>
                                                <br><small class="order-packaging-hint"><?php echo esc_html(sprintf(__('per %1$s %2$s', 'orderstock'), $display_packaging_quantity, $packaging_hint_unit)); ?></small>
                                            <?php endif; ?>
                                        </td>
                                        <td class="order-page-categories"><?php echo esc_html($category_list); ?></td>
                                        <td class="order-page-packaging"><?php echo esc_html($display_packaging_quantity . ' ' . ($packaging_unit ?: 'N/A')); ?></td>
                                        <td class="order-page-price-excl-tax"><?php echo esc_html(number_format_i18n($price_excl_tax, 2)); ?></td>
                                        <td><?php echo esc_html($display_stock); ?></td>
                                        <td>
                                            <div class="quantity-container">
                                                <input type="number" name="order[<?php echo esc_attr($product->ID); ?>]" value="<?php echo esc_attr(tulipwork_orderstock_trim_zeros($display_manual_quantity)); ?>" step="any" min="0" class="order-quantity"
                                                    data-calc="<?php echo esc_attr($effective_mode === 'forecast' ? "(($replenishment_period * $daily_sales) * $trend_score) - $stock" : "($stock <= $critical_threshold ? ($target_stock * $trend_score) - $stock : 0)"); ?>"
                                                    data-packaging="<?php echo esc_attr($packaging_quantity); ?>"
                                                    data-unit="<?php echo esc_attr($packaging_unit); ?>"
                                                    data-precision="<?php echo esc_attr($display_precision); ?>"
                                                    data-decimal="<?php echo esc_attr($decimal_sep); ?>"
                                                    data-thousands="<?php echo esc_attr($thousands_sep); ?>"
                                                    data-unit-singular="<?php echo esc_attr($unit_singular); ?>"
                                                    data-unit-plural="<?php echo esc_attr($unit_plural); ?>"
                                                    data-max="<?php echo esc_attr($max_quantity); ?>" />
                                                <span class="quantity-unit"><?php echo esc_html('(' . tulipwork_orderstock_i18n_number($display_total_quantity) . ' ' . ($unit_display ?: 'N/A') . ')'); ?></span>
                                            </div>
                                        </td>
                                        <td class="order-page-calc-mode"><?php
                                            $calc_mode_labels = ['forecast' => __('Forecast', 'orderstock'), 'threshold' => __('Threshold', 'orderstock')];
                                            echo esc_html($calc_mode_labels[$effective_mode] ?? ucfirst($effective_mode));
                                        ?></td>
                                        <td class="order-page-supplier"><?php echo esc_html($supplier_name); ?></td>
                                    </tr>
                                <?php } ?>
                                </tbody>
                            </table>
                            <p><input type="submit" name="preview_orders" class="button button-secondary" value="<?php esc_attr_e('Preview Order and Total Cost', 'orderstock'); ?>" /></p>
                <?php } else { ?>
                    <p><?php esc_html_e('No products available to order.', 'orderstock'); ?></p>
                <?php }
                } else {
                    do_action('tulipwork_orderstock_order_page_before_products', $manual_orders);
                }

                if (isset($_POST['preview_orders']) && isset($_POST['order']) && check_admin_referer('tulipwork_order_nonce', 'order_nonce')) {
                    global $orderstock_pro_handling_preview;
                    if (tulipwork_orderstock_is_premium() && !empty($orderstock_pro_handling_preview)) {
                        return;
                    }
                
                    error_log("OrderStock: Starting order preview for supplier $selected_supplier");
                    $exclude_prices = isset($_POST['exclude_prices']) && $_POST['exclude_prices'] == 1;
                    $orders_by_supplier = [];
                    $order_data = isset($_POST['order']) && is_array($_POST['order']) ? array_map('floatval', wp_unslash($_POST['order'])) : [];
                    $global_total_excl_tax = 0;
                    $global_total_incl_tax = 0;
                    error_log("OrderStock: Order data = " . print_r($order_data, true));
                
                    $has_unknown_supplier = false;
                    foreach ($order_data as $product_id => $quantity) {
                        $main_supplier_id = get_post_meta($product_id, '_supplier', true);
                        if (!$main_supplier_id) {
                            $has_unknown_supplier = true;
                            break;
                        }
                    }
                
                    foreach ($order_data as $product_id => $quantity) {
                        $quantity = empty($quantity) ? 0 : floatval($quantity);
                        error_log("OrderStock: Processing product $product_id with quantity $quantity");
                        if ($quantity <= 0) {
                            error_log("OrderStock: Skipped product $product_id (quantity <= 0)");
                            continue;
                        }
                
                        $product_id = intval($product_id);
                        if (!get_post($product_id) || get_post_type($product_id) !== 'tulipwork_product') {
                            error_log("OrderStock: Skipped product $product_id (invalid post or type)");
                            continue;
                        }
                
                        $main_supplier_id = get_post_meta($product_id, '_supplier', true);
                        $main_supplier_post = $main_supplier_id ? get_post($main_supplier_id) : null;
                        $main_supplier = $main_supplier_post ? $main_supplier_post->post_title : __('Unknown Supplier', 'orderstock');
                
                        $is_valid_supplier = true;
                        $supplier_id = $main_supplier_id ?: '';
                        if ($selected_supplier) {
                            error_log("OrderStock: Checking supplier filter $selected_supplier for product $product_id");
                            if (tulipwork_orderstock_is_premium()) {
                                $assigned_suppliers = get_post_meta($product_id, '_suppliers', true) ?: [];
                                if (!is_array($assigned_suppliers)) {
                                    $assigned_suppliers = $main_supplier_id ? [$main_supplier_id] : [];
                                }
                                $assigned_suppliers = array_map('intval', array_filter($assigned_suppliers, 'is_numeric'));
                                error_log("OrderStock: Product $product_id, main_supplier=$main_supplier_id, assigned_suppliers=" . implode(',', $assigned_suppliers));
                                $is_valid_supplier = ($selected_supplier == $main_supplier_id || in_array($selected_supplier, $assigned_suppliers));
                                $supplier_id = $selected_supplier;
                                $supplier = $main_supplier_post ? $main_supplier_post->post_title : __('Unknown Supplier', 'orderstock');
                                error_log("OrderStock: Product $product_id is_valid_supplier=" . ($is_valid_supplier ? 'true' : 'false'));
                            } else {
                                $is_valid_supplier = ($selected_supplier == $main_supplier_id);
                                $supplier_id = $main_supplier_id;
                                $supplier = $main_supplier;
                                error_log("OrderStock: Product $product_id (non-Pro), is_valid_supplier=" . ($is_valid_supplier ? 'true' : 'false'));
                            }
                        } else {
                            $supplier_id = $main_supplier_id ?: '';
                            $supplier = $main_supplier;
                            error_log("OrderStock: No supplier filter, using main supplier $main_supplier_id for product $product_id");
                        }
                
                        if (!$is_valid_supplier) {
                            error_log("OrderStock: Excluded product $product_id (invalid supplier)");
                            continue;
                        }
                
                        $prices_excl_tax = get_post_meta($product_id, '_prices_excl_tax', true) ?: [];
                        $price_excl_tax = isset($prices_excl_tax[$supplier_id]) ? floatval($prices_excl_tax[$supplier_id]) : 0;
                        error_log("OrderStock: Product $product_id, final price_excl_tax=$price_excl_tax");
                
                        $packaging_quantity = get_post_meta($product_id, '_packaging_quantity', true) !== '' ? floatval(get_post_meta($product_id, '_packaging_quantity', true)) : 0;
                        $packaging_unit = get_post_meta($product_id, '_packaging_unit', true);
                        $product_title = get_the_title($product_id);
                        $tax_rate = floatval(get_post_meta($product_id, '_tax_rate', true));
                        $decimal_precision = intval(get_post_meta($product_id, '_decimal_precision', true)) ?: 0;
                        $measured_units = ['kg', 'l', 'g'];
                        $is_measured_unit = in_array(strtolower($packaging_unit), $measured_units);
                        if ($packaging_quantity == 0) {
                            $adjusted_quantity = $quantity;
                            $total_units = $quantity;
                        } else {
                            if ($is_measured_unit) {
                                $adjusted_quantity = $quantity > 0 && fmod($quantity, $packaging_quantity) == 0 ? $quantity : ceil($quantity / $packaging_quantity) * $packaging_quantity;
                                $total_units = $adjusted_quantity;
                            } else {
                                $adjusted_quantity = ceil($quantity);
                                $total_units = $adjusted_quantity * $packaging_quantity;
                            }
                        }
                        $total_excl_tax = $total_units * $price_excl_tax;
                        $tax_amount = $total_excl_tax * ($tax_rate / 100);
                        $total_incl_tax = $total_excl_tax + $tax_amount;
                        $display_precision = $decimal_precision;
                        $display_total = number_format($total_units, $display_precision, '.', '');
                        $display_quantity = number_format($adjusted_quantity, $display_precision, '.', '');
                
$adjustment_notice = '';
if ($packaging_quantity > 0 && abs($quantity - $adjusted_quantity) > 0.0001 && $quantity > 0) {
    $raw_quantity_display = number_format($quantity, $decimal_precision, '.', '');
    if ($is_measured_unit) {
        $adjustment_notice = sprintf(
            esc_html__('Product %s: Quantity adjusted from %s to %s %s to respect supplier packaging.', 'orderstock'),
            esc_html($product_title),
            esc_html($raw_quantity_display),
            esc_html($display_total),
            esc_html($packaging_unit ?: __('units', 'orderstock'))
        );
    } else {
        $adjustment_notice = sprintf(
            esc_html__('Product %s: Quantity adjusted from %s to %s (%s %s) to respect supplier packaging.', 'orderstock'),
            esc_html($product_title),
            esc_html($raw_quantity_display),
            esc_html($display_quantity),
            esc_html($display_total),
            esc_html($packaging_unit ?: __('units', 'orderstock'))
        );
    }
    error_log("OrderStock: Product $product_id, notification='$adjustment_notice'");
}
                
                        $categories = wp_get_post_terms($product_id, 'tulipwork_prod_cat', ['fields' => 'names']);
                        $category_list = !empty($categories) && !is_wp_error($categories) ? implode(', ', $categories) : 'Uncategorized';
                
                        $orders_by_supplier[$supplier_id][] = [
                            'product_id' => $product_id,
                            'product' => $product_title,
                            'quantity' => $display_quantity,
                            'raw_quantity' => $quantity,
                            'total' => $display_total,
                            'unit' => $packaging_unit,
                            'price_excl_tax' => $price_excl_tax,
                            'tax_rate' => $tax_rate,
                            'total_excl_tax' => $total_excl_tax,
                            'tax_amount' => $tax_amount,
                            'total_incl_tax' => $total_incl_tax,
                            'categories' => $category_list,
                            'adjustment_notice' => $adjustment_notice
                        ];
                
                        $global_total_excl_tax += $total_excl_tax;
                        $global_total_incl_tax += $total_incl_tax;
                
                        error_log("OrderStock: Included product $product_id in order for supplier $supplier_id, quantity=$quantity, adjusted_quantity=$adjusted_quantity, total_units=$total_units, display_total=$display_total");
                    }
                
                    $below_threshold_suppliers = [];
                    foreach ($orders_by_supplier as $supplier_id => $items) {
                        $supplier_total_excl_tax = array_sum(array_column($items, 'total_excl_tax'));
                        $supplier_post = $supplier_id ? get_post($supplier_id) : null;
                        $supplier_title = $supplier_post ? $supplier_post->post_title : __('Unknown Supplier', 'orderstock');
                        $minimum_order_threshold = floatval(get_post_meta($supplier_id, '_min_order_threshold', true));
                        if ($minimum_order_threshold > 0 && $supplier_total_excl_tax < $minimum_order_threshold) {
                            $below_threshold_suppliers[$supplier_id] = [
                                'total_excl_tax' => $supplier_total_excl_tax,
                                'threshold' => $minimum_order_threshold,
                                'title' => $supplier_title
                            ];
                        }
                    }
                
                    if (!empty($below_threshold_suppliers)) {
                        $warning_message = '<div class="notice notice-warning"><p>' . esc_html__('Warning: some suppliers are below their minimum order threshold. Adjust quantities or confirm the order anyway if desired.', 'orderstock') . '</p><ul>';
                        foreach ($below_threshold_suppliers as $supplier_id => $data) {
                            $warning_message .= '<li>' . sprintf(
                                esc_html__('Supplier %s: Total %s is below the minimum threshold of %s.', 'orderstock'),
                                esc_html($data['title']),
                                esc_html(number_format_i18n($data['total_excl_tax'], 2)),
                                esc_html(number_format_i18n($data['threshold'], 2))
                            ) . '</li>';
                        }
                        $warning_message .= '</ul></div>';
                        error_log("OrderStock: Suppliers below minimum threshold: " . print_r($below_threshold_suppliers, true));
                    }
                
                    if ($has_unknown_supplier || !empty($orders_by_supplier)) {
                        echo '<div class="orderstock-notifications">';
                        if ($has_unknown_supplier) {
                            echo '<div class="notice notice-warning"><p>' . esc_html__('Some products in the order do not have a supplier assigned and will be listed as "Unknown Supplier". Consider assigning suppliers for better tracking.', 'orderstock') . '</p></div>';
                        }
                        echo tulipwork_orderstock_check_supplier_emails($orders_by_supplier);
                        foreach ($orders_by_supplier as $supplier_id => $items) {
                            foreach ($items as $item) {
                                if (!empty($item['adjustment_notice'])) {
                                    echo '<div class="notice notice-info"><p>' . esc_html($item['adjustment_notice']) . '</p></div>';
                                }
                            }
                        }
                        echo '</div>';
                    }
                
                    if (empty($orders_by_supplier)) {
                        echo '<p class="notice notice-info">' . esc_html__('No order preview generated because all quantities are set to 0.', 'orderstock') . '</p>';
                    } else {
                        ?>
                        <h2><?php esc_html_e('Order Preview', 'orderstock'); ?></h2>
                        <p><?php esc_html_e('Below is a preview of the orders that will be placed. Please review the details before confirming.', 'orderstock'); ?></p>
                        <?php if (!empty($warning_message)) echo wp_kses_post($warning_message); ?>
                        <?php 
                        foreach ($orders_by_supplier as $supplier_id => $items) {
                            $items = tulipwork_orderstock_sort_order_items($items);
                            $supplier_post = $supplier_id ? get_post($supplier_id) : null;
                            $supplier_title = $supplier_post ? $supplier_post->post_title : __('Unknown Supplier', 'orderstock');
                        ?>
                                <h3>
                                    <?php printf(esc_html__('Order for %s', 'orderstock'), esc_html($supplier_title)); ?>
                                </h3>
                            <table class="wp-list-table widefat fixed striped">
                                <thead>
                                    <tr>
                                        <th><?php esc_html_e('Product', 'orderstock'); ?></th>
                                        <th><?php esc_html_e('Quantity Ordered', 'orderstock'); ?></th>
                                        <?php if (!$exclude_prices) { ?>
                                            <th><?php esc_html_e('Price Excl. Tax', 'orderstock'); ?></th>
                                            <th><?php esc_html_e('Tax Rate', 'orderstock'); ?></th>
                                            <th><?php esc_html_e('Total Excl. Tax', 'orderstock'); ?></th>
                                            <th><?php esc_html_e('Total Incl. Tax', 'orderstock'); ?></th>
                                        <?php } ?>
                                    </tr>
                                </thead>
                                <tbody>
                                    <?php 
                                    $supplier_total_excl_tax = 0;
                                    $supplier_total_incl_tax = 0;
                                    foreach ($items as $item) { 
                                        $supplier_total_excl_tax += $item['total_excl_tax'];
                                        $supplier_total_incl_tax += $item['total_incl_tax'];
                                        ?>
                                        <tr>
                                            <td><?php echo esc_html($item['product']); ?></td>
                                            <td><?php echo esc_html(tulipwork_orderstock_i18n_number($item['quantity']) . ' (' . tulipwork_orderstock_i18n_number($item['total']) . ' ' . ($item['unit'] === 'unit' ? (floatval($item['total']) > 1 ? __('units', 'orderstock') : __('unit', 'orderstock')) : $item['unit']) . ')'); ?></td>
                                            <?php if (!$exclude_prices) { ?>
                                                <td><?php echo esc_html(number_format_i18n($item['price_excl_tax'], 2)); ?></td>
                                                <td><?php echo esc_html($item['tax_rate'] . '%'); ?></td>
                                                <td><?php echo esc_html(number_format_i18n($item['total_excl_tax'], 2)); ?></td>
                                                <td><?php echo esc_html(number_format_i18n($item['total_incl_tax'], 2)); ?></td>
                                            <?php } ?>
                                        </tr>
                                    <?php } ?>
                                </tbody>
                                <?php if (!$exclude_prices) { ?>
                                    <tfoot>
                                        <tr>
                                            <td colspan="4"><?php esc_html_e('Total', 'orderstock'); ?></td>
                                            <td><?php echo esc_html(number_format_i18n($supplier_total_excl_tax, 2)); ?></td>
                                            <td><?php echo esc_html(number_format_i18n($supplier_total_incl_tax, 2)); ?></td>
                                        </tr>
                                    </tfoot>
                                <?php } ?>
                            </table>
                        <?php } ?>
                        <?php if (!$exclude_prices) { ?>
                            <h3><?php esc_html_e('Overall Totals', 'orderstock'); ?></h3>
                            <table class="wp-list-table widefat fixed striped">
                                <tr>
                                    <th><?php esc_html_e('Total Excl. Tax', 'orderstock'); ?></th>
                                    <td><?php echo esc_html(number_format_i18n($global_total_excl_tax, 2)); ?></td>
                                </tr>
                                <tr>
                                    <th><?php esc_html_e('Total Incl. Tax', 'orderstock'); ?></th>
                                    <td><?php echo esc_html(number_format_i18n($global_total_incl_tax, 2)); ?></td>
                                </tr>
                            </table>
                        <?php } ?>
                        <p>
                            <label for="exclude_prices">
                                <input type="checkbox" id="exclude_prices" name="exclude_prices" value="1" <?php checked(isset($_POST['exclude_prices']) && $_POST['exclude_prices'] == 1); ?> />
                                <?php esc_html_e('Exclude prices from order preview and PDF', 'orderstock'); ?>
                            </label>
                        </p>
                        <?php
                        $desired_delivery_date_value = isset($_POST['desired_delivery_date']) ? sanitize_text_field(wp_unslash($_POST['desired_delivery_date'])) : '';
                        $order_comments_value = isset($_POST['order_comments']) ? sanitize_textarea_field(wp_unslash($_POST['order_comments'])) : '';
                        ?>
                        <p>
                            <label for="desired_delivery_date"><strong><?php esc_html_e('Desired delivery date', 'orderstock'); ?></strong></label><br>
                            <input type="date" id="desired_delivery_date" name="desired_delivery_date" value="<?php echo esc_attr($desired_delivery_date_value); ?>" min="<?php echo esc_attr(date_i18n('Y-m-d')); ?>" />
                            <br><span class="description"><?php esc_html_e('Leave empty for delivery as soon as possible.', 'orderstock'); ?></span>
                        </p>
                        <p>
                            <label for="order_comments"><strong><?php esc_html_e('Comments', 'orderstock'); ?></strong></label><br>
                            <textarea id="order_comments" name="order_comments" rows="3" style="width:100%;max-width:500px;"><?php echo esc_textarea($order_comments_value); ?></textarea>
                        </p>
                        <?php
                        $supplier_names = [];
                        foreach (array_keys($orders_by_supplier) as $preview_supplier_id) {
                            $supplier_names[] = $preview_supplier_id ? get_the_title($preview_supplier_id) : __('Unknown Supplier', 'orderstock');
                        }
                        $supplier_list = implode(', ', $supplier_names);
                        ?>
                        <div style="margin:15px 0;padding:12px 15px;border-left:4px solid #dba617;background:#fcf9e8;font-weight:bold;">
                            <?php
                            if (count($orders_by_supplier) > 1) {
                                printf(esc_html__('Multi-supplier order: %s', 'orderstock'), esc_html($supplier_list));
                            } else {
                                printf(esc_html__('Supplier: %s', 'orderstock'), esc_html($supplier_list));
                            }
                            ?>
                        </div>
                        <p>
                            <input type="submit" name="confirm_orders" class="button button-primary" value="<?php esc_attr_e('Confirm and Send Orders', 'orderstock'); ?>" />
                        </p>
                        <?php
                    }
                }
                        ?>
                        <?php do_action('tulipwork_orderstock_order_page_after_form'); ?>
                    </form>
                <?php } ?>
            </div>
            <?php
        }
?>