<?php
/**
 * Bizmart Core — Products AJAX Handlers.
 *
 * @package Bizmart
 * @license GPL-2.0-or-later
 */
if (!defined('ABSPATH')) exit;

// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.NonceVerification.Recommended, WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.InterpolatedNotPrepared, PluginCheck.Security.DirectDB.UnescapedDBParameter, WordPress.PHP.DevelopmentFunctions.error_log_error_log, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.DB.SlowDBQuery.slow_db_query_meta_key

// ============================================================
// HELPER FUNCTIONS
// ============================================================

if (!function_exists('bizmart_get_variation_title')) {
/**
 * Get a formatted title for a product variation
 */
function bizmart_get_variation_title($product_id, $variation_id) {
    $variation = wc_get_product($variation_id);
    if (!$variation) return 'Unknown';

    $parent_product = wc_get_product($product_id);
    if (!$parent_product) return 'Unknown';

    $attributes = $variation->get_attributes();
    if (empty($attributes)) return 'Variation';

    $title_parts = [];
    foreach ($attributes as $name => $value) {
        // Clean attribute name
        $clean_name = ucwords(str_replace(['pa_', '-'], [' ', ' '], sanitize_title_with_dashes($name)));
        $title_parts[] = $clean_name . ': ' . ucfirst(str_replace('-', ' ', $value));
    }

    return implode(' | ', $title_parts);
}
}

// ============================================================
// PRODUCT AJAX HANDLERS
// ============================================================

// Quick Update Product (inline editing from products table)
add_action('wp_ajax_bizmart_quick_update_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(__('Unauthorized', 'bizmart-cost-of-goods'), 403);

    $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
    if (!$product_id) wp_send_json_error(__('Invalid product ID', 'bizmart-cost-of-goods'));

    $product = wc_get_product($product_id);
    if (!$product) wp_send_json_error(__('Product not found', 'bizmart-cost-of-goods'));

    // Handle Price Updates
    if (isset($_POST['regular_price'])) {
        $price = sanitize_text_field(wp_unslash($_POST['regular_price']));
        // If empty, it remove the price; if numeric, update.
        $product->set_regular_price($price);
    }

    if (isset($_POST['sale_price'])) {
        $price = sanitize_text_field(wp_unslash($_POST['sale_price']));
        $product->set_sale_price($price);
    }

    // Note: Purchase Price is custom meta
    if (isset($_POST['purchase_price'])) {
        $price = sanitize_text_field(wp_unslash($_POST['purchase_price']));
        $meta_key = '_purchase_price'; // Default key
        update_post_meta($product_id, '_purchase_price', $price);
        // Also update standard WC Cost of Goods if present?
        update_post_meta($product_id, '_alg_wc_cog_cost', $price);
    }

    // Handle Stock Status - initially set on object
    if (isset($_POST['stock_status'])) {
        $status = sanitize_text_field(wp_unslash($_POST['stock_status']));
        if (in_array($status, ['instock', 'outofstock', 'onbackorder'])) {
            $product->set_stock_status($status);
        }
    }

    // Handle Post Status
    if (isset($_POST['post_status'])) {
        $status = sanitize_text_field(wp_unslash($_POST['post_status']));
        $allowed_statuses = array_keys(get_post_statuses());
        if (in_array($status, $allowed_statuses)) {
             $product->set_status($status);
        }
    }

    try {
        $product->save();
    } catch (Exception $e) {
        wp_send_json_error(__('Save error: ', 'bizmart-cost-of-goods') . $e->getMessage());
    }
    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    // Force stock status update AFTER save to override WC automatic calculation (if quantity > 0)
    if (isset($_POST['stock_status'])) {
        $status = sanitize_text_field(wp_unslash($_POST['stock_status']));
        if (in_array($status, ['instock', 'outofstock', 'onbackorder'])) {
            update_post_meta($product_id, '_stock_status', $status);
            wc_delete_product_transients($product_id);
            // Refresh object status for response
            $product->set_stock_status($status);
        }
    }

    // Clear cached statistics so dashboard and products page show fresh values
    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'quick_update_product');
    } else {
        $blog_id = get_current_blog_id();
        delete_transient('bizmart_inventory_totals_v9_' . $blog_id);
        delete_transient('bizmart_inventory_totals_v8_' . $blog_id);
        delete_transient('bizmart_products_stats_v5_' . $blog_id);
        delete_transient('bizmart_dash_missing_purchase_prices_v2');
    }

    // Return updated data for UI refresh
    wp_send_json_success([
        'message' => __('Product updated', 'bizmart-cost-of-goods'),
        'regular_price' => $product->get_regular_price(),
        'sale_price' => $product->get_sale_price(),
        'price_html' => $product->get_price_html(),
        'stock_status' => $product->get_stock_status(),
        'status' => $product->get_status()
    ]);
});

add_action('wp_ajax_bizmart_dashboard_update_margin_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(['message' => __('Unauthorized', 'bizmart-cost-of-goods')], 403);

    $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
    $purchase_raw = isset($_POST['purchase_price']) ? sanitize_text_field(wp_unslash($_POST['purchase_price'])) : '';
    $selling_raw = isset($_POST['selling_price']) ? sanitize_text_field(wp_unslash($_POST['selling_price'])) : '';
    $apply_to_variations = isset($_POST['apply_to_variations']) && sanitize_text_field(wp_unslash($_POST['apply_to_variations'])) === '1';
    $purchase_price = is_numeric($purchase_raw) ? round((float) $purchase_raw, 2) : -1;
    $selling_price = is_numeric($selling_raw) ? round((float) $selling_raw, 2) : -1;

    if ($product_id <= 0) {
        wp_send_json_error(['message' => __('Invalid product ID', 'bizmart-cost-of-goods')], 400);
    }
    if ($purchase_price < 0 || $selling_price <= 0) {
        wp_send_json_error(['message' => __('Enter valid purchase and selling prices.', 'bizmart-cost-of-goods')], 400);
    }

    $product = wc_get_product($product_id);
    if (!$product) {
        wp_send_json_error(['message' => __('Product not found', 'bizmart-cost-of-goods')], 404);
    }

    global $wpdb;
    $price_history_table = $wpdb->prefix . 'bizmart_price_history';
    $price_history_columns = (function_exists('bizmart_table_exists') && bizmart_table_exists('bizmart_price_history') && function_exists('bizmart_get_table_columns'))
        ? bizmart_get_table_columns($price_history_table)
        : [];
    $updated_ids = [];
    $targets = [$product_id];
    if ($apply_to_variations && $product->is_type('variable')) {
        $targets = array_map('intval', $product->get_children());
        if (empty($targets)) {
            $targets = [$product_id];
        }
        update_post_meta($product_id, '_purchase_price', wc_format_decimal($purchase_price));
        update_post_meta($product_id, '_alg_wc_cog_cost', wc_format_decimal($purchase_price));
        bizmart_sync_purchase_price_to_products_table($product_id, $purchase_price);
    }

    foreach ($targets as $target_id) {
        $target_id = (int) $target_id;
        if ($target_id <= 0) {
            continue;
        }

        $target_product = wc_get_product($target_id);
        if (!$target_product) {
            continue;
        }

        update_post_meta($target_id, '_purchase_price', wc_format_decimal($purchase_price));
        update_post_meta($target_id, '_alg_wc_cog_cost', wc_format_decimal($purchase_price));
        bizmart_sync_purchase_price_to_products_table($target_id, $purchase_price);

        $target_product->set_regular_price(wc_format_decimal($selling_price));
        $target_product->set_sale_price('');
        if (method_exists($target_product, 'set_price')) {
            $target_product->set_price(wc_format_decimal($selling_price));
        }
        $target_product->save();

        if (!empty($price_history_columns)) {
            $row = [
                'product_id' => $target_id,
                'purchase_price' => $purchase_price,
                'selling_price' => $selling_price,
                'invoice_id' => 0,
                'created_at' => current_time('mysql'),
            ];
            $formats = ['%d', '%f', '%f', '%d', '%s'];
            if (in_array('quantity', $price_history_columns, true)) {
                $row['quantity'] = 1;
                $formats[] = '%f';
            }
            if (in_array('source', $price_history_columns, true)) {
                $row['source'] = 'manual_dashboard';
                $formats[] = '%s';
            }
            if (in_array('supplier_id', $price_history_columns, true)) {
                $row['supplier_id'] = null;
                $formats[] = '%d';
            }
            $wpdb->insert($price_history_table, $row, $formats);
        }

        if (function_exists('bizmart_check_price_alerts')) {
            bizmart_check_price_alerts($target_id, $purchase_price, $selling_price);
            $alerts = get_transient('bizmart_price_alerts');
            if (is_array($alerts)) {
                $key = 'margin_' . $target_id;
                $margin = $selling_price > 0 ? round((($selling_price - $purchase_price) / $selling_price) * 100, 2) : 0;
                $threshold = (float) bizmart_get_option('biz_margin_alert_threshold', 10);
                if ($margin >= $threshold) {
                    unset($alerts[$key]);
                    set_transient('bizmart_price_alerts', $alerts, DAY_IN_SECONDS);
                }
            }
        }

        if (function_exists('bizmart_invalidate_product_metrics_cache')) {
            bizmart_invalidate_product_metrics_cache($target_id, 'dashboard_margin_update');
        }

        $updated_ids[] = $target_id;
    }

    if (empty($updated_ids)) {
        wp_send_json_error(['message' => __('Pricing update failed.', 'bizmart-cost-of-goods')], 500);
    }

    $margin_pct = $selling_price > 0 ? round((($selling_price - $purchase_price) / $selling_price) * 100, 2) : 0;

    wp_send_json_success([
        'message' => __('Pricing updated', 'bizmart-cost-of-goods'),
        'product_id' => $product_id,
        'purchase_price' => $purchase_price,
        'selling_price' => $selling_price,
        'margin_pct' => $margin_pct,
        'applied_to_variations' => $apply_to_variations ? 1 : 0,
        'updated_ids' => $updated_ids,
        'price_html' => $product->get_price_html(),
    ]);
});

