<?php

defined('ABSPATH') || exit;

/**
 * BundlePress_Bundle_Upsell
 *
 * Injects a "Complete the Bundle" upsell section on:
 *  - Single product pages (below the Add-to-Cart button)
 *  - Cart page (above the cart totals / below the cart items)
 *
 * product and renders a React root which BundleFrontend.jsx picks up.
 */
class BundlePress_Bundle_Upsell
{
    public function __construct()
    {
        // REST route so React components can look up bundles by product ID
        add_action('rest_api_init', [$this, 'register_routes']);

        // Register all potential placement hooks
        add_action('woocommerce_before_add_to_cart_form', [$this, 'maybe_render_upsell'], 10);
        add_action('woocommerce_after_add_to_cart_form',  [$this, 'maybe_render_upsell'], 10);
        add_action('woocommerce_before_single_product',   [$this, 'maybe_render_upsell'], 10);
        add_action('woocommerce_after_single_product',    [$this, 'maybe_render_upsell'], 10);
        
        // Elementor / legacy summary hooks
        add_action('woocommerce_single_product_summary', [$this, 'maybe_render_upsell'], 35);
        add_action('woocommerce_simple_add_to_cart',      [$this, 'maybe_render_upsell'], 35);

        // Shortcode support for manual placement in Elementor or other builders
        add_shortcode('bundlepress_upsell', [$this, 'render_upsell_shortcode']);
    }

    private $rendered_products = [];

    public function public_permission_check()
    {
        return true;
    }

    /* ------------------------------------------------------------------ */
    /*  REST API                                                            */
    /* ------------------------------------------------------------------ */

    public function register_routes()
    {
        register_rest_route('bundlepress/v1', '/bundles-by-product/(?P<product_id>\d+)', [
            'methods' => 'GET',
            'callback' => [$this, 'get_bundles_containing_product'],
            'permission_callback' => [$this, 'public_permission_check'],
            'args' => [
                'product_id' => [
                    'validate_callback' => function ($param) {
                        return is_numeric($param); },
                ],
            ],
        ]);

        register_rest_route('bundlepress/v1', '/recommendations/(?P<product_id>\d+)', [
            'methods' => 'GET',
            'callback' => [$this, 'get_recommendations_api'],
            'permission_callback' => [$this, 'public_permission_check'],
            'args' => [
                'product_id' => [
                    'validate_callback' => function ($param) {
                        return is_numeric($param); },
                ],
                'limit' => [
                    'validate_callback' => function ($param) {
                        return is_numeric($param); },
                ],
            ],
        ]);
    }

    public function get_recommendations_api($request)
    {
        $product_id = absint($request['product_id']);
        $limit = isset($request['limit']) ? absint($request['limit']) : 4;

        $items = $this->get_product_recommendations($product_id, $limit);

        return rest_ensure_response([
            'success' => true,
            'data' => $items
        ]);
    }

