<?php



add_action('updated_post_meta', 'wcmlim_update_inventory_data_addon', 15, 4);
add_action('added_post_meta', 'wcmlim_update_inventory_data_addon', 15, 4);
add_action('admin_head', 'wcmlim_hide_specific_stock_notice', 100);

// Hook for delayed OpenPOS stock update
add_action('wcmlim_delayed_openpos_update', 'wcmlim_delayed_openpos_stock_update', 10, 4);

/**
 * Delayed OpenPOS stock update function
 * This function is called after a delay to ensure OpenPOS memory is ready
 * Handles both simple and variable products
 */
function wcmlim_delayed_openpos_stock_update($product_id, $formatted_location_id, $stock_value, $wcmlim_pos_id) {
    // Verify OpenPOS is still active and compatibility is enabled
    if (get_option('wcmlim_pos_compatiblity') === 'on' && in_array('woocommerce-openpos/woocommerce-openpos.php', apply_filters('active_plugins', get_option('active_plugins')))) {
        $op_stock_key = '_op_qty_warehouse_' . $wcmlim_pos_id;
        
        
        // Get the product to check its type
        $product = wc_get_product($product_id);
        
        if ($product) {
            // Handle variable products
            if ($product->is_type('variable')) {
                $variations = $product->get_children();
                
                foreach ($variations as $variation_id) {
                    // Get the stock for this specific variation at this location
                    $variation_stock = (int)get_post_meta($variation_id, 'wcmlim_stock_at_' . $formatted_location_id, true);
                    
                    if ($variation_stock > 0) {
                        // Update OpenPOS stock for this variation
                        $result = update_post_meta($variation_id, $op_stock_key, $variation_stock);
                        
                        // Verify the value was actually saved
                        $saved_value = get_post_meta($variation_id, $op_stock_key, true);
                    }
                }
                
                // Also update the parent variable product with total stock
                $total_stock = 0;
                foreach ($variations as $variation_id) {
                    $variation_stock = (int)get_post_meta($variation_id, 'wcmlim_stock_at_' . $formatted_location_id, true);
                    $total_stock += $variation_stock;
                }
                
                if ($total_stock > 0) {
                    $result = update_post_meta($product_id, $op_stock_key, $total_stock);
                }
                
            } else {
                // Handle simple products (original logic)
                $result = update_post_meta($product_id, $op_stock_key, $stock_value);
                
                // Verify the value was actually saved
                $saved_value = get_post_meta($product_id, $op_stock_key, true);
            }
        } 
    }
}

//This function will update the total stock count via external methods including importers & woocommerce API
function wcmlim_update_inventory_data_addon($meta_id, $object_id, $meta_key, $_meta_value) {
    global $wpdb;

    // Check if the meta key relates to stock at a specific location
    if (!str_contains($meta_key, 'wcmlim_stock_at_')) {
        return;
    }

    $formatted_location_id = preg_replace('/[^0-9]/', '', $meta_key);
    $product_id = $object_id;
    $product = wc_get_product($product_id);

    $stock_value = (int)$_meta_value; // Convert to integer
    if ($stock_value <= 0) {
        return; // Skip processing if value is not positive
    }

    // Check if this location is linked to the product
    $linked_locations = wp_get_object_terms($product_id, 'locations', array('fields' => 'ids'));
    if (!in_array((int)$formatted_location_id, $linked_locations)) {
        // Location is not linked, so add it to linked locations
        $updated_terms = $linked_locations;
        $updated_terms[] = (int)$formatted_location_id;
        wp_set_object_terms($product_id, $updated_terms, 'locations', false);
    }

    // Stock Management
    manage_stock($product, $formatted_location_id, $stock_value);

    // Availability Management
    update_availability($product, $formatted_location_id, $stock_value);

    // --- OpenPOS Stock Sync (Scheduled) ---
    // Schedule OpenPOS update after 3 seconds to allow OpenPOS memory to be ready
    if (get_option('wcmlim_pos_compatiblity') === 'on' && in_array('woocommerce-openpos/woocommerce-openpos.php', apply_filters('active_plugins', get_option('active_plugins')))) {
        $wcmlim_pos_id = get_term_meta($formatted_location_id, 'wcmlim_pos_compatiblity', true);
        if (!empty($wcmlim_pos_id)) {
            
            // Schedule the OpenPOS update to run in 3 seconds
            wp_schedule_single_event(
                time() + 3, // 3 seconds delay
                'wcmlim_delayed_openpos_update',
                array($product_id, $formatted_location_id, $stock_value, $wcmlim_pos_id)
            );
        }
    }

     $product->save();
}