add_action('wp_ajax_bizmart_dashboard_save_margin_threshold', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(['message' => __('Unauthorized', 'bizmart-cost-of-goods')], 403);

    $threshold_raw = isset($_POST['threshold']) ? sanitize_text_field(wp_unslash($_POST['threshold'])) : '10';
    $threshold = is_numeric($threshold_raw) ? (float) $threshold_raw : 10;
    $threshold = max(0, min(100, $threshold));

    if (function_exists('bizmart_update_option')) {
        bizmart_update_option('biz_margin_alert_threshold', $threshold);
    } else {
        update_option('biz_margin_alert_threshold', $threshold);
    }

    wp_send_json_success([
        'threshold' => $threshold,
        'message' => __('Margin threshold updated', 'bizmart-cost-of-goods'),
    ]);
});

// Quick Update Price
add_action('wp_ajax_bizmart_quick_update_price', 'bizmart_quick_update_price_handler');
function bizmart_quick_update_price_handler() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
    $price_raw = isset($_POST['price']) ? sanitize_text_field(wp_unslash($_POST['price'])) : 0;
    $price = is_numeric($price_raw) ? (float) $price_raw : 0;

    if (!$product_id || $price < 0) {
        wp_send_json_error('Invalid data');
    }

    update_post_meta($product_id, '_regular_price', $price);
    update_post_meta($product_id, '_price', $price);

    // Optional integration: price history is implemented in Bizmart Addon.
    if (function_exists('bizmart_store_price_history')) {
        bizmart_store_price_history($product_id, 0, $price, null);
    }

    wc_delete_product_transients($product_id);

    wp_send_json_success('Price updated to ' . $price);
}

// Add Product (legacy bizmart_products table)
add_action('wp_ajax_bizmart_add_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(__('Unauthorized', 'bizmart-cost-of-goods'), 403);

    global $wpdb;
    $table = $wpdb->prefix . 'bizmart_products';
    $name = sanitize_text_field(wp_unslash($_POST['name'] ?? ''));
    $sku = sanitize_text_field(wp_unslash($_POST['sku'] ?? ''));
    $default_purchase_price_raw = isset($_POST['default_purchase_price']) ? sanitize_text_field(wp_unslash($_POST['default_purchase_price'])) : 0;
    $default_purchase_price = is_numeric($default_purchase_price_raw) ? (float) $default_purchase_price_raw : 0;

    if (empty($name) || empty($sku)) wp_send_json_error(__('Name and SKU are required.', 'bizmart-cost-of-goods'), 400);

    $existing = $wpdb->get_var($wpdb->prepare("SELECT id FROM {$table} WHERE sku = %s", $sku));
    if ($existing) wp_send_json_error(__('A product with this SKU already exists.', 'bizmart-cost-of-goods'), 409);

    $res = $wpdb->insert($table, [
        'name' => $name,
        'sku' => $sku,
        'default_purchase_price' => $default_purchase_price,
        'selling_price' => $default_purchase_price,
    ], ['%s','%s','%f','%f']);

    if ($res) wp_send_json_success([
        'id'=>$wpdb->insert_id,
        'name'=>$name,
        'sku'=>$sku,
        'default_purchase_price'=>$default_purchase_price,
        'selling_price'=>$default_purchase_price
    ]);
    wp_send_json_error($wpdb->last_error);
});

// Search Products (Select2)
add_action('wp_ajax_bizmart_search_products', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(__('Unauthorized', 'bizmart-cost-of-goods'), 403);

    $q = isset($_REQUEST['q']) ? sanitize_text_field(wp_unslash((string) $_REQUEST['q'])) : '';
    if (empty($q)) wp_send_json_success(['results'=>[]]);

    $args = [
        'post_type' => ['product','product_variation'],
        'posts_per_page' => 25,
        's' => $q,
        'fields' => 'ids',
        'post_status' => ['publish', 'draft'],
    ];
    $product_ids = get_posts($args);
    $results = [];

    foreach($product_ids as $pid){
        $product = wc_get_product($pid);
        if(!$product) continue;

        $sku = $product->get_sku() ?: 'N/A';
        $name = $product->get_name();
        $regular_price = $product->get_regular_price();
        $status = $product->get_status();

        // Add draft indicator to name
        $status_indicator = ($status === 'draft') ? ' [BROUILLON]' : '';

        $last_prices = function_exists('bizmart_get_last_prices') ? bizmart_get_last_prices($pid) : ['purchase_price' => 0, 'selling_price' => 0];

        $purchase_price = isset($last_prices['purchase_price']) ? (float) $last_prices['purchase_price'] : 0;
        $selling_price  = isset($last_prices['selling_price']) ? (float) $last_prices['selling_price'] : 0;
        if ($selling_price <= 0 && $regular_price !== '') {
            $selling_price = (float) $regular_price;
        }
        $stock_quantity = $product->get_stock_quantity();

        $results[] = [
            'id' => $pid,
            'text' => $name . ' (' . $sku . ')' . $status_indicator,
            'sku' => $sku,
            'name' => $name,
            'price' => $regular_price ? (float)$regular_price : 0,
            'purchase_price' => $purchase_price,
            'selling_price' => $selling_price,
            'status' => $status,
            'type' => $product->get_type(),
            'manage_stock' => (bool) $product->get_manage_stock(),
            'stock_quantity' => $stock_quantity !== null ? (float) $stock_quantity : null,
            'stock_status' => $product->get_stock_status(),
        ];
    }
    wp_send_json_success(['results'=>$results]);
});