    /**
     * Return all published bundles that include $product_id as an item.
     * Also matches the *parent* product if a variation ID is passed.
     */
    public function get_bundles_containing_product($request)
    {
        $product_id = absint($request['product_id']);

        // If it is a variation, also match the parent product ID
        $ids_to_check = [$product_id];
        $product = wc_get_product($product_id);
        if ($product && $product->get_type() === 'variation') {
            $ids_to_check[] = $product->get_parent_id();
        }

        global $wpdb;
        $items_table = $wpdb->prefix . 'bundlepress_bundle_items';
        $posts_table = $wpdb->prefix . 'posts';
        $meta_table = $wpdb->prefix . 'postmeta';

        $placeholders = implode(',', array_fill(0, count($ids_to_check), '%d'));

        global $wpdb;
        $bundles_table = $wpdb->prefix . 'bundlepress_bundles';
        $items_table   = $wpdb->prefix . 'bundlepress_bundle_items';
        $fixed_table   = $wpdb->prefix . 'bundlepress_fixed_settings';
        $volume_table  = $wpdb->prefix . 'bundlepress_volume_settings';
        $fbt_table     = $wpdb->prefix . 'bundlepress_fbt_settings';
        $bxgy_table    = $wpdb->prefix . 'bundlepress_bxgy_settings';
        $mixmatch_table = $wpdb->prefix . 'bundlepress_mixmatch_settings';

        $placeholders = implode(',', array_fill(0, count($ids_to_check), '%d'));

        // 1. Get bundles where product is specifically listed as an item
        $specific_bundle_ids = $wpdb->get_col($wpdb->prepare(
            "SELECT DISTINCT bundle_id FROM $items_table WHERE product_id IN ($placeholders)",
            ...$ids_to_check
        ));

        // 2. Get all promotion bundles (volume, fbt, bxgy, mixmatch) that might be store-wide or triggered
        $promo_bundles = $wpdb->get_results("SELECT id, type, product_id FROM $bundles_table WHERE type IN ('volume', 'fbt', 'bxgy', 'mixmatch', 'fixed') AND status = 'publish'", ARRAY_A);
        
        $bundle_ids = $specific_bundle_ids;

        foreach ($promo_bundles as $pb) {
            $pb_id = (int) $pb['id'];
            $data = BundlePress_DB::get_bundle_data($pb_id);
            if (!$data) continue;

            $settings = $data['settings'] ?? [];
            $target = $settings['target_type'] ?? 'all';

            if ($target === 'all') {
                $bundle_ids[] = $pb_id;
            } elseif ($target === 'specific' && !empty($settings['trigger_products'])) {
                $trigger_ids = wp_list_pluck($settings['trigger_products'], 'product_id');
                foreach ($ids_to_check as $check_id) {
                    if (in_array((int)$check_id, array_map('intval', $trigger_ids))) {
                        $bundle_ids[] = $pb_id;
                        break;
                    }
                }
            }
        }

        $bundle_ids = array_unique(array_map('intval', $bundle_ids));

        if (empty($bundle_ids)) {
            return rest_ensure_response(['success' => true, 'data' => []]);
        }

        $bundles = [];
        foreach ($bundle_ids as $bid) {
            $data = BundlePress_DB::get_bundle_data($bid);
            if (!$data || $data['status'] !== 'publish') {
                continue;
            }

            $b_type         = $data['type'];
            $regular_price  = (float) ($data['price'] ?? 0);
            $sale_price     = (float) ($data['sale_price'] ?? 0);
            $discount_type  = $data['discount_type'] ?? '';
            $discount_value = (float) ($data['discount_value'] ?? 0);

            // For volume/mixmatch bundles, if regular price is 0, use the current product's price
            if ($regular_price <= 0 && in_array($b_type, ['volume', 'mixmatch'])) {
                $regular_price = (float) $product->get_regular_price();
            }

            $settings = $data['settings'] ?? [];

            // If it has specific trigger products, ensure the current product is one of them
            if (isset($settings['target_type']) && $settings['target_type'] === 'specific' && !empty($settings['trigger_products'])) {
                $trigger_ids = wp_list_pluck($settings['trigger_products'], 'product_id');
                $is_triggered = false;
                foreach ($ids_to_check as $check_id) {
                    if (in_array($check_id, $trigger_ids)) {
                        $is_triggered = true;
                        break;
                    }
                }
                if (!$is_triggered)
                    continue;
            }

            $display_price = $sale_price ?: $regular_price;
            if (!$sale_price && $discount_type) {
                if ($discount_type === 'percentage') {
                    $display_price = $regular_price - ($regular_price * $discount_value / 100);
                } elseif ($discount_type === 'fixed') {
                    $display_price = max(0, $regular_price - $discount_value);
                }
            }

            // Gather items for preview
            $raw_items = $wpdb->get_results($wpdb->prepare(
                "SELECT id, product_id, variation_id, quantity FROM {$wpdb->prefix}bundlepress_bundle_items WHERE bundle_id = %d ORDER BY position ASC LIMIT 10",
                $bid
            ), ARRAY_A);

            // If it's a store-wide volume/fbt bundle and raw_items is empty, inject the current product
            if (empty($raw_items) && in_array($b_type, ['volume', 'fbt'])) {
                $raw_items[] = [
                    'product_id' => $product_id,
                    'quantity' => 1
                ];
            }

            $bundle_items = [];

            // For FBT, gather items based on source settings
            if ($b_type === 'fbt') {

                if (isset($settings['fbt_source']) && $settings['fbt_source'] === 'auto') {
                    $limit = isset($settings['fbt_limit']) ? absint($settings['fbt_limit']) : 4;
                    $recommendations = $this->get_product_recommendations($product_id, $limit);
                    $bundle_items = array_merge($bundle_items, $recommendations);
                } else {
                    foreach ($raw_items as $ri) {
                        // Avoid duplicating the current product if it's also in the manual list
                        if ((int) $ri['product_id'] === $product_id)
                            continue;

                        $rp = wc_get_product($ri['product_id']);
                        if ($rp) {
                            $v_id = isset($ri['variation_id']) ? (int) $ri['variation_id'] : null;
                            $attr_values = [];
                            if ($rp->get_type() === 'variable') {
                                $attr_values = $rp->get_variation_attributes();
                            }

                            $bundle_items[] = [
                                'id'           => isset($ri['id']) ? (int) $ri['id'] : 'ri_' . $ri['product_id'],
                                'product_id'   => (int) $ri['product_id'],
                                'variation_id' => $v_id,
                                'quantity'     => (int) ($ri['quantity'] ?? 1),
                                'name'         => $rp->get_name(),
                                'price'        => $v_id ? (float)wc_get_product($v_id)->get_price() : ($rp->get_type() === 'variable' ? (float)$rp->get_variation_price('min') : (float)$rp->get_price()),
                                'regular_price' => $v_id ? (float)wc_get_product($v_id)->get_regular_price() : ($rp->get_type() === 'variable' ? (float)$rp->get_variation_regular_price('min') : (float)$rp->get_regular_price()),
                                'image'        => wp_get_attachment_thumb_url($rp->get_image_id()) ?: '',
                                'type'         => $rp->get_type(),
                                'permalink'    => $rp->get_permalink(),
                                'variations'   => ($rp->get_type() === 'variable') ? array_map(function($v) use($rp) {
                                    return [
                                        'id' => $v['variation_id'],
                                        'name' => implode(', ', array_filter($v['attributes'])),
                                        'price' => $v['display_price'],
                                        'regular_price' => $v['display_regular_price'],
                                        'attributes' => $v['attributes']
                                    ];
                                }, method_exists($rp, 'get_available_variations') ? $this->sort_variations_by_attribute_order($rp->get_available_variations(), $rp) : []) : [],
                                'attribute_values' => $attr_values,
                            ];
                        }
                    }
                }
            } else {
                // Non-FBT logic (Volume, MixMatch, etc)
                foreach ($raw_items as $ri) {
                    $rp = wc_get_product($ri['product_id']);
                    if ($rp) {
                        $v_id = isset($ri['variation_id']) ? (int) $ri['variation_id'] : null;
                        $attr_values = [];
                        if ($rp->get_type() === 'variable') {
                            $attr_values = $rp->get_variation_attributes();
                            // Optional: If taxonomy attributes, they might need term name resolution or just rely on the slug
                        }

                        $bundle_items[] = [
                            'id'           => isset($ri['id']) ? (int) $ri['id'] : 'ri_' . $ri['product_id'],
                            'product_id'   => (int) $ri['product_id'],
                            'variation_id' => $v_id,
                            'quantity'     => (int) ($ri['quantity'] ?? 1),
                            'name'         => $rp->get_name(),
                            'price'        => $v_id ? (float)wc_get_product($v_id)->get_price() : ($rp->get_type() === 'variable' ? (float)$rp->get_variation_price('min') : (float)$rp->get_price()),
                            'regular_price' => $v_id ? (float)wc_get_product($v_id)->get_regular_price() : ($rp->get_type() === 'variable' ? (float)$rp->get_variation_regular_price('min') : (float)$rp->get_regular_price()),
                            'image'        => wp_get_attachment_thumb_url($rp->get_image_id()) ?: '',
                            'type'         => $rp->get_type(),
                            'permalink'    => $rp->get_permalink(),
                            'variations'   => ($rp->get_type() === 'variable') ? array_map(function($v) use($rp) {
                                return [
                                    'id' => $v['variation_id'],
                                    'name' => implode(', ', array_filter($v['attributes'])),
                                    'price' => $v['display_price'],
                                    'regular_price' => $v['display_regular_price'],
                                    'attributes' => $v['attributes']
                                ];
                            }, method_exists($rp, 'get_available_variations') ? $this->sort_variations_by_attribute_order($rp->get_available_variations(), $rp) : []) : [],
                            'attribute_values' => $attr_values,
                        ];
                    }
                }
            }

            // For BXGY: resolve offer_product (free gift) into full product details
            $bxgy_offer_items = [];
            if ($b_type === 'bxgy' && !empty($settings['offer_product'])) {
                $offer_products = $settings['offer_product'];
                // Normalize: can be a single product object or array of product objects
                if (isset($offer_products['product_id'])) {
                    $offer_products = [$offer_products];
                } elseif (!is_array($offer_products)) {
                    $offer_products = [];
                }

                foreach ($offer_products as $op) {
                    $op_id = isset($op['product_id']) ? (int) $op['product_id'] : 0;
                    if (!$op_id && isset($op['id']))
                        $op_id = (int) $op['id'];
                    if (!$op_id)
                        continue;

                    $op_product = wc_get_product($op_id);
                    if ($op_product) {
                        $v_id = isset($op['variation_id']) ? (int) $op['variation_id'] : null;
                        $bxgy_offer_items[] = [
                            'id'           => 'offer_' . $op_id,
                            'product_id'   => $op_id,
                            'variation_id' => $v_id,
                            'name'         => $op_product->get_name(),
                            'price'        => $v_id ? (float)wc_get_product($v_id)->get_price() : (float)$op_product->get_price(),
                            'image'        => wp_get_attachment_thumb_url($op_product->get_image_id()) ?: '',
                            'type'         => $op_product->get_type(),
                            'permalink'    => $op_product->get_permalink(),
                            'variations'   => ($op_product->get_type() === 'variable') ? array_map(function($v) {
                                return [
                                    'id' => $v['variation_id'],
                                    'name' => implode(', ', array_filter($v['attributes'])),
                                    'price' => $v['display_price'],
                                    'attributes' => $v['attributes']
                                ];
                            }, method_exists($op_product, 'get_available_variations') ? $this->sort_variations_by_attribute_order($op_product->get_available_variations(), $op_product) : []) : [],
                        ];
                    }
                }
            }

            $bundles[] = [
                'id'               => (int) $bid,
                'product_id'       => $data['product_id'] ? (int) $data['product_id'] : null,
                'name'             => $data['name'],
                'type'             => $b_type ?: 'fixed',
                'settings'         => $settings,
                'url'              => ($data['product_id'] ? get_permalink($data['product_id']) : '#'),
                'image_url'        => $data['image_url'] ?: '',
                'short_description'=> isset($data['short_description']) ? wp_kses_post($data['short_description']) : '',
                'gallery'          => isset($data['gallery']) ? $data['gallery'] : [],
                'regular_price'    => $regular_price,
                'display_price'    => $display_price,
                'discount_type'    => $discount_type,
                'discount_value'   => $discount_value,
                'sale_price'       => $sale_price ?: null,
                'item_names'       => array_column($bundle_items, 'name'),
                'item_count'       => count($bundle_items),
                'items'            => $bundle_items,
                'bxgy_offer_items' => $bxgy_offer_items,
            ];
        }

        return rest_ensure_response(['success' => true, 'data' => $bundles]);
    }