function manage_stock($product, $formatted_location_id, $_meta_value) {
    // Get all locations once
    $terms = get_terms(array('taxonomy' => 'locations', 'hide_empty' => false, 'parent' => 0));
    $available_stock_meta_key = 'wcmlim_stock_available_at_' . $formatted_location_id;
    
    // First check if sync mode is enabled
    $sync_enabled = get_post_meta($product->get_id(), 'wcmlim_sync_stock_with_location', true);
    $sync_location = get_post_meta($product->get_id(), 'wcmlim_sync_stock_location_id', true);
    $use_sync_stock = ($sync_enabled === 'yes' && !empty($sync_location));
    
    // Save the original product stock if not already saved
    $original_stock = (int)get_post_meta($product->get_id(), '_wcmlim_original_stock', true);
    $current_stock = (int)get_post_meta($product->get_id(), '_stock', true);
    
    if ($original_stock === 0 && $current_stock > 0) {
        update_post_meta($product->get_id(), '_wcmlim_original_stock', $current_stock);
        $original_stock = $current_stock;
    }
    
    // Get current stock levels for all locations in a single array
    $location_stocks = [];
    // Get linked locations for the product
    // This will give us the IDs of the locations linked to this product
    $Linked_locations = wp_get_object_terms( $product->get_id(), 'locations', array('fields' => 'ids'));
    foreach ($terms as $term) {
        $term_id = $term->term_id;
        // Check if term_id is present in Linked_locations before proceeding
        if (in_array($term_id, $Linked_locations)) {
            $location_stocks[$term_id] = (int)get_post_meta($product->get_id(), 'wcmlim_stock_at_' . $term_id, true);
        }
    }
    
    // Initialize total stock
    $total_location_stock = 0;

    // Handle variable products
    if ($product->is_type('variable')) {
        $variations = $product->get_children();
        $variation_stocks = [];
        
        // Process each variation
        foreach ($variations as $variation_id) {
            $variation = wc_get_product($variation_id);
            
            // Check if this specific variation has sync enabled
            $var_sync_enabled = get_post_meta($variation_id, 'wcmlim_sync_stock_with_location', true);
            $var_sync_location = get_post_meta($variation_id, 'wcmlim_sync_stock_location_id', true);
            $var_use_sync_stock = ($var_sync_enabled === 'yes' && !empty($var_sync_location));
            
            if ($var_use_sync_stock) {
                // If sync is enabled for this variation, use only the selected location's stock
                $var_stock = (int)get_post_meta($variation_id, 'wcmlim_stock_at_' . $var_sync_location, true);
                
                // Update variation stock with just the synced location stock
                if ($variation->get_manage_stock()) {
                    update_post_meta($variation_id, '_stock', $var_stock);
                    $variation->update_meta_data('wcmlim_sync_updated', true);
                    $variation->save();
                }
                
                // Add to total stock for parent product
                $total_location_stock += $var_stock;
            } else {
                // Calculate total stock for this variation across linked locations only
                $variation_total_stock = 0;
                // Get linked locations for this variation
                $var_linked_locations = wp_get_object_terms($variation_id, 'locations', array('fields' => 'ids'));
                
                foreach ($terms as $term) {
                    $term_id = $term->term_id;
                    // Only add stock if this location is linked to the variation
                    if (in_array($term_id, $var_linked_locations)) {
                        $var_stock = (int)get_post_meta($variation_id, 'wcmlim_stock_at_' . $term_id, true);
                        $variation_total_stock += $var_stock;
                    }
                }
                
                // Update variation stock with all locations sum
                if ($variation_total_stock !== (int)get_post_meta($variation_id, '_stock', true) && $variation->get_manage_stock()) {
                    update_post_meta($variation_id, '_stock', $variation_total_stock);
                    $variation->update_meta_data('wcmlim_sync_updated', true);
                    $variation->save();
                }
                
                // Add to total stock for parent product
                $total_location_stock += $variation_total_stock;
            }
        }
    } else {
        // For simple products
        if ($use_sync_stock) {
            // If sync is enabled, use only the selected location's stock
            $total_location_stock = (int)get_post_meta($product->get_id(), 'wcmlim_stock_at_' . $sync_location, true);
        } else {
            // Only sum up stock from linked locations
            // This ensures unlinked locations are ignored in the stock calculation
            $total_location_stock = 0;
            foreach ($location_stocks as $loc_id => $loc_stock) {
                if (in_array($loc_id, $Linked_locations)) {
                    $total_location_stock += $loc_stock;
                }
            }
        }
    }

    // Update the stock for the parent product (variable or simple)
    // Check if any linked locations have stock
    $has_location_stock = ($total_location_stock > 0);
    // Check if any locations are linked to this product
    $has_linked_locations = !empty($Linked_locations);
    
    if ($product->get_manage_stock()) {
        if ($has_linked_locations) {
            // If product has linked locations, update stock based on location stock
            if ($total_location_stock !== $current_stock) {
                // If no location stock and we have an original stock value, use it
                if ($total_location_stock === 0 && $original_stock > 0 && !$has_location_stock) {
                    // Don't update to zero if we have original stock and no location stock
                    // This preserves the base product stock when locations are empty
                } else {
                    // Otherwise update to the sum of location stocks
                    update_post_meta($product->get_id(), '_stock', $total_location_stock);
                }
                
                $product->update_meta_data('wcmlim_sync_updated', true);
            }
            
            // Update stock status based on total location stock and original stock
            if ($has_location_stock) {
                // If any linked location has stock, product is in stock
                update_post_meta($product->get_id(), '_stock_status', 'instock');
                wp_remove_object_terms($product->get_id(), 'outofstock', 'product_visibility');
            } else if (!$product->is_on_backorder()) {
                // If no linked location has stock but we have original base stock, keep product in stock
                if ($original_stock > 0) {
                    update_post_meta($product->get_id(), '_stock', $original_stock); // Use original stock
                    update_post_meta($product->get_id(), '_stock_status', 'instock');
                    wp_remove_object_terms($product->get_id(), 'outofstock', 'product_visibility');
                } else {
                    // No linked location stock and no base stock, so product is out of stock
                    update_post_meta($product->get_id(), '_stock_status', 'outofstock');
                    wp_set_post_terms($product->get_id(), 'outofstock', 'product_visibility', true);
                }
            }
        } else {
            // If product has no linked locations, always preserve and use the original stock
            if ($original_stock > 0) {
                update_post_meta($product->get_id(), '_stock', $original_stock);
                update_post_meta($product->get_id(), '_stock_status', 'instock');
                wp_remove_object_terms($product->get_id(), 'outofstock', 'product_visibility');
            }
        }
    }

    // Handle empty value case
    if (empty($_meta_value)) {
        update_post_meta($product->get_id(), 'wcmlim_stock_at_' . $formatted_location_id, '0');
    }

    // Update available stock meta key
    update_post_meta($product->get_id(), $available_stock_meta_key, $total_location_stock);
}