// Select2: search simple products (used by grouped-products picker)
add_action('wp_ajax_bizmart_search_simple_products_select2', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) {
        wp_send_json_error(__('Unauthorized', 'bizmart-cost-of-goods'), 403);
    }

    $q = isset($_REQUEST['q']) ? sanitize_text_field(wp_unslash((string) $_REQUEST['q'])) : '';
    $page = isset($_REQUEST['page']) ? max(1, absint(wp_unslash($_REQUEST['page']))) : 1;
    $per_page = 25;

    if ($q === '') {
        wp_send_json_success([
            'results' => [],
            'pagination' => ['more' => false],
        ]);
    }

    if (!function_exists('wc_get_products')) {
        wp_send_json_error(__('WooCommerce is not available', 'bizmart-cost-of-goods'), 400);
    }

    $query = new WC_Product_Query([
        'status'   => ['publish'],
        'type'     => ['simple'],
        'limit'    => $per_page,
        'page'     => $page,
        'paginate' => true,
        'search'   => $q,
        'orderby'  => 'title',
        'order'    => 'ASC',
        'return'   => 'objects',
    ]);

    $res = $query->get_products();
    $products = is_object($res) && isset($res->products) ? $res->products : [];
    $total = is_object($res) && isset($res->total) ? (int) $res->total : 0;

    $results = [];
    foreach ($products as $product) {
        if (!$product) continue;
        $sku = $product->get_sku();
        $name = $product->get_name();
        $label = $name;
        if ($sku) {
            $label .= ' (' . $sku . ')';
        }
        $results[] = [
            'id'   => $product->get_id(),
            'text' => $label,
        ];
    }

    $more = ($page * $per_page) < $total;
    wp_send_json_success([
        'results' => $results,
        'pagination' => ['more' => $more],
    ]);
});

// Get Recent Products (for product search initial load)
add_action('wp_ajax_bizmart_get_recent_products', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(__('Unauthorized', 'bizmart-cost-of-goods'), 403);

    global $wpdb;
    $table = $wpdb->prefix . 'bizmart_price_history';

    $recent_product_ids = [];
    if (bizmart_table_exists('bizmart_price_history')) {
        // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- table name only, no user input
        $recent_product_ids = $wpdb->get_col(
            "SELECT DISTINCT product_id
             FROM $table
             WHERE product_id > 0
             ORDER BY created_at DESC
             LIMIT 20"
        );
    }

    // If there is no price history yet (fresh install), fall back to the most recent WooCommerce products.
    if (empty($recent_product_ids)) {
        // 1) Top sellers (uses WooCommerce total_sales meta)
        $recent_product_ids = get_posts([
            'post_type'      => 'product',
            'posts_per_page' => 20,
            'orderby'        => 'meta_value_num',
            'meta_key'       => 'total_sales',
            'order'          => 'DESC',
            'fields'         => 'ids',
            'post_status'    => ['publish', 'draft'],
            'no_found_rows'  => true,
        ]);

        // 2) If still empty, most recent products/variations
        if (empty($recent_product_ids)) {
            $recent_product_ids = get_posts([
                'post_type'      => ['product', 'product_variation'],
                'posts_per_page' => 20,
                'orderby'        => 'date',
                'order'          => 'DESC',
                'fields'         => 'ids',
                'post_status'    => ['publish', 'draft'],
                'no_found_rows'  => true,
            ]);
        }
    }

    $results = [];

    if(!empty($recent_product_ids)) {
        foreach($recent_product_ids as $pid) {
            $product = wc_get_product($pid);
            if(!$product) continue;

            $sku = $product->get_sku() ?: 'N/A';
            $name = $product->get_name();
            $regular_price = $product->get_regular_price();
            $status = $product->get_status();

            // Add draft indicator to name
            $status_indicator = ($status === 'draft') ? bizmart_text(' [DRAFT]', ' [BROUILLON]') : '';

            $last_prices = function_exists('bizmart_get_last_prices') ? bizmart_get_last_prices($pid) : ['purchase_price' => 0, 'selling_price' => 0];
            $stock_quantity = $product->get_stock_quantity();

            $results[] = [
                'id' => $pid,
                'text' => $name . ' (' . $sku . ')' . $status_indicator,
                'sku' => $sku,
                'name' => $name,
                'price' => $regular_price ? (float)$regular_price : 0,
                'purchase_price' => $last_prices['purchase_price'],
                'selling_price' => $last_prices['selling_price'] > 0 ? $last_prices['selling_price'] : ($regular_price ? (float)$regular_price : 0),
                'status' => $status,
                'type' => $product->get_type(),
                'manage_stock' => (bool) $product->get_manage_stock(),
                'stock_quantity' => $stock_quantity !== null ? (float) $stock_quantity : null,
                'stock_status' => $product->get_stock_status(),
            ];
        }
    }

    wp_send_json_success(['results'=>$results]);
});

// ============================================================
// PRODUCT CREATION AJAX HANDLERS
// ============================================================

// Update product status (draft -> publish)
add_action('wp_ajax_bizmart_update_product_status', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error(bizmart_text('Unauthorized', 'Non autorisé', 'غير مصرح'));

    $product_id = isset($_POST['product_id']) ? (int) wp_unslash($_POST['product_id']) : 0;
    $new_status = isset($_POST['status']) ? sanitize_key(wp_unslash((string) $_POST['status'])) : 'publish';

    if (!$product_id) {
        wp_send_json_error(bizmart_text('Product ID required', 'ID produit requis', 'معرّف المنتج مطلوب'));
    }

    $product = wc_get_product($product_id);
    if (!$product) {
        wp_send_json_error(bizmart_text('Product not found', 'Produit introuvable', 'المنتج غير موجود'));
    }

    // Update status
    $product->set_status($new_status);
    $product->save();
                if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    wp_send_json_success([
        'id' => $product_id,
        'status' => $product->get_status(),
        'message' => sprintf(bizmart_text('Product updated successfully (status: %s)', 'Produit mis à jour avec succès (statut: %s)'), ucfirst($new_status))
    ]);
});