    /**
     * Get WooCommerce recommendations (Upsells -> Cross-sells -> Related)
     */
    private function get_product_recommendations($product_id, $limit = 4)
    {
        $product = wc_get_product($product_id);
        if (!$product)
            return [];

        $recommended_ids = [];

        // 1. Try Upsells
        $recommended_ids = array_merge($recommended_ids, $product->get_upsell_ids());

        // 2. Try Cross-sells if needed
        if (count($recommended_ids) < $limit) {
            $recommended_ids = array_unique(array_merge($recommended_ids, $product->get_cross_sell_ids()));
        }

        // 3. Try Related products if still needed
        if (count($recommended_ids) < $limit) {
            $related = wc_get_related_products($product_id, $limit * 2);
            $recommended_ids = array_unique(array_merge($recommended_ids, $related));
        }

        // 4. Fallback: Products in same category
        if (count($recommended_ids) < $limit) {
            $cat_ids = $product->get_category_ids();
            if (!empty($cat_ids)) {
                $args = [
                    'post_type' => 'product',
                    'post_status' => 'publish',
                    'posts_per_page' => $limit,
                    'post__not_in' => array_merge([$product_id], $recommended_ids),
                    'tax_query' => [
                        [
                            'taxonomy' => 'product_cat',
                            'field' => 'term_id',
                            'terms' => $cat_ids,
                        ],
                    ],
                    'fields' => 'ids'
                ];
                $cat_products = get_posts($args);
                $recommended_ids = array_unique(array_merge($recommended_ids, $cat_products));
            }
        }

        // 5. Final Fallback: Recent Products
        if (count($recommended_ids) < $limit) {
            $recent = get_posts([
                'post_type' => 'product',
                'post_status' => 'publish',
                'posts_per_page' => $limit,
                'post__not_in' => array_merge([$product_id], $recommended_ids),
                'fields' => 'ids'
            ]);
            $recommended_ids = array_unique(array_merge($recommended_ids, $recent));
        }

        // Clean up: remove current product and slice to limit
        $recommended_ids = array_diff($recommended_ids, [$product_id]);
        $recommended_ids = array_slice($recommended_ids, 0, $limit);

        $items = [];
        foreach ($recommended_ids as $pid) {
            $rp = wc_get_product($pid);
            if ($rp && $rp->is_visible()) {
                $items[] = [
                    'id'         => 'rec_' . $pid,
                    'product_id' => (int) $pid,
                    'quantity' => 1,
                    'name' => $rp->get_name(),
                    'price' => $rp->get_price(),
                    'image' => wp_get_attachment_thumb_url($rp->get_image_id()) ?: '',
                    'permalink' => $rp->get_permalink(),
                ];
            }
        }

        return $items;
    }