function update_availability($product, $formatted_location_id, $_meta_value) {
    global $wpdb;

    // Determine the correct parent ID
    $parent_id = $product->get_type() === 'variation' ? wp_get_post_parent_id($product->get_id()) : $product->get_id();
    $availability_meta_key = 'wcmlim_product_availability_at_' . $formatted_location_id;


    // Determine the new meta value based on stock status
    $new_meta_value = (!empty($_meta_value) && $_meta_value > 0) ? 'yes' : 'no';
   
    // Check if the meta key already exists
    $current_meta_value = get_post_meta($parent_id, $availability_meta_key, true);

    // Update or insert meta based on whether it exists
    if (empty($current_meta_value)) {
        $wpdb->insert(
            $wpdb->postmeta,
            [
                'post_id'    => $parent_id,
                'meta_key'   => $availability_meta_key,
                'meta_value' => $new_meta_value
            ],
            ['%d', '%s', '%s']
        );
    } else {
        update_post_meta($parent_id, $availability_meta_key, $new_meta_value);
    }

    // Adjust location product count based on availability change
    // Only update count if availability actually changed
    if ($current_meta_value !== $new_meta_value) {
        $count_change = ($new_meta_value === 'yes') ? 1 : -1;
        update_location_product_count($formatted_location_id, $count_change);
    }
}

function update_location_product_count($formatted_location_id, $increment) {
    // Get the current count and cast it to an integer
    $current_count = (int) wcmlim_get_location_product_count($formatted_location_id);
    
    // Calculate the new count, ensuring it doesn't go below zero
    $new_count = max(0, $current_count + (int)$increment);
    
    // Update the location product count with the new value
    wcmlim_update_location_product_count($formatted_location_id, $new_count);
}

function wcmlim_linked_location_status($product_id, $location_id)
{

    global $wpdb;

    $sql = $wpdb->prepare(
        "SELECT COUNT(*) FROM {$wpdb->term_relationships} WHERE object_id = %d AND term_taxonomy_id = %d LIMIT 1",
        $product_id,
        $location_id
    );
    
    $count = $wpdb->get_var($sql);
    return $count ? "true" : "false";

}

function wcmlim_get_location_product_count($location_id)
{

    $count = get_term_meta($location_id, 'wcmlim_product_count', true);

    return $count;

}

function wcmlim_update_location_product_count($location_id, $count)
{

    $updated_count = update_term_meta($location_id, 'wcmlim_product_count', $count);

    return $updated_count;

}


function wcmlim_hide_specific_stock_notice() {
    global $wp_filter;

    if (!is_admin() || empty($wp_filter['admin_notices'])) {
        return;
    }

    $notices = $wp_filter['admin_notices'];

    foreach ($notices as $priority => $hooks) {
        foreach ($hooks as $key => $hook) {
            if (is_array($hook['function']) && is_object($hook['function'][0])) {
                ob_start();
                call_user_func($hook['function']);
                $output = ob_get_clean();

                if (strpos($output, 'The stock has not been updated because the value has changed since editing') !== false) {
                    // Remove this notice
                    unset($wp_filter['admin_notices'][$priority][$key]);
                }
            }
        }
    }
}
add_action('admin_head', 'wcmlim_hide_specific_stock_notice', 100);

?>