// Get Product Variations Handler
add_action('wp_ajax_bizmart_get_product_variations', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $product_id = isset($_POST['product_id']) ? (int) wp_unslash($_POST['product_id']) : 0;

    if (!$product_id) {
        wp_send_json_error('Product ID required');
    }

    $product = wc_get_product($product_id);
    if (!$product) {
        wp_send_json_error('Product not found');
    }

    if ($product->get_type() !== 'variable') {
        wp_send_json_error('Not a variable product');
    }

    // Get variation IDs - using get_children() for variable products
    $variation_ids = $product->get_children();
    if (empty($variation_ids)) {
        wp_send_json_error('No variations found');
    }

    $variation_data = [];
    $successful_variations = 0;

    foreach ($variation_ids as $variation_id) {
        try {
            $variation = wc_get_product($variation_id);
            if (!$variation || !is_a($variation, 'WC_Product_Variation')) {
                continue;
            }

            // Get variation attributes
            $attributes = $variation->get_attributes();
            $attr_display = [];
            if (!empty($attributes)) {
                foreach ($attributes as $attr_name => $attr_value) {
                    $clean_name = ucwords(str_replace(['pa_', '-'], [' ', ' '], $attr_name));
                    $attr_display[] = $clean_name . ': ' . ucfirst(str_replace('-', ' ', $attr_value));
                }
            }
            $title = !empty($attr_display) ? implode(' | ', $attr_display) : 'Variation #' . $variation_id;

            // Get prices - try multiple sources for reliability
            $selling_price = (float) $variation->get_regular_price();
            if (!$selling_price) {
                // Fallback to postmeta
                $selling_price = (float) get_post_meta($variation_id, '_regular_price', true) ?: 0;
            }
            if (!$selling_price) {
                // Final fallback to sale price or price
                $selling_price = (float) get_post_meta($variation_id, '_price', true) ?: 0;
            }

            // Resolve purchase price: try common meta keys and fallback to parent product if available
            $purchase_price = (float) get_post_meta($variation_id, '_purchase_price', true);
            if (!$purchase_price) {
                $purchase_price = (float) get_post_meta($variation_id, '_bizmart_purchase_price', true);
            }
            if (!$purchase_price && method_exists($variation, 'get_parent_id')) {
                $parent_id = (int) $variation->get_parent_id();
                if ($parent_id) {
                    $purchase_price = (float) get_post_meta($parent_id, '_purchase_price', true) ?: (float) get_post_meta($parent_id, '_bizmart_purchase_price', true);
                }
            }
            $purchase_price = $purchase_price ?: 0;

            $variation_data[] = [
                'id' => $variation_id,
                'sku' => $variation->get_sku() ?: '',
                'title' => $title,
                'stock' => (int) ($variation->get_stock_quantity() ?: 0),
                'manage_stock' => (bool) $variation->get_manage_stock(),
                'stock_status' => $variation->get_stock_status(),
                'purchase_price' => $purchase_price,
                'selling_price' => $selling_price,
            ];
            $successful_variations++;
        } catch (Exception $e) {
            // Log error but continue with next variation
            if (defined('WP_DEBUG') && WP_DEBUG) {
                error_log('BizMart - Error loading variation ' . $variation_id . ': ' . $e->getMessage());
            }
            continue;
        }
    }

    // Only return error if NO variations were successfully loaded
    if ($successful_variations === 0) {
        wp_send_json_error('Unable to load variation details');
    }

    wp_send_json_success([
        'variations' => $variation_data,
        'product_id' => $product_id,
        'count' => $successful_variations
    ]);
});

// Create Product Category
add_action('wp_ajax_bizmart_create_product_category', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $name = sanitize_text_field(wp_unslash($_POST['name'] ?? ''));
    if (!$name) wp_send_json_error('Category name required');

    $term = wp_insert_term($name, 'product_cat');
    if (is_wp_error($term)) {
        wp_send_json_error($term->get_error_message());
    }

    wp_send_json_success([
        'id' => $term['term_id'],
        'name' => $name
    ]);
});

// Create Simple Product
add_action('wp_ajax_bizmart_create_simple_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $raw_data = wp_unslash($_POST['data'] ?? '');
    $data = json_decode($raw_data, true);
    if (!$data) wp_send_json_error('Invalid data format');

    $product_id = isset($data['id']) ? absint($data['id']) : 0;
    if ($product_id) {
        $product = wc_get_product($product_id);
        if (!$product || $product->get_type() !== 'simple') {
             wp_send_json_error('Invalid product for update');
        }
    } else {
        $product = new WC_Product_Simple();
    }

    $name = isset($data['name']) ? sanitize_text_field($data['name']) : '';
    if ($name === '') wp_send_json_error('Product name required');

    $sku = isset($data['sku']) ? sanitize_text_field($data['sku']) : '';

    // Updates: if the SKU field is empty, keep the existing SKU (avoid generating a new SKU and triggering conflicts).
    if ($product_id && $sku === '' && $product && method_exists($product, 'get_sku')) {
        $sku = (string) $product->get_sku();
    }

    // Creates: generate SKU if none provided.
    if (!$product_id && $sku === '') {
        $slug_base = sanitize_title($name);
        $sku = $slug_base ? strtoupper(substr(preg_replace('/[^A-Za-z0-9]/', '', $slug_base), 0, 12)) : '';
        if ($sku === '') {
            $sku = 'BIZ-' . wp_generate_password(8, false, false);
        }
    }

    $regular_price = isset($data['regular_price']) ? trim((string) $data['regular_price']) : '';

    $product->set_name($name);

    // SKU handling:
    // - On update: only set SKU if user provided a different one (prevents false "duplicate SKU" errors).
    // - On create: SKU must be set (generated earlier if missing).
    try {
        $current_sku = $product_id ? (string) $product->get_sku() : '';
        if (!$product_id || ($sku !== '' && $sku !== $current_sku)) {
            $product->set_sku($sku);
        }
    } catch (Exception $e) {
        wp_send_json_error('SKU error: ' . $e->getMessage());
    }
    if ($regular_price !== '') {
        $product->set_regular_price(wc_format_decimal($regular_price));
    }
    if (!empty($data['sale_price'])) $product->set_sale_price(wc_format_decimal($data['sale_price']));

    $product->set_short_description(wp_kses_post($data['short_description'] ?? ''));
    $product->set_description(wp_kses_post($data['description'] ?? ''));

    // Categories
    if (isset($data['categories'])) {
        $product->set_category_ids(array_map('intval', (array)$data['categories']));
    }

    // Tags (apply after save when we have a valid product ID)
    $pending_tags = null;
    if (isset($data['tags'])) {
        $pending_tags = is_string($data['tags']) ? array_map('trim', explode(',', $data['tags'])) : (array) $data['tags'];
    }
// Images
    if (isset($data['image_id'])) {
        $product->set_image_id(intval($data['image_id']));
    }
    if (isset($data['gallery_ids'])) {
        $g_ids = is_array($data['gallery_ids']) ? $data['gallery_ids'] : explode(',', $data['gallery_ids']);
        $product->set_gallery_image_ids(array_map('intval', array_filter($g_ids)));
    }

    // Stock
    if (!empty($data['manage_stock'])) {
        $product->set_manage_stock(true);
        $product->set_stock_quantity(isset($data['stock_quantity']) ? (int) $data['stock_quantity'] : 0);
        $product->set_stock_status(!empty($data['stock_status']) ? sanitize_key($data['stock_status']) : 'instock');
        $product->set_backorders(!empty($data['backorders']) ? sanitize_key($data['backorders']) : 'no');
        if (!empty($data['sold_individually'])) $product->set_sold_individually(true);
    } else {
        $product->set_manage_stock(false);
    }

    // Shipping
    if (empty($data['virtual'])) {
        $product->set_virtual(false);
        if (isset($data['weight'])) $product->set_weight(wc_format_decimal($data['weight']));
        if (isset($data['length'])) $product->set_length(wc_format_decimal($data['length']));
        if (isset($data['width'])) $product->set_width(wc_format_decimal($data['width']));
        if (isset($data['height'])) $product->set_height(wc_format_decimal($data['height']));
        if (!empty($data['shipping_class'])) {
            $product->set_shipping_class_id((int) $data['shipping_class']);
        }
    } else {
        $product->set_virtual(true);
    }

    // Linked products
    if (isset($data['cross_sell_ids'])) $product->set_cross_sell_ids((array)$data['cross_sell_ids']);
    if (isset($data['upsell_ids'])) $product->set_upsell_ids((array)$data['upsell_ids']);

    // Advanced
    if (isset($data['purchase_note'])) $product->set_purchase_note(wp_kses_post($data['purchase_note']));
    if (isset($data['menu_order'])) $product->set_menu_order((int) $data['menu_order']);
    if (!empty($data['publish_date'])) $product->set_date_created(strtotime($data['publish_date']));

    $product->set_status(!empty($data['status']) ? sanitize_key($data['status']) : 'publish');
    $product->set_reviews_allowed(($data['comment_status'] ?? 'closed') === 'open');

    try {
        $product_id = $product->save();
    } catch (Exception $e) {
        wp_send_json_error('Save error: ' . $e->getMessage());
    }
    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    // Apply tags now that we have a valid product ID
    if (!empty($pending_tags)) {
        $term_result = wp_set_object_terms($product_id, $pending_tags, 'product_tag', false);
        if (is_wp_error($term_result)) {
            // Not fatal, but surface in response if needed
        }
    }

    if ($product_id && isset($data['cost_price'])) {
        $cost = $data['cost_price'] !== '' ? wc_format_decimal($data['cost_price']) : '';
        update_post_meta($product_id, '_purchase_price', $cost);
        update_post_meta($product_id, '_alg_wc_cog_cost', $cost);
    }

    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'product_save');
    }

    if (!$product_id) wp_send_json_error('Failed to save product');

    wp_send_json_success([
        'id' => $product_id,
        'name' => $product->get_name(),
        'sku' => $product->get_sku(),
        'edit_link' => admin_url('admin.php?page=bizmart-products&view=create&action=edit&id=' . $product_id),
        'view_link' => get_permalink($product_id)
    ]);
});