    private function sort_variations_by_attribute_order(array $variations_data, $product): array
    {
        $attributes = $product->get_attributes();

        usort($attributes, function ($a, $b) {
            return $a->get_position() <=> $b->get_position();
        });

        $attr_value_order = [];
        foreach ($attributes as $attr) {
            $attr_name = $attr->get_name();
            $attr_key = strpos($attr_name, 'pa_') === 0
                ? 'attribute_' . $attr_name
                : 'attribute_' . strtolower(sanitize_title($attr_name));

            $options = $attr->get_options();
            $ordered_slugs = [];

            if ($attr->is_taxonomy()) {
                foreach ($options as $term_id) {
                    $term = get_term($term_id);
                    if ($term && !is_wp_error($term)) {
                        $ordered_slugs[] = $term->slug;
                    }
                }
            } else {
                $ordered_slugs = array_map(function ($val) {
                    return strtolower(sanitize_title($val));
                }, $options);
            }

            $attr_value_order[$attr_key] = array_flip($ordered_slugs);
        }

        usort($variations_data, function ($a, $b) use ($attr_value_order) {
            foreach ($attr_value_order as $attr_key => $value_order) {
                $val_a = $a['attributes'][$attr_key] ?? '';
                $val_b = $b['attributes'][$attr_key] ?? '';

                $pos_a = ($val_a !== '') ? ($value_order[$val_a] ?? PHP_INT_MAX) : PHP_INT_MAX;
                $pos_b = ($val_b !== '') ? ($value_order[$val_b] ?? PHP_INT_MAX) : PHP_INT_MAX;

                if ($pos_a !== $pos_b) {
                    return $pos_a <=> $pos_b;
                }
            }
            return 0;
        });

        return $variations_data;
    }