// Create Variable Product
add_action('wp_ajax_bizmart_create_variable_product', function() {
    // Capture any warnings/notices so AJAX JSON remains valid.
    ob_start();
    // Use status 200 by default so jQuery success callback fires and shows the error message properly.
    // Non-200 codes (400, 403) trigger jQuery .fail() which doesn't parse our error message.
    $bizmart_ajax_fail = function($message, $status = 200) {
        $buffer = ob_get_clean();
        if (!empty($buffer) && function_exists('bizmart_import_log')) {
            bizmart_import_log("AJAX output (variable product error): " . $buffer);
        }
        wp_send_json_error(['message' => $message], $status);
        exit;
    };

    // Catch any uncaught errors at the top level
    set_error_handler(function($errno, $errstr, $errfile, $errline) use ($bizmart_ajax_fail) { // phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_set_error_handler
        if (!(error_reporting() & $errno)) return false; // phpcs:ignore WordPress.PHP.DevelopmentFunctions.prevent_path_disclosure_error_reporting,WordPress.PHP.DiscouragedPHPFunctions.runtime_configuration_error_reporting
        $bizmart_ajax_fail("PHP Error: $errstr in $errfile:$errline");
        return true;
    });

    try {

    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) $bizmart_ajax_fail('Unauthorized', 403);

    $raw_data = wp_unslash($_POST['data'] ?? '');
    $data = json_decode($raw_data, true);
    if (!$data) $bizmart_ajax_fail('Invalid data format');

    $product_id = isset($data['id']) ? absint($data['id']) : 0;
    $updating_existing_product = ($product_id > 0);
    if ($product_id) {
        $product = wc_get_product($product_id);
        if (!$product || $product->get_type() !== 'variable') {
             $bizmart_ajax_fail('Invalid product for update');
        }
    } else {
        $product = new WC_Product_Variable();
    }

    $product->set_name(sanitize_text_field($data['name'] ?? ''));

    // SKU handling (minimal / no side-effects):
    // - On update: if SKU field is empty, keep existing SKU (do not clear it).
    // - On create: set SKU as provided.
    $incoming_sku = isset($data['sku']) ? sanitize_text_field((string) $data['sku']) : '';
    if ($product_id && $incoming_sku === '' && method_exists($product, 'get_sku')) {
        $incoming_sku = (string) $product->get_sku();
    }
    $product->set_sku($incoming_sku);
    $product->set_short_description(wp_kses_post($data['short_description'] ?? ''));
    $product->set_description(wp_kses_post($data['description'] ?? ''));
    $product->set_status(!empty($data['status']) ? sanitize_key((string) $data['status']) : 'publish');

    // Initial save to get ID (if new)
    try {
        $product_id = $product->save();
    } catch (Exception $e) {
        $bizmart_ajax_fail('Save error: ' . $e->getMessage());
    }
    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }
    if (!$product_id) $bizmart_ajax_fail('Failed to save parent product');

    // Categories
    if (isset($data['categories'])) {
        $product->set_category_ids(array_map('intval', (array)$data['categories']));
    }

    // Tags (apply after save when we have a valid product ID)
    $pending_tags = null;
    if (isset($data['tags'])) {
        $pending_tags = is_string($data['tags']) ? array_map('trim', explode(',', $data['tags'])) : (array) $data['tags'];
    }
    // Variations payload flags (used to avoid rewriting attributes during stock-only edits).
    $has_variations_payload = array_key_exists('variations', $data) && is_array($data['variations']);
    $has_new_variations = false;
    if ($has_variations_payload) {
        foreach ((array) $data['variations'] as $v) {
            $v_id = isset($v['id']) ? intval($v['id']) : 0;
            if ($v_id <= 0) { $has_new_variations = true; break; }
        }
    }

// Image
    if (isset($data['image_id'])) {
        $product->set_image_id(intval($data['image_id']));
    }

    // Attributes
    $attribute_objects = [];
    // On updates, only rewrite attributes when the request is creating new variations (i.e. a regen/add flow).
    // This prevents failures on legacy variable products whose attributes don't round-trip cleanly through our UI.
    if ((!$updating_existing_product || $has_new_variations) && !empty($data['attributes'])) {
        foreach ($data['attributes'] as $attr) {
            $raw_name = sanitize_text_field((string) ($attr['name'] ?? ''));
            if ($raw_name === '') {
                continue;
            }

            $attribute = new WC_Product_Attribute();
            $tax_name = null;
            if (taxonomy_exists($raw_name)) {
                $tax_name = $raw_name;
            } else {
                $candidate_tax = wc_attribute_taxonomy_name($raw_name);
                if (taxonomy_exists($candidate_tax)) {
                    $tax_name = $candidate_tax;
                }
            }

            if ($tax_name) {
                $attribute->set_id(wc_attribute_taxonomy_id_by_name(str_replace('pa_', '', $tax_name)));
                $attribute->set_name($tax_name);
            } else {
                $attribute->set_name($raw_name);
            }

            $options = $attr['options'] ?? [];
            if ($tax_name && is_array($options)) {
                $term_ids = [];
                foreach ($options as $opt) {
                    $opt = sanitize_text_field((string) $opt);
                    if ($opt === '') continue;
                    $term = get_term_by('name', $opt, $tax_name);
                    if (!$term || is_wp_error($term)) {
                        $term = get_term_by('slug', sanitize_title($opt), $tax_name);
                    }
                    if ($term && !is_wp_error($term) && isset($term->slug)) {
                        $val = (string) $term->slug;
                    } else {
                        // Fall back to a best-effort slug to avoid save failures on label input.
                        $val = sanitize_title($opt);
                    }
                    $term_ids[] = (int) $term->term_id;
                }
                $attribute->set_options(!empty($term_ids) ? $term_ids : $options);
            } else {
                $attribute->set_options($options);
            }
            $attribute->set_visible(!empty($attr['visible']));
            $attribute->set_variation(!empty($attr['variation']));
            $attribute_objects[] = $attribute;
        }
        $product->set_attributes($attribute_objects);
        try {
            $product->save();
        } catch (Exception $e) {
            $bizmart_ajax_fail('Save error (attributes): ' . $e->getMessage());
        }
        if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }
    }

    // Variations
    // Critical: when editing, the UI might not submit variations (e.g., user only edits the name).
    // In that case we must NOT delete or recreate any WooCommerce variations.
    $current_variation_ids = $product->get_children();
    $processed_variation_ids = [];

    if ($has_variations_payload && !empty($data['variations'])) {
        foreach ((array) $data['variations'] as $var_data) {
            $var_id = isset($var_data['id']) ? intval($var_data['id']) : 0;
            $is_existing_variation = ($var_id && in_array($var_id, $current_variation_ids, true));

            if ($is_existing_variation) {
                $variation = wc_get_product($var_id);
                if (!$variation || !is_a($variation, 'WC_Product_Variation')) {
                    $variation = new WC_Product_Variation($var_id);
                }
            } else {
                $variation = new WC_Product_Variation();
                $variation->set_parent_id($product_id);
            }

            $incoming_sku = isset($var_data['sku']) ? sanitize_text_field((string) $var_data['sku']) : '';
            $existing_sku = $is_existing_variation ? (string) $variation->get_sku() : '';

            // Only set SKU if it's actually changed (avoid duplicate SKU error on same variation)
            if ($incoming_sku !== '' && $incoming_sku !== $existing_sku) {
                $variation->set_sku($incoming_sku);
            }

            $incoming_regular = $var_data['regular_price'] ?? null;
            if ($incoming_regular !== null && $incoming_regular !== '') {
                $variation->set_regular_price($incoming_regular);
            }
            $incoming_sale = $var_data['sale_price'] ?? null;
            if ($incoming_sale !== null && $incoming_sale !== '') {
                $variation->set_sale_price($incoming_sale);
            } elseif ($is_existing_variation) {
                // Preserve existing sale price when not provided on update.
                $variation->set_sale_price($variation->get_sale_price());
            }

            $has_stock_qty = array_key_exists('stock_quantity', $var_data);
            $qty = $has_stock_qty ? intval($var_data['stock_quantity']) : null;

            // Fast-path: existing variation, stock-only update. Avoid full save to prevent legacy-attribute failures.
            if ($is_existing_variation && $has_stock_qty) {
                $existing_regular = (string) $variation->get_regular_price();
                $existing_sale = (string) $variation->get_sale_price();
                $existing_cost = (string) get_post_meta($var_id, '_purchase_price', true);

                $sku_changed = ($incoming_sku !== '' && $incoming_sku !== $existing_sku);
                $regular_changed = ($incoming_regular !== null && $incoming_regular !== '' && (string) $incoming_regular !== $existing_regular);
                $sale_changed = ($incoming_sale !== null && $incoming_sale !== '' && (string) $incoming_sale !== $existing_sale);
                $incoming_cost = isset($var_data['cost_price']) ? (string) $var_data['cost_price'] : '';
                $cost_changed = ($incoming_cost !== '' && $incoming_cost !== $existing_cost);

                if (!$sku_changed && !$regular_changed && !$sale_changed && !$cost_changed) {
                    update_post_meta($var_id, '_manage_stock', 'yes');
                    update_post_meta($var_id, '_stock', $qty);
                    update_post_meta($var_id, '_stock_status', ($qty > 0) ? 'instock' : 'outofstock');
                    if (isset($var_data['cost_price'])) {
                        $cost = $var_data['cost_price'] !== '' ? floatval($var_data['cost_price']) : '';
                        update_post_meta($var_id, '_purchase_price', $cost);
                        update_post_meta($var_id, '_alg_wc_cog_cost', $cost);
                    }
                    if (function_exists('wc_update_product_lookup_tables')) {
                        wc_update_product_lookup_tables($var_id);
                    }
                    if (function_exists('wc_delete_product_transients')) {
                        wc_delete_product_transients($var_id);
                    }
                    $processed_variation_ids[] = $var_id;
                    continue;
                }
            }

            $variation->set_manage_stock(true);
            if ($has_stock_qty) {
                $variation->set_stock_quantity($qty);
                // Keep stock status coherent for variations too.
                $variation->set_stock_status(($qty > 0) ? 'instock' : 'outofstock');
            }
            $variation->set_status('publish');

            // Map attributes
            $var_attributes = [];
            if (isset($var_data['attributes']) && is_array($var_data['attributes'])) {
                foreach ($var_data['attributes'] as $name => $val) {
                    $name = sanitize_text_field((string) $name);
                    if ($name === '') continue;
                    if (taxonomy_exists($name)) {
                        $tax_name = $name;
                    } else {
                        $candidate_tax = wc_attribute_taxonomy_name($name);
                        $tax_name = taxonomy_exists($candidate_tax) ? $candidate_tax : null;
                    }
                    $key = $tax_name ? 'attribute_' . $tax_name : 'attribute_' . sanitize_title($name);
                    $val = sanitize_text_field((string) $val);
                    if ($tax_name) {
                        // WC expects the term *slug* for taxonomy-based variation attributes.
                        $term = get_term_by('slug', sanitize_title($val), $tax_name);
                        if (!$term || is_wp_error($term)) {
                            $term = get_term_by('name', $val, $tax_name);
                        }
                        if ((!$term || is_wp_error($term)) && is_numeric($val)) {
                            $term = get_term((int) $val, $tax_name);
                        }
                        if ($term && !is_wp_error($term) && isset($term->slug)) {
                            $val = (string) $term->slug;
                        } else {
                            // Fall back to a best-effort slug to avoid save failures on label input.
                            $val = sanitize_title($val);
                        }
                    }
                    $var_attributes[$key] = $val;
                }
            }

            // When updating existing variations, do not touch attributes: legacy products may have
            // attribute names/values that don't round-trip cleanly through our UI representation.
            if (!$is_existing_variation && !empty($var_attributes)) {
                $variation->set_attributes($var_attributes);
            }
            try {
                $saved_var_id = $variation->save();
                if (!$saved_var_id) {
                    $bizmart_ajax_fail('Save error (variation): Failed to save variation - no ID returned');
                }
            } catch (Exception $e) {
                $bizmart_ajax_fail('Save error (variation): ' . $e->getMessage());
            }
            if ($saved_var_id) {
                $processed_variation_ids[] = $saved_var_id;
                if (isset($var_data['cost_price'])) {
                    $cost = $var_data['cost_price'] !== '' ? floatval($var_data['cost_price']) : '';
                    update_post_meta($saved_var_id, '_purchase_price', $cost);
                    update_post_meta($saved_var_id, '_alg_wc_cog_cost', $cost);
                }
            }
        }
    }

    // Delete variations only when the UI explicitly submitted a variations payload.
    // This preserves existing WooCommerce variations during simple edits.
    if ($has_variations_payload && !empty($data['variations'])) {
        $to_delete = array_diff($current_variation_ids, $processed_variation_ids);
        foreach ($to_delete as $del_id) {
            $v_to_del = wc_get_product($del_id);
            if ($v_to_del) $v_to_del->delete(true);
        }
    }

    if ($product_id && isset($data['base_cost_price'])) {
        $cost = $data['base_cost_price'] !== '' ? wc_format_decimal($data['base_cost_price']) : '';
        update_post_meta($product_id, '_purchase_price', $cost);
        update_post_meta($product_id, '_alg_wc_cog_cost', $cost);
    }

    try {
        $product->save();
    } catch (Exception $e) {
        $bizmart_ajax_fail('Save error (final product save): ' . $e->getMessage());
    }

    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'product_save');
    }

    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    $buffer = ob_get_clean();
    if (!empty($buffer) && function_exists('bizmart_import_log')) {
        bizmart_import_log("AJAX output (variable product success): " . $buffer);
    }

    restore_error_handler();
    wp_send_json_success([
        'id' => $product_id,
        'name' => $product->get_name(),
        'sku' => $product->get_sku(),
        'edit_link' => admin_url('admin.php?page=bizmart-products&view=create&action=edit&id=' . $product_id),
        'view_link' => get_permalink($product_id)
    ]);

    } catch (Throwable $e) {
        restore_error_handler();
        $bizmart_ajax_fail('Unexpected error: ' . $e->getMessage());
    }
});

// Create Grouped Product
add_action('wp_ajax_bizmart_create_grouped_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $raw_data = wp_unslash($_POST['data'] ?? '');
    $data = json_decode($raw_data, true);
    if (!$data) wp_send_json_error('Invalid data format');

    $product_id = isset($data['id']) ? absint($data['id']) : 0;
    if ($product_id) {
        $product = wc_get_product($product_id);
        if (!$product || $product->get_type() !== 'grouped') {
             wp_send_json_error('Invalid product for update');
        }
    } else {
        $product = new WC_Product_Grouped();
    }

    $product->set_name(sanitize_text_field((string) ($data['name'] ?? '')));
    $product->set_sku(sanitize_text_field((string) ($data['sku'] ?? '')));
    $product->set_description(wp_kses_post($data['description'] ?? ''));

    if (isset($data['categories'])) {
        $product->set_category_ids(array_map('intval', (array)$data['categories']));
    }

    if (isset($data['image_id'])) {
        $product->set_image_id(intval($data['image_id']));
    }

    if (isset($data['grouped_products'])) {
        $product->set_children(array_map('intval', (array)$data['grouped_products']));
    }

    $product->set_status(!empty($data['status']) ? sanitize_key((string) $data['status']) : 'publish');

    try {
        $product_id = $product->save();
    } catch (Exception $e) {
        wp_send_json_error('Save error: ' . $e->getMessage());
    }
    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    // Apply tags
    if (!empty($pending_tags)) {
        $term_result = wp_set_object_terms($product_id, $pending_tags, 'product_tag', false);
    }

    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'product_save');
    }
    wp_send_json_success([
        'id' => $product_id,
        'name' => $product->get_name(),
        'sku' => $product->get_sku(),
        'edit_link' => admin_url('admin.php?page=bizmart-products&view=create&action=edit&id=' . $product_id),
        'view_link' => get_permalink($product_id)
    ]);
});