    /* ------------------------------------------------------------------ */
    /*  Template helpers                                                    */
    /* ------------------------------------------------------------------ */

    public function maybe_render_upsell()
    {
        $customizations = BundlePress_Customization_API::get_customizations_flat();
        $placement      = $customizations['general_bundle_placement'] ?? 'woocommerce_after_add_to_cart_form';
        $current_action = current_action();

        $should_render = false;

        // 1. Exact match for standard WC hooks
        if ($current_action === $placement) {
            $should_render = true;
        }

        // 2. Elementor / Legacy summary hook mapping
        // If user wants it AFTER, and we are on summary or simple_add_to_cart hook
        $after_hooks = ['woocommerce_single_product_summary', 'woocommerce_simple_add_to_cart', 'woocommerce_after_add_to_cart_form'];
        if (in_array($current_action, $after_hooks, true) && $placement === 'woocommerce_after_add_to_cart_form') {
            $should_render = true;
        }

        // Handle Elementor specifically: it usually fires simple_add_to_cart for the button area.
        if ($current_action === 'woocommerce_simple_add_to_cart') {
            $should_render = true;
        }

        if ($should_render) {
            $this->render_product_upsell();
        }
    }

    public function render_product_upsell()
    {
        global $product;

        if (!$product || $product->get_type() === 'bundlepress' || is_admin()) {
            return; // don't show on bundle product pages themselves
        }

        $product_id = $product->get_id();

        // Prevent double rendering on the same product page
        if (isset($this->rendered_products[$product_id])) {
            return;
        }
        $this->rendered_products[$product_id] = true;

        // Check if this product is actually a fixed bundle (handles cases where term is cached as 'simple')
        global $wpdb;
        $is_fixed_bundle = $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM {$wpdb->prefix}bundlepress_bundles WHERE product_id = %d AND type = 'fixed'",
            $product_id
        ));
        
        if ($is_fixed_bundle) {
            return;
        }

        // Quick DB check – only render if at least one bundle contains this product

        if (!$this->product_has_bundles($product_id)) {
            echo '<!-- BundlePress DEBUG: Product ' . esc_html($product_id) . ' has no associated bundles for upsell -->';
            return;
        }

        echo '<!-- BundlePress Upsell Root Injection -->';
        echo '<div id="bundlepress-upsell-root-product-' . esc_attr($product_id) . '" '
            . 'class="bundlepress-upsell-root" '
            . 'data-product-id="' . esc_attr($product_id) . '" '
            . 'data-context="product" '
            . 'style="margin: 24px 0;"></div>';
    }

    /**
     * Shortcode callback for [bundlepress_upsell]
     */
    public function render_upsell_shortcode($atts)
    {
        global $product;
        $pid = null;

        if (isset($atts['product_id'])) {
            $pid = absint($atts['product_id']);
        } elseif ($product) {
            $pid = $product->get_id();
        }

        if (!$pid) {
            return '<!-- BundlePress: No product context for upsell shortcode -->';
        }

        // We don't use the rendering guard for shortcodes as the user might explicitly want it twice
        // or they might be using it instead of the automatic hooks.

        if (!$this->product_has_bundles($pid)) {
            return '<!-- BundlePress: Product ' . esc_html($pid) . ' has no associated bundles for upsell -->';
        }

        return '<div id="bundlepress-upsell-root-product-' . esc_attr($pid) . '" '
            . 'class="bundlepress-upsell-root" '
            . 'data-product-id="' . esc_attr($pid) . '" '
            . 'data-context="product" '
            . 'style="margin: 24px 0;"></div>';
    }



    /**
     * Cheap check: does any published bundle contain this product?
     */
    private function product_has_bundles(int $product_id): bool
    {
        global $wpdb;
        $items_table = $wpdb->prefix . 'bundlepress_bundle_items';
        $bundles_table = $wpdb->prefix . 'bundlepress_bundles';

        $ids = [$product_id];
        $p = wc_get_product($product_id);
        if ($p && $p->get_type() === 'variation') {
            $ids[] = $p->get_parent_id();
        }

        $placeholders = implode(',', array_fill(0, count($ids), '%d'));

        // 1. Check if product is explicitly in bundle items
        // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
        $has_direct = (bool) $wpdb->get_var($wpdb->prepare(
            "SELECT 1 FROM $items_table as items 
             JOIN $bundles_table as bundles ON items.bundle_id = bundles.id 
             WHERE items.product_id IN ($placeholders) AND bundles.status = 'publish' LIMIT 1",
            ...$ids
        ));

        if ($has_direct) return true;

        // 2. Check store-wide or triggered bundles
        $promo_bundles = $wpdb->get_results("SELECT id, type FROM $bundles_table WHERE status = 'publish' AND type IN ('volume', 'fbt', 'bxgy')", ARRAY_A);
        foreach ($promo_bundles as $pb) {
            $data = BundlePress_DB::get_bundle_data($pb['id']);
            if (!$data) continue;
            
            $settings = $data['settings'] ?? [];
            $target = $settings['target_type'] ?? 'all';
            if ($target === 'all') return true;

            if ($target === 'specific' && !empty($settings['trigger_products'])) {
                $trigger_ids = wp_list_pluck($settings['trigger_products'], 'product_id');
                foreach ($ids as $check_id) {
                    if (in_array((int)$check_id, array_map('intval', $trigger_ids))) return true;
                }
            }
        }

        return false;
    }
}