// Create External Product
add_action('wp_ajax_bizmart_create_external_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $raw_data = wp_unslash($_POST['data'] ?? '');
    $data = json_decode($raw_data, true);
    if (!$data) wp_send_json_error('Invalid data format');

    $product_id = isset($data['id']) ? absint($data['id']) : 0;
    if ($product_id) {
        $product = wc_get_product($product_id);
        if (!$product || $product->get_type() !== 'external') {
             wp_send_json_error('Invalid product for update');
        }
    } else {
        $product = new WC_Product_External();
    }

    $product->set_name(sanitize_text_field((string) ($data['name'] ?? '')));
    $product->set_sku(sanitize_text_field((string) ($data['sku'] ?? '')));
    $product->set_product_url(esc_url_raw((string) ($data['product_url'] ?? '')));
    $product->set_button_text(sanitize_text_field((string) ($data['button_text'] ?? '')));
    $product->set_regular_price(wc_format_decimal((string) ($data['regular_price'] ?? '')));
    if (!empty($data['sale_price'])) $product->set_sale_price(wc_format_decimal($data['sale_price']));

    $product->set_description(wp_kses_post($data['description'] ?? ''));

    if (isset($data['categories'])) {
        $product->set_category_ids(array_map('intval', (array)$data['categories']));
    }

    if (isset($data['image_id'])) {
        $product->set_image_id(intval($data['image_id']));
    }

    $product->set_virtual(true);
    $product->set_downloadable(true);

    if (!empty($data['download_files'])) {
        $downloads = [];
        foreach ($data['download_files'] as $file) {
            $downloads[] = [
                'name' => sanitize_text_field($file['name']),
                'file' => esc_url_raw($file['url'])
            ];
        }
        $product->set_downloads($downloads);
    }

    if (isset($data['download_limit'])) $product->set_download_limit((int) $data['download_limit']);
    if (isset($data['download_expiry'])) $product->set_download_expiry((int) $data['download_expiry']);

    $product->set_status(!empty($data['status']) ? sanitize_key((string) $data['status']) : 'publish');
    $product_id = $product->save();
                if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    if ($product_id && isset($data['cost_price'])) {
        $cost = $data['cost_price'] !== '' ? wc_format_decimal($data['cost_price']) : '';
        update_post_meta($product_id, '_purchase_price', $cost);
        update_post_meta($product_id, '_alg_wc_cog_cost', $cost);
    }

    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'product_save');
    }

    wp_send_json_success([
        'id' => $product_id,
        'name' => $product->get_name(),
        'sku' => $product->get_sku(),
        'edit_link' => admin_url('admin.php?page=bizmart-products&view=create&action=edit&id=' . $product_id),
        'view_link' => get_permalink($product_id)
    ]);
});

// Create Digital Product
add_action('wp_ajax_bizmart_create_digital_product', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $raw_data = wp_unslash($_POST['data'] ?? '');
    $data = json_decode($raw_data, true);
    if (!$data) wp_send_json_error('Invalid data format');

    $product_id = isset($data['id']) ? absint($data['id']) : 0;
    if ($product_id) {
        $product = wc_get_product($product_id);
        if (!$product || $product->get_type() !== 'simple') {
             wp_send_json_error('Invalid product for update');
        }
    } else {
        $product = new WC_Product_Simple();
    }

    $product->set_name(sanitize_text_field((string) ($data['name'] ?? '')));
    $product->set_sku(sanitize_text_field((string) ($data['sku'] ?? '')));
    $product->set_regular_price(wc_format_decimal((string) ($data['regular_price'] ?? '')));
    if (!empty($data['sale_price'])) $product->set_sale_price(wc_format_decimal($data['sale_price']));

    $product->set_description(wp_kses_post($data['description'] ?? ''));

    if (isset($data['categories'])) {
        $product->set_category_ids(array_map('intval', (array)$data['categories']));
    }

    if (isset($data['image_id'])) {
        $product->set_image_id(intval($data['image_id']));
    }

    $product->set_virtual(true);
    $product->set_downloadable(true);

    if (!empty($data['download_files'])) {
        $downloads = [];
        foreach ($data['download_files'] as $file) {
            $downloads[] = [
                'name' => sanitize_text_field($file['name']),
                'file' => esc_url_raw($file['url'])
            ];
        }
        $product->set_downloads($downloads);
    }

    if (isset($data['download_limit'])) $product->set_download_limit((int) $data['download_limit']);
    if (isset($data['download_expiry'])) $product->set_download_expiry((int) $data['download_expiry']);

    $product->set_status(!empty($data['status']) ? sanitize_key((string) $data['status']) : 'publish');
    $product_id = $product->save();
                if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    if ($product_id && isset($data['cost_price'])) {
        $cost = $data['cost_price'] !== '' ? wc_format_decimal($data['cost_price']) : '';
        update_post_meta($product_id, '_purchase_price', $cost);
        update_post_meta($product_id, '_alg_wc_cog_cost', $cost);
    }

    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'product_save');
    }

    wp_send_json_success([
        'id' => $product_id,
        'name' => $product->get_name(),
        'sku' => $product->get_sku(),
        'edit_link' => admin_url('admin.php?page=bizmart-products&view=create&action=edit&id=' . $product_id),
        'view_link' => get_permalink($product_id)
    ]);
});

// Quick Stock Update
add_action('wp_ajax_bizmart_quick_update_stock', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized');

    $product_id = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;
    $qty = isset($_POST['qty']) ? intval(wp_unslash($_POST['qty'])) : 0;

    $product = wc_get_product($product_id);
    if (!$product) wp_send_json_error('Product not found');

    $product->set_stock_quantity($qty);
    if ($qty > 0) {
        $product->set_stock_status('instock');
    } else {
        $product->set_stock_status('outofstock');
    }

    try {
        $product->save();
    } catch (Exception $e) {
        wp_send_json_error('Save error: ' . $e->getMessage());
    }
    if (function_exists('wc_delete_product_transients')) { wc_delete_product_transients($product_id); }

    // Invalidate metrics cache so "Items in Stock" updates immediately
    if (function_exists('bizmart_invalidate_product_metrics_cache')) {
        bizmart_invalidate_product_metrics_cache($product_id, 'quick_stock_update');
    } else {
        $blog_id = get_current_blog_id();
        delete_transient('bizmart_inventory_totals_v9_' . $blog_id);
        delete_transient('bizmart_inventory_totals_v8_' . $blog_id);
        delete_transient('bizmart_products_stats_v5_' . $blog_id);
    }

    wp_send_json_success(['qty' => $qty]);
});

// AJAX handler to get products for select dropdown
add_action('wp_ajax_bizmart_get_products_for_select', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized', 403);

    $products = wc_get_products([
        'limit' => 500,
        'status' => 'publish',
        'orderby' => 'name',
        'order' => 'ASC'
    ]);

    $options = '<option value="">' . esc_html(bizmart_text('Select a product', 'Sélectionner un produit', 'اختر منتجاً')) . '</option>';
    foreach ($products as $product) {
        $price = $product->get_price();
        $price_display = $price ? ' (' . wc_price($price) . ')' : '';
        $options .= '<option value="' . $product->get_id() . '">' . esc_html($product->get_name()) . $price_display . '</option>';
    }

    wp_send_json_success($options);
});

// AJAX handler to get attribute terms
add_action('wp_ajax_bizmart_get_attribute_terms', function() {
    bizmart_check_ajax_nonce('nonce');

    if (!current_user_can('manage_woocommerce')) {
        wp_send_json_error('Unauthorized');
    }

    $attribute_name = sanitize_text_field(wp_unslash($_POST['attribute_name'] ?? ''));

    if (empty($attribute_name)) {
        wp_send_json_error('Attribute name is required');
    }

    // Get terms for the attribute
    $taxonomy = 'pa_' . $attribute_name;
    $terms = get_terms([
        'taxonomy' => $taxonomy,
        'hide_empty' => false,
        'orderby' => 'name',
        'order' => 'ASC'
    ]);

    if (is_wp_error($terms)) {
        wp_send_json_error($terms->get_error_message());
    }

    $term_data = [];
    foreach ($terms as $term) {
        $term_data[] = [
            'id' => $term->term_id,
            'name' => $term->name,
            'slug' => $term->slug
        ];
    }

    wp_send_json_success([
        'terms' => $term_data,
        'taxonomy' => $taxonomy
    ]);
});

// ============================================================
// PRICE HISTORY & WAC AJAX HANDLERS
// ============================================================

// Get Product Price History
add_action('wp_ajax_bizmart_get_product_price_history', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized', 403);

    $product_id = absint(wp_unslash($_POST['product_id'] ?? 0));
    if (!$product_id) wp_send_json_error('Missing product_id');

    $limit  = absint(wp_unslash($_POST['limit'] ?? 50));
    $offset = absint(wp_unslash($_POST['offset'] ?? 0));

    $history = function_exists('bizmart_get_price_history')
        ? bizmart_get_price_history($product_id, $limit, $offset)
        : [];

    $stats = function_exists('bizmart_get_price_stats')
        ? bizmart_get_price_stats($product_id)
        : [];

    $wac = function_exists('bizmart_get_wac')
        ? bizmart_get_wac($product_id)
        : 0;

    $last = function_exists('bizmart_get_last_prices')
        ? bizmart_get_last_prices($product_id)
        : ['purchase_price' => 0, 'selling_price' => 0];

    wp_send_json_success([
        'history' => $history,
        'stats'   => $stats,
        'wac'     => $wac,
        'last'    => $last,
        'product_name' => get_the_title($product_id),
    ]);
});

/**
 * AJAX: Get chart-ready price history data.
 */
add_action('wp_ajax_bizmart_get_product_price_chart', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized', 403);

    $product_id = absint(wp_unslash($_POST['product_id'] ?? 0));
    if (!$product_id) wp_send_json_error('Missing product_id');

    $history = function_exists('bizmart_get_price_history')
        ? bizmart_get_price_history($product_id, 100, 0)
        : [];

    // Reverse for chronological order (oldest first)
    $history = array_reverse($history);

    $labels = [];
    $pp_data = [];
    $sp_data = [];
    $margin_data = [];

    foreach ($history as $h) {
        $labels[]      = date_i18n('d M Y', strtotime($h['created_at']));
        $pp_data[]     = $h['purchase_price'];
        $sp_data[]     = $h['selling_price'];
        $margin_data[] = $h['margin_pct'] ?? 0;
    }

    wp_send_json_success([
        'labels'  => $labels,
        'pp'      => $pp_data,
        'sp'      => $sp_data,
        'margin'  => $margin_data,
    ]);
});

/**
 * AJAX: Get WAC for a product.
 */
add_action('wp_ajax_bizmart_get_product_wac', function() {
    bizmart_check_ajax_nonce('nonce');
    if (!current_user_can('manage_woocommerce')) wp_send_json_error('Unauthorized', 403);

    $product_id = absint(wp_unslash($_POST['product_id'] ?? 0));
    if (!$product_id) wp_send_json_error('Missing product_id');

    $wac = function_exists('bizmart_get_wac') ? bizmart_get_wac($product_id) : 0;
    $last = function_exists('bizmart_get_last_prices') ? bizmart_get_last_prices($product_id) : ['purchase_price' => 0, 'selling_price' => 0];
    $method = function_exists('bizmart_get_valuation_method') ? bizmart_get_valuation_method() : 'last_price';

    wp_send_json_success([
        'wac'        => $wac,
        'last_price' => $last['purchase_price'],
        'method'     => $method,
    ]);
});
