<?php

if (!defined('ABSPATH')) {
    exit;
}

class AIEO_DMM_Brand_Gifts extends AIEO_DMM_Module_Base {

    public function get_id() { return 'brand_gifts'; }
    public function get_label() { return __('Free Gifts', 'ai-eshop-optimizer'); }
    public function get_priority() { return 45; }
    public function get_group() { return 'special_pricing_offers'; }

    
    private $is_syncing = false;

    
    private static $instance = null;
    public static function instance() {
        if (self::$instance === null) {
            
            
            
            $existing = function_exists('AIEO_DMM') ? null : null;
            if (class_exists('AIEO_DMM')) {
                $mod = AIEO_DMM::instance()->get_module('brand_gifts');
                if ($mod instanceof self) { self::$instance = $mod; }
            }
            if (self::$instance === null) { self::$instance = new self(); }
        }
        return self::$instance;
    }
    public function __construct() { if (self::$instance === null) { self::$instance = $this; } }

    
    private static $is_internal_add = false;

    public function register_hooks() {
        
        
        
        add_filter('aieo_eligibility_compute', array(__CLASS__, 'add_eligibility_row'), 10, 3);

        add_action('wp_ajax_aieo_dmm_brand_gift_save', array($this, 'ajax_save'));
        add_action('wp_ajax_aieo_dmm_brand_gift_delete', array($this, 'ajax_delete'));
        add_action('wp_ajax_aieo_dmm_search_products', array($this, 'ajax_search_products'));
        add_action('wp_ajax_aieo_dmm_search_need_terms', array($this, 'ajax_search_need_terms'));
        
        add_action('wp_ajax_aieo_dmm_brand_gift_pick',        array($this, 'ajax_pick_gift'));
        add_action('wp_ajax_nopriv_aieo_dmm_brand_gift_pick', array($this, 'ajax_pick_gift'));
        add_action('wp_ajax_aieo_dmm_brand_gift_variations',        array($this, 'ajax_get_variations'));
        add_action('wp_ajax_nopriv_aieo_dmm_brand_gift_variations', array($this, 'ajax_get_variations'));

        
        
        
        
        
        
        add_filter('woocommerce_is_purchasable',     array($this, 'filter_sample_unpurchasable'), 10, 2);
        add_action('woocommerce_product_query',      array($this, 'exclude_samples_from_archive'));
        add_action('pre_get_posts',                  array($this, 'exclude_samples_from_search'));
        add_action('woocommerce_update_product',     array($this, 'flush_sample_ids_cache'));

        
        
        add_action('woocommerce_product_options_general_product_data', array($this, 'render_gift_type_field'));
        add_action('woocommerce_process_product_meta',                 array($this, 'save_gift_type_field'));

        
        
        
        
        
        
        
        
        
        $dash_on = class_exists('AIEO_DMM_Product_Display')
            && AIEO_DMM_Product_Display::module_is_enabled('aieo_dmm_brand_gifts_settings');
        if (AIEO_DMM_Settings::get('recipe.brand_gift', 'over_and_above') !== 'off' && $dash_on) {
            
            
            
            
            
            
            
            
            if ( ! defined( 'AIEO_RUNTIME_OWNS_AJAX' ) ) {
                add_action('woocommerce_cart_loaded_from_session', array($this, 'sync_gifts'), 99);
                add_action('woocommerce_add_to_cart', array($this, 'sync_gifts_deferred'), 99);
                add_action('woocommerce_cart_item_removed', array($this, 'sync_gifts_deferred'), 99);
                add_action('woocommerce_after_cart_item_quantity_update', array($this, 'sync_gifts_deferred'), 99);
                add_action('woocommerce_before_calculate_totals', array($this, 'set_gift_prices'), 99);
                add_filter('woocommerce_cart_item_quantity', array($this, 'lock_gift_quantity'), 10, 3);
                add_filter('woocommerce_cart_item_name', array($this, 'add_gift_badge'), 10, 3);
                add_filter('woocommerce_cart_item_remove_link', array($this, 'hide_gift_remove_link'), 10, 2);
            }

            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            
            $is_block_theme = function_exists('wp_is_block_theme') && wp_is_block_theme();
            $use_wc_hook    = (bool) apply_filters('aieo_dmm_brand_gifts_fse_use_hook', ! $is_block_theme);
            if ($use_wc_hook) {
                add_action('woocommerce_single_product_summary',                 array($this, 'render_single_product_section'), 25);
                add_filter('render_block_woocommerce/add-to-cart-form',          array($this, 'inject_single_product_section_into_block'), 12, 2);
            }
            
            
            
            
            
            add_action('woocommerce_before_shop_loop_item_title', array($this, 'render_archive_badge'), 12);
            
            
            
            
            
            
            
            
            
            
            add_action('woocommerce_archive_description',                  array($this, 'render_archive_banner'), 5);
            add_filter('render_block_core/term-description',               array($this, 'inject_archive_banner_into_block'), 5, 2);
            add_filter('render_block_woocommerce/product-collection',      array($this, 'inject_archive_banner_into_block'), 5, 2);
            
            
            
            add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        }
    }

    
    public function enqueue_frontend_assets() {
        $css_rel = 'assets/css/aieo-brand-gifts.css';
        $js_rel  = 'assets/js/aieo-brand-gifts.js';
        $css_path = dirname(AIEO_FILE) . '/' . $css_rel;
        $js_path  = dirname(AIEO_FILE) . '/' . $js_rel;
        $css_ver  = file_exists($css_path) ? filemtime($css_path) : AIEO_VERSION;
        $js_ver   = file_exists($js_path)  ? filemtime($js_path)  : AIEO_VERSION;
        wp_enqueue_style('aieo-brand-gifts',  plugins_url($css_rel, AIEO_FILE), array(), $css_ver);
        wp_enqueue_script('aieo-brand-gifts', plugins_url($js_rel,  AIEO_FILE), array('jquery'), $js_ver, true);
        wp_localize_script('aieo-brand-gifts', 'aieoBrandGifts', array(
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce'   => wp_create_nonce('aieo_side_cart'),
            'i18n'    => array(
                'pickVariation' => __('— Pick variation —', 'ai-eshop-optimizer'),
                'noVariations'  => __('No in-stock variations available.', 'ai-eshop-optimizer'),
                'claimed'       => __('Gift added to your cart.', 'ai-eshop-optimizer'),
                'error'         => __('Could not update — please try again.', 'ai-eshop-optimizer'),
            ),
        ));
    }

    public function render_subtab() {
        $this->render_template('brand-gifts.php', array(
            'offers' => $this->fetch_all_offers(true),  
            'module' => $this,
        ));
    }

    
    public function fetch_all_offers($with_labels = false) {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_gift_offers';
        if (!aieo_dmm_table_exists($table)) {
            return array();
        }
        
        $rows = $wpdb->get_results("SELECT * FROM {$table} ORDER BY enabled DESC, id DESC", ARRAY_A);
        $out = array();
        if (is_array($rows)) {
            foreach ($rows as $row) {
                if ($with_labels) {
                    
                    
                    $resolved = $this->fetch_offer_with_labels((int) $row['id']);
                    if ($resolved) { $out[] = $resolved; continue; }
                }
                $row['brand_term_ids']    = json_decode($row['brand_term_ids'] ?? '[]', true) ?: array();
                $row['gift_product_ids']  = json_decode($row['gift_product_ids'] ?? '[]', true) ?: array();
                $row['category_term_ids'] = json_decode($row['category_term_ids'] ?? '[]', true) ?: array();
                $row['need_term_ids']     = json_decode($row['need_term_ids'] ?? '[]', true) ?: array();
                $row['rule_operator']     = (!empty($row['rule_operator']) && strtoupper($row['rule_operator']) === 'OR') ? 'OR' : 'AND';
                $out[] = $row;
            }
        }
        return $out;
    }

    
    public function get_active_offers() {
        return AIEO_DMM_Cache::remember('gifts', 'active_offers', function () {
            $all = $this->fetch_all_offers();
            $today = current_time('Y-m-d');
            $active = array();
            foreach ($all as $offer) {
                if (empty($offer['enabled'])) {
                    continue;
                }
                if (!empty($offer['date_from']) && $offer['date_from'] > $today) {
                    continue;
                }
                if (!empty($offer['date_to']) && $offer['date_to'] < $today) {
                    continue;
                }
                $active[] = $offer;
            }
            return $active;
        }, AIEO_DMM_Cache::TTL_SHORT);
    }

    public function ajax_save() {
        AIEO_DMM::verify_ajax_request();

        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_gift_offers';
        if (!aieo_dmm_table_exists($table)) {
            wp_send_json_error(array('message' => __('Table missing.', 'ai-eshop-optimizer')));
        }

        $id        = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;
        $is_update = $id > 0;

        
        
        $need_ids = isset($_POST['need_term_ids']) && is_array($_POST['need_term_ids'])
            ? array_values(array_filter(array_map('absint', wp_unslash($_POST['need_term_ids']))))
            : array();
        $brand_ids = isset($_POST['brand_term_ids']) && is_array($_POST['brand_term_ids'])
            ? array_map('absint', wp_unslash($_POST['brand_term_ids']))
            : array();
        $category_ids = isset($_POST['category_term_ids']) && is_array($_POST['category_term_ids'])
            ? array_map('absint', wp_unslash($_POST['category_term_ids']))
            : array();
        $gift_ids = isset($_POST['gift_product_ids']) && is_array($_POST['gift_product_ids'])
            ? array_map('absint', wp_unslash($_POST['gift_product_ids']))
            : array();

        $brand_ids    = array_values(array_filter($brand_ids));
        $category_ids = array_values(array_filter($category_ids));

        
        
        
        
        $excluded_brand_ids = isset($_POST['excluded_brand_ids']) && is_array($_POST['excluded_brand_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_brand_ids']))))) : array();
        $excluded_category_ids = isset($_POST['excluded_category_ids']) && is_array($_POST['excluded_category_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_category_ids']))))) : array();
        $excluded_need_ids = isset($_POST['excluded_need_ids']) && is_array($_POST['excluded_need_ids'])
            ? array_values(array_unique(array_filter(array_map('absint', wp_unslash($_POST['excluded_need_ids']))))) : array();

        
        
        
        $product_ids = AIEO_DMM_Product_Picker::roll_up_to_parents(
            AIEO_DMM_Product_Picker::collect_ids('product_ids')
        );
        $excluded_product_ids = AIEO_DMM_Product_Picker::roll_up_to_parents(
            AIEO_DMM_Product_Picker::collect_ids('excluded_product_ids')
        );

        $rule_operator = isset($_POST['rule_operator']) && sanitize_key(wp_unslash($_POST['rule_operator'])) === 'or' ? 'OR' : 'AND';
        $min_subtotal  = isset($_POST['min_subtotal']) ? (float) $_POST['min_subtotal'] : 0.0;

        
        
        if (empty($brand_ids) && empty($category_ids) && empty($need_ids) && $min_subtotal <= 0) {
            wp_send_json_error(array('message' => __('Pick at least one brand, category, need, or set a minimum subtotal.', 'ai-eshop-optimizer')));
        }
        if (empty($gift_ids)) {
            wp_send_json_error(array('message' => __('Pick at least one gift product.', 'ai-eshop-optimizer')));
        }

        
        
        
        $gift_kind_in = isset($_POST['gift_kind']) ? sanitize_key(wp_unslash($_POST['gift_kind'])) : 'product';
        if (!in_array($gift_kind_in, array('product', 'sample', 'mixed'), true)) { $gift_kind_in = 'product'; }
        $pres_mode_in = isset($_POST['presentation_mode']) ? sanitize_key(wp_unslash($_POST['presentation_mode'])) : 'auto';
        if (!in_array($pres_mode_in, array('list', 'dropdown', 'auto'), true)) { $pres_mode_in = 'auto'; }

        $data = array(
            'enabled'            => !empty($_POST['enabled']) ? 1 : 0,
            'label'              => isset($_POST['label']) ? sanitize_text_field(wp_unslash($_POST['label'])) : '',
            'brand_term_ids'     => wp_json_encode($brand_ids),
            'category_term_ids'  => wp_json_encode($category_ids),
            'need_term_ids'      => wp_json_encode($need_ids),
            'rule_operator'      => $rule_operator,
            'min_subtotal'       => $min_subtotal,
            'date_from'          => !empty($_POST['date_from']) ? sanitize_text_field(wp_unslash($_POST['date_from'])) : null,
            'date_to'            => !empty($_POST['date_to']) ? sanitize_text_field(wp_unslash($_POST['date_to'])) : null,
            'gift_product_ids'   => wp_json_encode(array_values(array_filter($gift_ids))),
            'before_text'        => isset($_POST['before_text']) ? wp_kses_post(wp_unslash($_POST['before_text'])) : '',
            'after_text'         => isset($_POST['after_text']) ? wp_kses_post(wp_unslash($_POST['after_text'])) : '',
            'before_image_id'    => isset($_POST['before_image_id']) ? absint(wp_unslash($_POST['before_image_id'])) : null,
            'after_image_id'     => isset($_POST['after_image_id']) ? absint(wp_unslash($_POST['after_image_id'])) : null,
            'bar_bg_before'      => sanitize_hex_color(wp_unslash($_POST['bar_bg_before']  ?? '')) ?: null,
            'bar_bg_after'       => sanitize_hex_color(wp_unslash($_POST['bar_bg_after']   ?? '')) ?: null,
            'bar_fg_before'      => sanitize_hex_color(wp_unslash($_POST['bar_fg_before']  ?? '')) ?: null,
            'bar_fg_after'       => sanitize_hex_color(wp_unslash($_POST['bar_fg_after']   ?? '')) ?: null,
            'gift_item_bg'       => sanitize_hex_color(wp_unslash($_POST['gift_item_bg']   ?? '')) ?: null,
            'show_banner'        => !empty($_POST['show_banner'])  ? 1 : 0,
            'show_rewards'       => !empty($_POST['show_rewards']) ? 1 : 0,
            'gift_kind'          => $gift_kind_in,
            'presentation_mode'  => $pres_mode_in,
            'show_when_pending'  => !empty($_POST['show_when_pending']) ? 1 : 0,
            'headline_pending'   => isset($_POST['headline_pending'])   ? sanitize_text_field(wp_unslash($_POST['headline_pending']))   : '',
            'headline_qualified' => isset($_POST['headline_qualified']) ? sanitize_text_field(wp_unslash($_POST['headline_qualified'])) : '',
            'pill_locked'        => isset($_POST['pill_locked'])    ? sanitize_text_field(wp_unslash($_POST['pill_locked']))    : '',
            'pill_available'     => isset($_POST['pill_available']) ? sanitize_text_field(wp_unslash($_POST['pill_available'])) : '',
            'pill_claimed'       => isset($_POST['pill_claimed'])   ? sanitize_text_field(wp_unslash($_POST['pill_claimed']))   : '',
            'excluded_brand_ids'    => wp_json_encode($excluded_brand_ids),
            'excluded_category_ids' => wp_json_encode($excluded_category_ids),
            'excluded_need_ids'     => wp_json_encode($excluded_need_ids),
            'product_ids'           => wp_json_encode($product_ids),
            'excluded_product_ids'  => wp_json_encode($excluded_product_ids),
        );
        $formats = array(
            '%d', '%s', '%s', '%s', '%s', '%s', '%f', '%s', '%s', '%s', '%s', '%s', '%d', '%d',
            '%s', '%s', '%s', '%s', '%s', '%d', '%d',
            '%s', '%s', '%d', '%s', '%s', '%s', '%s', '%s',
            '%s', '%s', '%s',
            '%s', '%s',
        );

        if ($is_update) {
            $wpdb->update($table, $data, array('id' => $id), $formats, array('%d'));
        } else {
            
            
            
            
            $dup_id = (int) $wpdb->get_var($wpdb->prepare(
                
                "SELECT id FROM {$table}
                 WHERE COALESCE(brand_term_ids,'[]')    = %s
                   AND COALESCE(category_term_ids,'[]') = %s
                   AND COALESCE(need_term_ids,'[]')     = %s
                   AND rule_operator                    = %s
                   AND COALESCE(min_subtotal,0)         = %f
                   AND COALESCE(gift_product_ids,'[]')  = %s
                   AND COALESCE(date_from,'')           = %s
                   AND COALESCE(date_to,'')             = %s
                 LIMIT 1",
                $data['brand_term_ids'],
                $data['category_term_ids'],
                $data['need_term_ids'],
                $data['rule_operator'],
                $data['min_subtotal'],
                $data['gift_product_ids'],
                (string) ($data['date_from'] ?? ''),
                (string) ($data['date_to'] ?? '')
            ));
            if ($dup_id > 0) {
                $id = $dup_id;
            } else {
                $wpdb->insert($table, $data, $formats);
                $id = (int) $wpdb->insert_id;
            }
        }

        AIEO_DMM_Cache::bump_version('gifts');

        
        
        
        
        $row = $this->fetch_offer_with_labels($id);
        wp_send_json_success(array(
            'id'        => $id,
            'is_update' => $is_update,
            'row'       => $row,
            'row_html'  => $this->render_offer_row($row),
            'message'   => __('Gift offer saved.', 'ai-eshop-optimizer'),
        ));
    }

    
    private function fetch_offer_with_labels($id) {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_brand_gift_offers';
        $row = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table} WHERE id = %d", (int) $id), ARRAY_A);
        if (!$row) { return null; }

        $brand_ids    = json_decode($row['brand_term_ids'] ?? '[]', true) ?: array();
        $category_ids = json_decode($row['category_term_ids'] ?? '[]', true) ?: array();
        $need_ids     = json_decode($row['need_term_ids'] ?? '[]', true) ?: array();
        $gift_ids     = json_decode($row['gift_product_ids'] ?? '[]', true) ?: array();
        $excl_brand_ids = json_decode($row['excluded_brand_ids']    ?? '[]', true) ?: array();
        $excl_cat_ids   = json_decode($row['excluded_category_ids'] ?? '[]', true) ?: array();
        $excl_need_ids  = json_decode($row['excluded_need_ids']     ?? '[]', true) ?: array();
        $product_ids_pos = json_decode($row['product_ids']           ?? '[]', true) ?: array();
        $product_ids_neg = json_decode($row['excluded_product_ids']  ?? '[]', true) ?: array();

        $brand_tax = class_exists('AIEO_DMM_Brand_Discounts') ? AIEO_DMM_Brand_Discounts::get_brand_taxonomy() : 'product_brand';
        if (!$brand_tax) { $brand_tax = 'product_brand'; }

        $resolve_term_names = function ($ids, $tax) {
            $out = array();
            foreach ($ids as $tid) {
                $t = get_term((int) $tid, $tax);
                $out[] = ($t && !is_wp_error($t)) ? (string) $t->name : ('#' . (int) $tid);
            }
            return $out;
        };
        $resolve_product_names = function ($ids) {
            $out = array();
            foreach ($ids as $pid) {
                $title = get_the_title((int) $pid);
                $out[] = ($title !== '' && $title !== null) ? (string) $title : ('#' . (int) $pid);
            }
            return $out;
        };

        $row['brand_term_ids']    = array_map('intval', $brand_ids);
        $row['category_term_ids'] = array_map('intval', $category_ids);
        $row['need_term_ids']     = array_map('intval', $need_ids);
        $row['gift_product_ids']  = array_map('intval', $gift_ids);
        $row['brand_term_names']    = $resolve_term_names($brand_ids, $brand_tax);
        $row['category_term_names'] = $resolve_term_names($category_ids, 'product_cat');
        $row['need_term_names']     = $resolve_term_names($need_ids, 'pa_need');
        $row['gift_product_names']  = $resolve_product_names($gift_ids);
        $row['rule_operator']       = (!empty($row['rule_operator']) && strtoupper($row['rule_operator']) === 'OR') ? 'OR' : 'AND';
        
        
        
        $row['excluded_brand_ids']    = array_map('intval', $excl_brand_ids);
        $row['excluded_category_ids'] = array_map('intval', $excl_cat_ids);
        $row['excluded_need_ids']     = array_map('intval', $excl_need_ids);
        $row['excluded_brand_names']    = $resolve_term_names($excl_brand_ids, $brand_tax);
        $row['excluded_category_names'] = $resolve_term_names($excl_cat_ids, 'product_cat');
        $row['excluded_need_names']     = $resolve_term_names($excl_need_ids, 'pa_need');
        
        
        
        $row['product_ids']           = array_map('intval', $product_ids_pos);
        $row['excluded_product_ids']  = array_map('intval', $product_ids_neg);
        $row['product_tokens_text']   = AIEO_DMM_Offer_Matcher::format_product_tokens($product_ids_pos);
        $row['excluded_product_tokens_text'] = AIEO_DMM_Offer_Matcher::format_product_tokens($product_ids_neg);
        
        
        $row['product_products']   = AIEO_DMM_Product_Picker::hydrate_ids($product_ids_pos);
        $row['excluded_products']  = AIEO_DMM_Product_Picker::hydrate_ids($product_ids_neg);

        
        
        
        foreach (array('before_image_id', 'after_image_id') as $key) {
            $aid = isset($row[$key]) ? (int) $row[$key] : 0;
            $url = '';
            if ($aid > 0) {
                $img = wp_get_attachment_image_src($aid, 'medium');
                if ($img && !empty($img[0])) { $url = (string) $img[0]; }
            }
            $row[str_replace('_id', '_url', $key)] = $url;
        }
        
        foreach (array('bar_bg_before','bar_bg_after','bar_fg_before','bar_fg_after','gift_item_bg') as $ck) {
            $row[$ck] = isset($row[$ck]) ? (string) $row[$ck] : '';
        }
        
        
        
        $row['show_banner']  = isset($row['show_banner'])  && $row['show_banner']  !== null ? (int) $row['show_banner']  : 1;
        $row['show_rewards'] = isset($row['show_rewards']) && $row['show_rewards'] !== null ? (int) $row['show_rewards'] : 1;
        return $row;
    }

    public function enqueue_admin_assets() {
        
        
        wp_enqueue_media();
        
        wp_enqueue_style('wp-color-picker');
        wp_enqueue_script('wp-color-picker');
        wp_add_inline_script('wp-color-picker',
            'jQuery(function($){$(".aieo-dmm-bg-color").wpColorPicker();});'
        );
    }

    
    public function render_offer_row($offer) {
        if (empty($offer) || !is_array($offer)) { return ''; }
        $data_attr = esc_attr(wp_json_encode($offer));
        $window = '';
        $df = !empty($offer['date_from']) ? esc_html($offer['date_from']) : '—';
        $dt = !empty($offer['date_to'])   ? esc_html($offer['date_to'])   : '—';
        $window = $df . ' → ' . $dt;
        $brands = !empty($offer['brand_term_names'])
            ? esc_html(implode(', ', $offer['brand_term_names']))
            : '<em class="description">' . esc_html__('(any)', 'ai-eshop-optimizer') . '</em>';
        $cats = !empty($offer['category_term_names'])
            ? esc_html(implode(', ', $offer['category_term_names']))
            : '<em class="description">' . esc_html__('(any)', 'ai-eshop-optimizer') . '</em>';
        $gifts = !empty($offer['gift_product_names'])
            ? esc_html(implode(', ', $offer['gift_product_names']))
            : '—';
        $op    = esc_html(isset($offer['rule_operator']) ? $offer['rule_operator'] : 'AND');
        $label = esc_html((string) ($offer['label'] ?? ''));
        $sub   = esc_html(number_format((float) ($offer['min_subtotal'] ?? 0), 2));
        $en    = !empty($offer['enabled']) ? '✔' : '—';

        return '<tr data-id="' . (int) $offer['id'] . '" data-offer="' . $data_attr . '">'
            . '<td>' . $label . '</td>'
            . '<td>' . $brands . '</td>'
            . '<td>' . $cats . '</td>'
            . '<td><strong>' . $op . '</strong></td>'
            . '<td>' . $sub . '</td>'
            . '<td>' . $gifts . '</td>'
            . '<td>' . esc_html($window) . '</td>'
            . '<td>' . $en . '</td>'
            . '<td>'
            .   '<button type="button" class="button button-small aieo-dmm-edit-gift">'
            .     esc_html__('Edit', 'ai-eshop-optimizer')
            .   '</button> '
            .   '<button type="button" class="button button-small aieo-dmm-delete-row" data-action="aieo_dmm_brand_gift_delete">'
            .     esc_html__('Delete', 'ai-eshop-optimizer')
            .   '</button>'
            . '</td>'
            . '</tr>';
    }

    public function ajax_delete() {
        AIEO_DMM::verify_ajax_request();
        $id = isset($_POST['id']) ? absint(wp_unslash($_POST['id'])) : 0;
        if ($id <= 0) {
            wp_send_json_error(array('message' => __('Invalid id.', 'ai-eshop-optimizer')));
        }
        global $wpdb;
        $wpdb->delete($wpdb->prefix . 'aieo_dmm_brand_gift_offers', array('id' => $id), array('%d'));
        AIEO_DMM_Cache::bump_version('gifts');
        wp_send_json_success();
    }

    
    
    public function ajax_search_need_terms() {
        AIEO_DMM::verify_ajax_request();
        $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
        if (!taxonomy_exists('pa_need')) {
            wp_send_json(array('results' => array()));
        }
        $args = array('taxonomy' => 'pa_need', 'hide_empty' => false, 'number' => 50);
        if ($q !== '') { $args['name__like'] = $q; }
        $terms = get_terms($args);
        $results = array();
        if (is_array($terms)) {
            foreach ($terms as $t) {
                $results[] = array(
                    'id'   => (int) $t->term_id,
                    'text' => $t->name . ' (' . (int) $t->count . ')',
                );
            }
        }
        wp_send_json(array('results' => $results));
    }

    public function ajax_search_products() {
        AIEO_DMM::verify_ajax_request();

        $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
        $limit = 25;

        if (!function_exists('wc_get_products')) {
            wp_send_json(array('results' => array()));
        }

        $products = wc_get_products(array(
            'status'  => array('publish', 'private'),
            'limit'   => $limit,
            's'       => $q,
            'orderby' => 'title',
            'order'   => 'ASC',
        ));

        $results = array();
        foreach ($products as $product) {
            $results[] = array(
                'id'   => (int) $product->get_id(),
                'text' => $product->get_name() . ($product->get_sku() ? ' [' . $product->get_sku() . ']' : ''),
            );
        }
        wp_send_json(array('results' => $results));
    }

    
    
    

    public function sync_gifts_deferred() {
        add_action('woocommerce_calculated_shipping', array($this, 'sync_gifts'));
        add_action('shutdown', array($this, 'sync_gifts'));
    }

    
    public function sync_gifts() {
        if ($this->is_syncing) {
            return;
        }
        if (!function_exists('WC') || !WC()->cart) {
            return;
        }

        $this->is_syncing = true;
        try {
            $offers = $this->get_active_offers();
            if (empty($offers)) {
                $this->is_syncing = false;
                return;
            }

            $subtotals = $this->compute_brand_subtotals($offers);

            
            foreach (WC()->cart->get_cart() as $item_key => $item) {
                if (empty($item['_aieo_dmm_gift_offer_id'])) {
                    continue;
                }
                $offer_id = (int) $item['_aieo_dmm_gift_offer_id'];
                if (!isset($subtotals[$offer_id]) || $subtotals[$offer_id]['qualified'] === false) {
                    WC()->cart->remove_cart_item($item_key);
                }
            }

            
            
            
            foreach ($offers as $offer) {
                $offer_id = (int) $offer['id'];
                if (empty($subtotals[$offer_id]) || empty($subtotals[$offer_id]['qualified'])) {
                    continue;
                }
                $gift_ids = $offer['gift_product_ids'];
                if (empty($gift_ids)) {
                    continue;
                }
                $picked     = $this->get_picked_gift($offer_id);
                $picked_vid = $this->get_picked_variation($offer_id);
                $valid_gifts = $this->filter_addable_gifts($gift_ids);
                if (empty($valid_gifts)) {
                    continue; 
                }
                if ($picked > 0 && !in_array($picked, $valid_gifts, true)) {
                    $picked = 0;
                    $picked_vid = 0;
                }
                $target = $picked > 0 ? $picked : (int) $valid_gifts[0];
                $target_vid = ($target === $picked) ? $picked_vid : 0;

                
                
                
                
                $target_p = wc_get_product($target);
                if ($target_p && $target_p->is_type('variable') && $target_vid <= 0) {
                    
                    
                    $existing_key = $this->find_gift_cart_key($offer_id);
                    if ($existing_key) { WC()->cart->remove_cart_item($existing_key); }
                    continue;
                }

                
                $existing_key = $this->find_gift_cart_key($offer_id);
                if ($existing_key) {
                    $existing = WC()->cart->get_cart_item($existing_key);
                    $existing_pid = isset($existing['product_id'])   ? (int) $existing['product_id']   : 0;
                    $existing_vid = isset($existing['variation_id']) ? (int) $existing['variation_id'] : 0;
                    if ($existing_pid === $target && $existing_vid === $target_vid) { continue; }
                    WC()->cart->remove_cart_item($existing_key);
                }
                
                
                
                
                $variation_attrs = array();
                if ($target_vid > 0) {
                    $variation = wc_get_product($target_vid);
                    if ($variation && $variation->is_type('variation')) {
                        $variation_attrs = $variation->get_variation_attributes();
                    }
                }
                
                
                
                
                self::$is_internal_add = true;
                try {
                    WC()->cart->add_to_cart($target, 1, $target_vid, $variation_attrs, array(
                        '_aieo_dmm_gift_offer_id' => $offer_id,
                    ));
                } finally {
                    self::$is_internal_add = false;
                }
            }
        } finally {
            $this->is_syncing = false;
        }
    }

    
    private function compute_brand_subtotals(array $offers) {
        $out = array();
        $cart_items = WC()->cart->get_cart();
        $taxonomy = class_exists('AIEO_DMM_Brand_Discounts') ? AIEO_DMM_Brand_Discounts::get_brand_taxonomy() : 'product_brand';
        if (!$taxonomy) { $taxonomy = 'product_brand'; }

        
        
        
        $cart_total = 0.0;
        foreach ($cart_items as $_item) {
            if (!empty($_item['_aieo_dmm_gift_offer_id'])) { continue; }
            if (!isset($_item['data']) || !is_object($_item['data'])) { continue; }
            $cart_total += (float) $_item['data']->get_price() * (int) ($_item['quantity'] ?? 0);
        }

        
        
        
        $dec_list = static function ($v) {
            if (is_array($v)) { return array_values(array_filter(array_map('intval', $v))); }
            if (is_string($v) && $v !== '') {
                $d = json_decode($v, true);
                return is_array($d) ? array_values(array_filter(array_map('intval', $d))) : array();
            }
            return array();
        };

        foreach ($offers as $offer) {
            $offer_id    = (int) $offer['id'];
            $brand_ids   = is_array($offer['brand_term_ids'])   ? array_map('intval', $offer['brand_term_ids'])   : array();
            $category_ids = is_array($offer['category_term_ids']) ? array_map('intval', $offer['category_term_ids']) : array();
            $need_ids     = is_array($offer['need_term_ids'] ?? null) ? array_map('intval', $offer['need_term_ids']) : array();
            $operator     = (isset($offer['rule_operator']) && strtoupper($offer['rule_operator']) === 'OR') ? 'OR' : 'AND';

            
            $excl_brand = $dec_list($offer['excluded_brand_ids']    ?? null);
            $excl_cat   = $dec_list($offer['excluded_category_ids'] ?? null);
            $excl_need  = $dec_list($offer['excluded_need_ids']     ?? null);
            $excl_prod  = $dec_list($offer['excluded_product_ids']  ?? null);
            $req_prod   = $dec_list($offer['product_ids']           ?? null);

            
            
            
            
            $no_targeting = empty($brand_ids) && empty($category_ids) && empty($need_ids);

            $subtotal = 0.0;
            foreach ($cart_items as $item) {
                if (!empty($item['_aieo_dmm_gift_offer_id'])) {
                    continue; 
                }
                $pid = !empty($item['variation_id']) ? (int) $item['variation_id'] : (int) $item['product_id'];

                $matches = $no_targeting;
                if (!$no_targeting) {
                    $brand_terms = wp_get_object_terms($pid, $taxonomy, array('fields' => 'ids'));
                    if (is_wp_error($brand_terms)) { $brand_terms = array(); }
                    $cat_terms = wp_get_object_terms($pid, 'product_cat', array('fields' => 'ids'));
                    if (is_wp_error($cat_terms)) { $cat_terms = array(); }
                    $need_terms = array();
                    if (!empty($need_ids) && taxonomy_exists('pa_need')) {
                        $need_terms = wp_get_object_terms($pid, 'pa_need', array('fields' => 'ids'));
                        if (is_wp_error($need_terms)) { $need_terms = array(); }
                    }

                    
                    
                    
                    
                    
                    if ($operator === 'OR') {
                        $matches = (!empty($brand_ids)    && !empty($brand_terms) && array_intersect($brand_terms, $brand_ids))
                                || (!empty($category_ids) && !empty($cat_terms)   && array_intersect($cat_terms,   $category_ids))
                                || (!empty($need_ids)     && !empty($need_terms)  && array_intersect($need_terms,  $need_ids));
                    } else {
                        $brand_match = empty($brand_ids)    || (!empty($brand_terms) && array_intersect($brand_terms, $brand_ids));
                        $cat_match   = empty($category_ids) || (!empty($cat_terms)   && array_intersect($cat_terms,   $category_ids));
                        $need_match  = empty($need_ids)     || (!empty($need_terms)  && array_intersect($need_terms,  $need_ids));
                        $matches     = $brand_match && $cat_match && $need_match;
                    }
                }

                if ($matches) {
                    
                    
                    
                    
                    
                    
                    $unit_price = (isset($item['data']) && is_object($item['data']))
                        ? (float) $item['data']->get_price()
                        : 0.0;
                    $qty        = (int) ($item['quantity'] ?? 0);
                    $subtotal  += $unit_price * $qty;
                }
            }

            
            
            
            
            
            
            $vetoed  = false;
            $req_met = empty($req_prod);
            if (!empty($excl_brand) || !empty($excl_cat) || !empty($excl_need) || !empty($excl_prod) || !empty($req_prod)) {
                foreach ($cart_items as $xitem) {
                    if (!empty($xitem['_aieo_dmm_gift_offer_id'])) { continue; }
                    $xpid    = !empty($xitem['variation_id']) ? (int) $xitem['variation_id'] : (int) ($xitem['product_id'] ?? 0);
                    $xparent = (int) ($xitem['product_id'] ?? $xpid);
                    $xself   = array($xpid, $xparent);
                    if (!empty($req_prod) && array_intersect($xself, $req_prod)) { $req_met = true; }
                    if (!empty($excl_prod) && array_intersect($xself, $excl_prod)) { $vetoed = true; break; }
                    if (!empty($excl_brand)) {
                        $xb = wp_get_object_terms($xparent, $taxonomy, array('fields' => 'ids'));
                        if (!is_wp_error($xb) && array_intersect(array_map('intval', (array) $xb), $excl_brand)) { $vetoed = true; break; }
                    }
                    if (!empty($excl_cat)) {
                        $xc = wp_get_object_terms($xparent, 'product_cat', array('fields' => 'ids'));
                        if (!is_wp_error($xc) && array_intersect(array_map('intval', (array) $xc), $excl_cat)) { $vetoed = true; break; }
                    }
                    if (!empty($excl_need) && taxonomy_exists('pa_need')) {
                        $xn = wp_get_object_terms($xparent, 'pa_need', array('fields' => 'ids'));
                        if (!is_wp_error($xn) && array_intersect(array_map('intval', (array) $xn), $excl_need)) { $vetoed = true; break; }
                    }
                }
            }

            
            
            
            
            
            
            
            
            
            $threshold = (float) $offer['min_subtotal'];
            $has_match = ($subtotal > 0);
            if ($operator === 'OR') {
                $price_or = ($threshold > 0 && $cart_total >= $threshold);
                
                
                
                $qualified = $has_match || $price_or;
                if (!$has_match && !$price_or) {
                    $qualified = false;
                }
            } else {
                
                
                
                
                
                
                
                
                if ($no_targeting) {
                    $qualified = ($subtotal >= $threshold) && ($subtotal > 0);
                } else {
                    $qualified = $has_match && ($subtotal >= $threshold);
                }
            }

            
            if ($qualified && ($vetoed || !$req_met)) {
                $qualified = false;
            }

            $out[$offer_id] = array(
                'subtotal'   => $subtotal,
                'cart_total' => $cart_total,
                'qualified'  => $qualified,
            );
        }
        return $out;
    }

    private function cart_has_gift_for_offer($offer_id) {
        foreach (WC()->cart->get_cart() as $item) {
            if (!empty($item['_aieo_dmm_gift_offer_id']) && (int) $item['_aieo_dmm_gift_offer_id'] === (int) $offer_id) {
                return true;
            }
        }
        return false;
    }

    
    private function gift_text($offer, $key, $default_template, $tokens, $plain_remaining = false) {
        $template = isset($offer[$key]) ? trim((string) $offer[$key]) : '';
        if ($template === '') { $template = $default_template; }

        $remaining = isset($tokens['remaining']) ? (float) $tokens['remaining'] : 0.0;
        $brand     = isset($tokens['brand']) ? (string) $tokens['brand'] : '';
        $price_str = wc_price($remaining);
        if ($plain_remaining) { $price_str = wp_strip_all_tags($price_str); }

        return strtr($template, array(
            '{remaining}' => $price_str,
            '{brand}'     => $brand,
        ));
    }

    public function set_gift_prices($cart) {
        if (!is_a($cart, 'WC_Cart')) {
            return;
        }
        foreach ($cart->get_cart() as $item) {
            if (!empty($item['_aieo_dmm_gift_offer_id']) && isset($item['data']) && is_object($item['data'])) {
                $item['data']->set_price(0);
            }
        }
    }

    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    

    
    private function is_sample_product($product_or_id) {
        if (is_numeric($product_or_id)) {
            $pid = (int) $product_or_id;
        } elseif (is_object($product_or_id) && method_exists($product_or_id, 'get_id')) {
            $pid = (int) $product_or_id->get_id();
        } else {
            return false;
        }
        if ($pid <= 0) { return false; }
        return get_post_meta($pid, '_aieo_gift_type', true) === 'sample';
    }

    
    public function filter_sample_unpurchasable($purchasable, $product) {
        if (!$purchasable) { return $purchasable; }      
        if (self::$is_internal_add) { return $purchasable; }
        if ($this->is_sample_product($product)) { return false; }
        return $purchasable;
    }

    
    public function exclude_samples_from_archive($q) {
        if (!($q instanceof WP_Query)) { return; }

        
        
        
        
        
        
        
        
        
        
        
        
        $post_in = $q->get('post__in');
        if (!empty($post_in)) { return; }

        
        
        
        
        
        if (function_exists('doing_action') && doing_action('dynamic_sidebar')) {
            return;
        }

        
        
        
        
        
        
        
        $sample_ids = $this->sample_product_ids();
        if (!empty($sample_ids)) {
            $not_in = array_map('intval', (array) $q->get('post__not_in'));
            $q->set('post__not_in', array_values(array_unique(array_merge($not_in, $sample_ids))));
        }
    }

    
    public function sample_product_ids() {
        $ids = get_transient('aieo_bg_sample_ids');
        if (is_array($ids)) { return $ids; }
        global $wpdb;
        $ids = $wpdb->get_col($wpdb->prepare(
            "SELECT post_id FROM {$wpdb->postmeta} WHERE meta_key = %s AND meta_value = %s",
            '_aieo_gift_type',
            'sample'
        ));
        $ids = array_map('intval', (array) $ids);
        set_transient('aieo_bg_sample_ids', $ids, 6 * HOUR_IN_SECONDS);
        return $ids;
    }

    
    public function flush_sample_ids_cache() {
        delete_transient('aieo_bg_sample_ids');
    }

    
    public function exclude_samples_from_search($q) {
        if (is_admin() || !($q instanceof WP_Query) || !$q->is_main_query() || !$q->is_search()) {
            return;
        }
        $this->exclude_samples_from_archive($q);
    }

    
    public function render_gift_type_field() {
        global $post;
        $current = $post ? (string) get_post_meta($post->ID, '_aieo_gift_type', true) : '';
        woocommerce_wp_select(array(
            'id'          => '_aieo_gift_type',
            'label'       => __('Free gift type', 'ai-eshop-optimizer'),
            'description' => __('"Sample" hides this product from archives + search and prevents direct purchase. The Free Gifts module can still add it to the cart automatically when offer conditions are met.', 'ai-eshop-optimizer'),
            'desc_tip'    => true,
            'value'       => $current,
            'options'     => array(
                ''       => __('Regular product', 'ai-eshop-optimizer'),
                'sample' => __('Sample (gift only — not purchasable)', 'ai-eshop-optimizer'),
            ),
        ));
    }

    
    public function save_gift_type_field($post_id) {
        $val = isset($_POST['_aieo_gift_type']) ? sanitize_key(wp_unslash($_POST['_aieo_gift_type'])) : '';
        if ($val === 'sample') {
            update_post_meta($post_id, '_aieo_gift_type', 'sample');
        } else {
            delete_post_meta($post_id, '_aieo_gift_type');
        }
    }

    public function lock_gift_quantity($qty_html, $item_key, $item) {
        if (!empty($item['_aieo_dmm_gift_offer_id'])) {
            return '1';
        }
        return $qty_html;
    }

    public function add_gift_badge($name, $item, $item_key) {
        if (!empty($item['_aieo_dmm_gift_offer_id'])) {
            $badge = '<span class="aieo-dmm-gift-badge">' . esc_html__('Free Gift', 'ai-eshop-optimizer') . '</span> ';
            return $badge . $name;
        }
        return $name;
    }

    public function hide_gift_remove_link($link_html, $item_key) {
        if (!function_exists('WC') || !WC()->cart) {
            return $link_html;
        }
        $item = WC()->cart->get_cart_item($item_key);
        if (!empty($item['_aieo_dmm_gift_offer_id'])) {
            return '';
        }
        return $link_html;
    }

    
    
    

    private function pick_session_key($offer_id) {
        return 'aieo_dmm_gift_pick_' . (int) $offer_id;
    }

    
    public function get_picked_gift($offer_id) {
        $entry = $this->get_picked_entry($offer_id);
        return (int) $entry['product_id'];
    }

    public function get_picked_variation($offer_id) {
        $entry = $this->get_picked_entry($offer_id);
        return (int) $entry['variation_id'];
    }

    
    private function get_picked_entry($offer_id) {
        $default = array('product_id' => 0, 'variation_id' => 0);
        if (!function_exists('WC') || !WC()->session) { return $default; }
        $v = WC()->session->get($this->pick_session_key($offer_id), 0);
        if (is_array($v)) {
            return array(
                'product_id'   => isset($v['product_id'])   ? (int) $v['product_id']   : 0,
                'variation_id' => isset($v['variation_id']) ? (int) $v['variation_id'] : 0,
            );
        }
        
        return array('product_id' => (int) $v, 'variation_id' => 0);
    }

    public function set_picked_gift($offer_id, $product_id, $variation_id = 0) {
        if (!function_exists('WC') || !WC()->session) { return; }
        WC()->session->set($this->pick_session_key($offer_id), array(
            'product_id'   => (int) $product_id,
            'variation_id' => (int) $variation_id,
        ));
    }

    
    public function get_offers_for_product($product_id) {
        $product_id = (int) $product_id;
        if ($product_id <= 0) { return array(); }
        $offers = $this->get_active_offers();
        if (empty($offers)) { return array(); }

        
        
        
        
        
        
        return AIEO_DMM_Offer_Matcher::for_product($product_id, $offers);
    }

    
    public static function add_eligibility_row($rows, $product_id, $audience_key) {
        if (!is_array($rows)) { $rows = array(); }
        $product_id = (int) $product_id;
        if ($product_id === 0) { return $rows; }
        if (!class_exists('AIEO_Effective_Eligibility')) { return $rows; }
        $r = self::is_eligible_for($product_id, (string) $audience_key);
        if (!empty($r['eligible'])) {
            $rows[AIEO_Effective_Eligibility::SURFACE_BRAND_GIFT] = $r;
        }
        return $rows;
    }

    
    public static function is_eligible_for($product_id, $audience_key = 'guest') {
        $product_id = (int) $product_id;
        if ($product_id <= 0) { return array('eligible' => false); }
        if (class_exists('AIEO_DMM_Settings')) {
            if (!AIEO_DMM_Settings::is_module_enabled('brand_gifts')) { return array('eligible' => false); }
            if (AIEO_DMM_Settings::get('recipe.brand_gift', 'over_and_above') === 'off') { return array('eligible' => false); }
        }
        $instance = self::instance();
        if (!$instance) { return array('eligible' => false); }
        $matches = $instance->get_offers_for_product($product_id);
        if (empty($matches) || !is_array($matches)) { return array('eligible' => false); }
        $offer = reset($matches);
        if (!is_array($offer)) { return array('eligible' => false); }
        return array(
            'eligible' => true,
            'offer_id' => isset($offer['id']) ? (int) $offer['id'] : null,
            'payload'  => array(
                'label'        => isset($offer['label']) ? (string) $offer['label'] : '',
                'min_subtotal' => isset($offer['min_subtotal']) ? (float) $offer['min_subtotal'] : null,
            ),
        );
    }

    
    private function filter_addable_gifts(array $gift_ids) {
        $out = array();
        foreach ($gift_ids as $pid) {
            $pid = (int) $pid;
            if ($pid <= 0) { continue; }
            $p = wc_get_product($pid);
            if (!$p || !$p->exists() || !$p->is_in_stock()) { continue; }
            if (in_array($p->get_type(), array('grouped', 'external'), true)) { continue; }
            $out[] = $pid;
        }
        return $out;
    }

    private function find_gift_cart_key($offer_id) {
        if (!function_exists('WC') || !WC()->cart) { return ''; }
        foreach (WC()->cart->get_cart() as $key => $item) {
            if (!empty($item['_aieo_dmm_gift_offer_id']) && (int) $item['_aieo_dmm_gift_offer_id'] === (int) $offer_id) {
                return (string) $key;
            }
        }
        return '';
    }

    
    public function ajax_pick_gift() {
        check_ajax_referer('aieo_side_cart', 'nonce');
        $offer_id     = isset($_POST['offer_id'])     ? absint(wp_unslash($_POST['offer_id']))     : 0;
        $product_id   = isset($_POST['product_id'])   ? absint(wp_unslash($_POST['product_id']))   : 0;
        $variation_id = isset($_POST['variation_id']) ? absint(wp_unslash($_POST['variation_id'])) : 0;
        if ($offer_id <= 0 || $product_id <= 0) {
            wp_send_json_error(array('message' => __('Bad pick.', 'ai-eshop-optimizer')));
        }
        $offers = $this->get_active_offers();
        $valid_pids = array();
        foreach ($offers as $o) {
            if ((int) $o['id'] === $offer_id) {
                $valid_pids = array_map('intval', $o['gift_product_ids']);
                break;
            }
        }
        if (!in_array($product_id, $valid_pids, true)) {
            wp_send_json_error(array('message' => __('Product not in this offer.', 'ai-eshop-optimizer')));
        }
        
        
        $product = wc_get_product($product_id);
        if ($product && $product->is_type('variable')) {
            if ($variation_id <= 0) {
                
                
                $this->set_picked_gift($offer_id, $product_id, 0);
                wp_send_json_success(array('picked' => $product_id, 'needs_variation' => true));
            }
            $variation = wc_get_product($variation_id);
            if (!$variation || !$variation->is_type('variation') || (int) $variation->get_parent_id() !== $product_id) {
                wp_send_json_error(array('message' => __('Invalid variation.', 'ai-eshop-optimizer')));
            }
        } else {
            $variation_id = 0; 
        }
        $this->set_picked_gift($offer_id, $product_id, $variation_id);
        $this->sync_gifts();
        wp_send_json_success(array('picked' => $product_id, 'variation_id' => $variation_id));
    }

    
    public function ajax_get_variations() {
        check_ajax_referer('aieo_side_cart', 'nonce');
        $product_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
        wp_send_json_success(array('variations' => $this->get_variations_for_product($product_id)));
    }

    
    public function get_variations_for_product($product_id) {
        $product = (int) $product_id > 0 ? wc_get_product((int) $product_id) : null;
        if (!$product || !$product->is_type('variable')) { return array(); }
        $out = array();
        foreach ($product->get_available_variations() as $v) {
            if (empty($v['is_purchasable']) || empty($v['is_in_stock'])) { continue; }
            $label_parts = array();
            foreach ((array) $v['attributes'] as $attr_key => $attr_val) {
                if ($attr_val === '' || $attr_val === null) { continue; }
                
                
                
                
                
                
                
                
                
                $taxonomy = preg_replace('/^attribute_/', '', (string) $attr_key);
                $is_global = (strpos($taxonomy, 'pa_') === 0);
                $value_display = (string) $attr_val;
                if ($is_global && taxonomy_exists($taxonomy)) {
                    $term = get_term_by('slug', $attr_val, $taxonomy);
                    if ($term && !is_wp_error($term)) {
                        $value_display = (string) $term->name;
                    }
                }
                
                
                
                $key_display = function_exists('wc_attribute_label')
                    ? wc_attribute_label($taxonomy)
                    : ucfirst(str_replace(array('-', '_'), ' ', $taxonomy));
                $label_parts[] = $key_display . ': ' . $value_display;
            }
            $out[] = array(
                'variation_id' => (int) $v['variation_id'],
                'label'        => implode(' / ', $label_parts) ?: ('#' . (int) $v['variation_id']),
            );
        }
        return $out;
    }

    
    
    

    
    public function render_side_cart_section() {
        $offers = $this->get_active_offers();
        if (empty($offers)) { return ''; }

        $subtotals = $this->compute_brand_subtotals($offers);

        ob_start();
        foreach ($offers as $offer) {
            
            
            if (isset($offer['show_banner']) && (int) $offer['show_banner'] === 0) {
                continue;
            }
            $offer_id  = (int) $offer['id'];
            $info      = isset($subtotals[$offer_id]) ? $subtotals[$offer_id] : array('subtotal' => 0, 'qualified' => false);
            $qualified = !empty($info['qualified']);
            $current   = (float) $info['subtotal'];
            $threshold = (float) ($offer['min_subtotal'] ?? 0);
            $remaining = max(0, $threshold - $current);
            $percent   = $threshold > 0 ? min(100, ($current / $threshold) * 100) : 0;

            $brand_names = $this->resolve_brand_names_html((array) ($offer['brand_term_ids'] ?? array()));

            $picked       = $this->get_picked_gift($offer_id);
            $picked_pid   = $picked > 0 ? $picked : (int) (!empty($offer['gift_product_ids']) ? $offer['gift_product_ids'][0] : 0);
            $picked_name  = '';
            if ($picked_pid > 0) {
                $picked_p = wc_get_product($picked_pid);
                if ($picked_p) { $picked_name = $picked_p->get_name(); }
            }

            $status = array(
                'remaining' => $remaining,
                'threshold' => $threshold,
                'current'   => $current,
                'percent'   => $percent,
                'qualified' => $qualified,
            );
            $text = (string) ($qualified ? ($offer['after_text'] ?? '') : ($offer['before_text'] ?? ''));
            $text = $this->parse_placeholders($text, $status, $brand_names, $picked_name);

            $img_id  = $qualified ? (int) ($offer['after_image_id'] ?? 0) : (int) ($offer['before_image_id'] ?? 0);
            $image_url = '';
            if ($img_id > 0) {
                $image_url = (string) wp_get_attachment_image_url($img_id, 'thumbnail');
            }
            $class = $qualified ? 'om-bg-qualified' : '';
            $addable = $this->filter_addable_gifts((array) ($offer['gift_product_ids'] ?? array()));
            $current_pick = $picked_pid;
            if ($current_pick > 0 && !in_array($current_pick, $addable, true)) {
                $current_pick = !empty($addable) ? (int) $addable[0] : 0;
            }

            
            
            
            $style_parts = array();
            $bar_bg = $qualified ? ($offer['bar_bg_after'] ?? '') : ($offer['bar_bg_before'] ?? '');
            $bar_fg = $qualified ? ($offer['bar_fg_after'] ?? '') : ($offer['bar_fg_before'] ?? '');
            if ($bar_bg) { $style_parts[] = 'background:' . $bar_bg; }
            if ($bar_fg) { $style_parts[] = '--om-bg-bar-fg:' . $bar_fg; }
            $style_attr = $style_parts ? ' style="' . esc_attr(implode(';', $style_parts)) . '"' : '';
            ?>
            <div class="om-bg-wrap <?php echo esc_attr($class); ?>" data-om-bg-offer="<?php echo $offer_id; ?>"<?php echo $style_attr; ?>>
                <?php if ($image_url): ?>
                    <div class="om-bg-image">
                        <img src="<?php echo esc_url($image_url); ?>" alt="">
                    </div>
                <?php endif; ?>
                <div class="om-bg-info">
                    <?php if ($text !== ''): ?>
                        <div class="om-bg-msg"><?php echo wp_kses_post($text); ?></div>
                    <?php endif; ?>
                    <?php if ($threshold > 0): ?>
                        <div class="om-bg-bar-wrap">
                            <div class="om-bg-bar-bg">
                                <div class="om-bg-bar-fg" style="width:<?php echo esc_attr(round($percent, 1)); ?>%;<?php echo $bar_fg ? 'background:' . esc_attr($bar_fg) . ';' : ''; ?>"></div>
                            </div>
                        </div>
                    <?php endif; ?>

                    <?php
                    
                    
                    
                    
                    
                    
                    
                    if ($qualified && count($addable) > 1):
                        ?>
                        <div class="om-bg-gift-choice aieo-sc-gift-choice">
                            <?php
                            $current_label = '';
                            if ($current_pick > 0) {
                                $cp = wc_get_product($current_pick);
                                if ($cp) { $current_label = $cp->get_name(); }
                            }
                            ?>
                            <label class="om-bg-gift-choice-label">
                                <?php
                                if ($current_label !== '') {
                                    echo wp_kses_post(sprintf(
                                        
                                        __('Your gift: %s', 'ai-eshop-optimizer'),
                                        '<strong>' . esc_html($current_label) . '</strong>'
                                    ));
                                } else {
                                    esc_html_e('Pick your free gift', 'ai-eshop-optimizer');
                                }
                                ?>
                            </label>
                            <select class="om-bg-gift-select aieo-sc-gift-select"
                                    data-offer-id="<?php echo esc_attr((string) $offer_id); ?>">
                                <option value="0" disabled selected>
                                    <?php esc_html_e('— Choose a different gift —', 'ai-eshop-optimizer'); ?>
                                </option>
                                <?php
                                foreach ($addable as $gpid):
                                    $gp = wc_get_product($gpid);
                                    if (!$gp) { continue; }
                                    if ((int) $gpid === (int) $current_pick) { continue; }
                                    ?>
                                    <option value="<?php echo esc_attr((string) $gpid); ?>"
                                            data-product-type="<?php echo esc_attr($gp->get_type()); ?>">
                                        <?php echo esc_html($gp->get_name()); ?>
                                    </option>
                                <?php endforeach; ?>
                            </select>
                            <div class="om-bg-gift-variation aieo-sc-gift-variation"
                                 data-offer-id="<?php echo esc_attr((string) $offer_id); ?>"></div>
                        </div>
                    <?php endif; ?>
                </div>
            </div>
            <?php
        }
        return (string) ob_get_clean();
    }

    
    public function render_archive_badge() {
        if (class_exists('AIEO_DMM_Badge_Renderer') && AIEO_DMM_Badge_Renderer::is_enabled()) { return; }
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        $matched = $this->get_offers_for_product($product->get_id());
        if (empty($matched)) { return; }
        $label = apply_filters('aieo_dmm_brand_gifts_archive_badge_label', __('+ Free gift', 'ai-eshop-optimizer'));
        echo '<span class="aieo-bg-archive-badge" aria-label="' . esc_attr__('Eligible for a free gift', 'ai-eshop-optimizer') . '">'
            . '<span class="aieo-bg-archive-badge-icon" aria-hidden="true">🎁</span> '
            . '<span class="aieo-bg-archive-badge-text">' . esc_html($label) . '</span>'
            . '</span>';
    }

    
    private static $archive_banner_rendered = false;

    
    public function render_archive_banner() {
        if (self::$archive_banner_rendered) { return; }
        $banner = $this->build_archive_banner_html();
        if ($banner === '') { return; }
        self::$archive_banner_rendered = true;
        echo $banner; 
    }

    
    public function inject_archive_banner_into_block($block_content, $block) {
        if (self::$archive_banner_rendered) { return $block_content; }
        $banner = $this->build_archive_banner_html();
        if ($banner === '') { return $block_content; }
        self::$archive_banner_rendered = true;
        return $banner . $block_content;
    }

    
    private function build_archive_banner_html() {
        
        
        
        $term = null;
        $tax  = '';
        if (function_exists('is_tax') && is_tax(array('pa_need'))) {
            $term = get_queried_object();
            $tax  = 'pa_need';
        } elseif (function_exists('is_product_category') && is_product_category()) {
            $term = get_queried_object();
            $tax  = 'product_cat';
        } elseif (function_exists('is_tax')) {
            
            
            
            $brand_tax = class_exists('AIEO_DMM_Brand_Discounts') ? AIEO_DMM_Brand_Discounts::get_brand_taxonomy() : 'product_brand';
            if ($brand_tax && is_tax($brand_tax)) {
                $term = get_queried_object();
                $tax  = $brand_tax;
            }
        }
        if (!$term || is_wp_error($term) || !isset($term->term_id) || $tax === '') {
            return '';
        }

        $offers  = $this->get_active_offers();
        if (empty($offers)) { return ''; }
        $matched = AIEO_DMM_Offer_Matcher::for_term($tax, (int) $term->term_id, $offers);
        if (empty($matched)) { return ''; }

        
        
        
        
        
        $offer       = $matched[0];
        $offer_id    = (int) ($offer['id'] ?? 0);
        $threshold   = (float) ($offer['min_subtotal'] ?? 0);
        $brand_html  = $this->resolve_brand_names_html((array) ($offer['brand_term_ids'] ?? array()));

        
        
        
        
        $tokens = array('remaining' => $threshold, 'brand' => $brand_html);
        $headline = $this->gift_text($offer, 'headline_pending',
            
            __('🎁 Free gift waiting — spend {remaining} more on {brand}', 'ai-eshop-optimizer'),
            $tokens);

        
        $addable = $this->filter_addable_gifts((array) ($offer['gift_product_ids'] ?? array()));
        $thumbs_html = '';
        $shown = 0;
        foreach ($addable as $gpid) {
            if ($shown >= 3) { break; }
            $thumb = get_the_post_thumbnail_url($gpid, 'thumbnail');
            if (!$thumb) { continue; }
            $thumbs_html .= '<span class="aieo-bg-archive-banner-thumb"><img src="' . esc_url($thumb) . '" alt=""></span>';
            $shown++;
        }
        $extra = max(0, count($addable) - $shown);
        if ($extra > 0) {
            $thumbs_html .= '<span class="aieo-bg-archive-banner-more">+' . esc_html(number_format_i18n($extra)) . '</span>';
        }

        
        
        $bg = (string) ($offer['bar_bg_before'] ?? '');
        $style = $bg ? ' style="background:' . esc_attr($bg) . ';"' : '';

        $html  = '<div class="aieo-bg-archive-banner" data-offer-id="' . esc_attr((string) $offer_id) . '"' . $style . '>';
        $html .=   '<div class="aieo-bg-archive-banner-headline">' . wp_kses_post($headline) . '</div>';
        if ($thumbs_html !== '') {
            $html .= '<div class="aieo-bg-archive-banner-thumbs">' . $thumbs_html . '</div>';
        }
        $html .= '</div>';
        return $html;
    }

    
    
    private static $single_product_rendered = false;

    
    public function inject_single_product_section_into_block($block_content, $block) {
        
        
        
        ob_start();
        $this->render_single_product_section();
        $section_html = (string) ob_get_clean();
        if ($section_html === '') { return $block_content; }
        return $block_content . $section_html;
    }

    
    public function is_active() {
        if (!class_exists('AIEO_DMM_Settings')) { return false; }
        if (!AIEO_DMM_Settings::is_module_enabled('brand_gifts')) { return false; }
        if (AIEO_DMM_Settings::get('recipe.brand_gift', 'over_and_above') === 'off') { return false; }
        $stored = get_option('aieo_dmm_brand_gifts_settings', array());
        if (!is_array($stored)) { $stored = array(); }
        if (isset($stored['enabled']) && empty($stored['enabled'])) {
            return false;
        }
        return true;
    }

    
    public function output() {
        $this->render_single_product_section();
    }

    public function render_single_product_section() {
        if (self::$single_product_rendered) { return; }
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        $matched = $this->get_offers_for_product($product->get_id());
        if (empty($matched)) { return; }

        
        
        
        self::$single_product_rendered = true;

        $subtotals = $this->compute_brand_subtotals($matched);

        echo '<div class="aieo-bg-product-section">';
        foreach ($matched as $offer) {
            $offer_id = (int) $offer['id'];
            $info     = isset($subtotals[$offer_id]) ? $subtotals[$offer_id] : array('subtotal' => 0, 'qualified' => false);
            $qualified = !empty($info['qualified']);

            
            $show_when_pending = isset($offer['show_when_pending']) ? (int) $offer['show_when_pending'] : 1;
            if (!$qualified && $show_when_pending === 0) {
                continue;
            }

            $current   = (float) $info['subtotal'];
            $threshold = (float) ($offer['min_subtotal'] ?? 0);
            $remaining = max(0, $threshold - $current);
            $addable   = $this->filter_addable_gifts((array) ($offer['gift_product_ids'] ?? array()));
            if (empty($addable)) { continue; }

            $picked = $this->get_picked_gift($offer_id);
            if ($picked > 0 && !in_array($picked, $addable, true)) { $picked = 0; }
            if ($picked === 0) { $picked = (int) $addable[0]; }

            $brand_names = $this->resolve_brand_names_html((array) ($offer['brand_term_ids'] ?? array()));
            $tokens   = array('remaining' => $remaining, 'brand' => $brand_names);
            $headline = $qualified
                ? $this->gift_text($offer, 'headline_qualified',
                    
                    __('🎁 You\'ve unlocked your free gift from {brand}', 'ai-eshop-optimizer'),
                    $tokens)
                : $this->gift_text($offer, 'headline_pending',
                    
                    __('🎁 Spend {remaining} more on {brand} and pick a free gift', 'ai-eshop-optimizer'),
                    $tokens);

            $bar_bg = $qualified ? ($offer['bar_bg_after'] ?? '') : ($offer['bar_bg_before'] ?? '');
            $style  = $bar_bg ? ' style="background:' . esc_attr($bar_bg) . ';"' : '';
            ?>
            <?php
            
            
            
            
            
            $pres_mode = isset($offer['presentation_mode']) ? (string) $offer['presentation_mode'] : 'auto';
            $use_dropdown = ($pres_mode === 'dropdown') || ($pres_mode !== 'list' && count($addable) > 1);
            ?>
            <div class="aieo-bg-product-card<?php echo $qualified ? ' is-qualified' : ' is-pending'; ?>"
                 data-offer-id="<?php echo esc_attr($offer_id); ?>"<?php echo $style; ?>>
                <div class="aieo-bg-product-card-headline"><?php echo wp_kses_post($headline); ?></div>
                <?php if ($use_dropdown) : ?>
                    <label class="aieo-bg-product-card-label">
                        <?php esc_html_e('Choose your gift:', 'ai-eshop-optimizer'); ?>
                    </label>
                    <select class="aieo-sc-gift-select aieo-bg-product-select"
                            data-offer-id="<?php echo esc_attr((string) $offer_id); ?>">
                        <option value="0" disabled selected>
                            <?php esc_html_e('— Pick a gift —', 'ai-eshop-optimizer'); ?>
                        </option>
                        <?php
                        foreach ($addable as $gpid):
                            $gp = wc_get_product($gpid);
                            if (!$gp) { continue; }
                            ?>
                            <option value="<?php echo esc_attr((string) $gpid); ?>"
                                    data-product-type="<?php echo esc_attr($gp->get_type()); ?>"
                                    <?php selected($gpid, $picked); ?>>
                                <?php echo esc_html($gp->get_name()); ?>
                            </option>
                        <?php endforeach; ?>
                    </select>
                    <div class="aieo-sc-gift-variation aieo-bg-product-variation"
                         data-offer-id="<?php echo esc_attr((string) $offer_id); ?>"></div>
                <?php else: ?>
                    <?php
                    $only = wc_get_product((int) $addable[0]);
                    if ($only) {
                        echo '<div class="aieo-bg-product-card-only">';
                        echo '<strong>' . esc_html__('Your gift:', 'ai-eshop-optimizer') . '</strong> '
                           . esc_html($only->get_name());
                        echo '</div>';
                    }
                    ?>
                <?php endif; ?>
            </div>
            <?php
        }
        echo '</div>';
    }

    
    public function render_cart_reward_cards() {
        $offers = $this->get_active_offers();
        if (empty($offers)) { return ''; }
        $subtotals = $this->compute_brand_subtotals($offers);

        ob_start();
        foreach ($offers as $offer) {
            
            
            if (isset($offer['show_rewards']) && (int) $offer['show_rewards'] === 0) {
                continue;
            }
            $offer_id  = (int) $offer['id'];
            $info      = isset($subtotals[$offer_id]) ? $subtotals[$offer_id] : array('subtotal' => 0, 'qualified' => false);
            $qualified = !empty($info['qualified']);

            
            
            
            
            $show_when_pending = isset($offer['show_when_pending']) ? (int) $offer['show_when_pending'] : 1;
            if (!$qualified && $show_when_pending === 0) {
                continue;
            }

            $current   = (float) $info['subtotal'];
            $threshold = (float) ($offer['min_subtotal'] ?? 0);
            $remaining = max(0, $threshold - $current);
            $addable   = $this->filter_addable_gifts((array) ($offer['gift_product_ids'] ?? array()));
            if (empty($addable)) { continue; }

            $picked     = $this->get_picked_gift($offer_id);
            $picked_vid = $this->get_picked_variation($offer_id);
            
            
            
            
            
            $brand_names_html  = $this->resolve_brand_names_html((array) ($offer['brand_term_ids'] ?? array()));
            $brand_names_plain = wp_strip_all_tags($brand_names_html);

            $headline_tokens = array('remaining' => $remaining, 'brand' => $brand_names_html);
            $pill_tokens     = array('remaining' => $remaining, 'brand' => $brand_names_plain);
            $section_label = $qualified
                ? $this->gift_text($offer, 'headline_qualified',
                    
                    __('🎁 Pick your free gift from {brand}', 'ai-eshop-optimizer'),
                    $headline_tokens)
                : $this->gift_text($offer, 'headline_pending',
                    
                    __('🎁 Free gift waiting — spend {remaining} more on {brand}', 'ai-eshop-optimizer'),
                    $headline_tokens);

            
            
            
            $pres_mode = isset($offer['presentation_mode']) ? (string) $offer['presentation_mode'] : 'auto';
            $use_dropdown = ($pres_mode === 'dropdown') && count($addable) > 1;
            if ($use_dropdown) {
                
                
                
                
                
                
                
                $picked_for_select = ($picked > 0 && in_array($picked, $addable, true))
                    ? (int) $picked
                    : (int) $addable[0];
                $picked_p = wc_get_product($picked_for_select);
                if (!$picked_p) {
                    
                    
                    
                    $picked_for_select = 0;
                }
                $picked_thumb = $picked_for_select > 0 ? get_the_post_thumbnail_url($picked_for_select, 'thumbnail') : '';
                $picked_name  = $picked_for_select > 0 ? $picked_p->get_name() : '';
                $picked_type  = $picked_for_select > 0 ? $picked_p->get_type() : 'simple';

                
                
                
                
                
                
                
                ?>
                <div class="aieo-bg-rewards aieo-bg-rewards--dropdown" data-offer-id="<?php echo esc_attr($offer_id); ?>">
                    <div class="aieo-bg-rewards-head"><?php echo wp_kses_post($section_label); ?></div>
                    <div class="om-bg-gift-choice aieo-sc-gift-choice">
                        <div class="aieo-bg-dropdown-card">
                            <div class="aieo-bg-dropdown-thumb">
                                <?php if ($picked_thumb) : ?>
                                    <img src="<?php echo esc_url($picked_thumb); ?>" alt="">
                                <?php endif; ?>
                            </div>
                            <div class="aieo-bg-dropdown-body">
                                <div class="aieo-bg-dropdown-name"><?php echo esc_html($picked_name); ?></div>
                                <select class="om-bg-gift-select aieo-sc-gift-select"
                                        data-offer-id="<?php echo esc_attr((string) $offer_id); ?>">
                                    <option value="0" <?php selected($picked_for_select, 0); ?>>
                                        <?php esc_html_e('— Pick a different gift —', 'ai-eshop-optimizer'); ?>
                                    </option>
                                    <?php foreach ($addable as $gpid) :
                                        $gp = wc_get_product($gpid);
                                        if (!$gp) { continue; }
                                        ?>
                                        <option value="<?php echo esc_attr((string) $gpid); ?>"
                                                data-product-type="<?php echo esc_attr($gp->get_type()); ?>"
                                                <?php selected($gpid, $picked_for_select); ?>>
                                            <?php echo esc_html($gp->get_name()); ?>
                                        </option>
                                    <?php endforeach; ?>
                                </select>
                            </div>
                        </div>
                        <?php
                        
                        
                        
                        
                        
                        
                        ?>
                        <div class="om-bg-gift-variation aieo-sc-gift-variation"
                             data-offer-id="<?php echo esc_attr((string) $offer_id); ?>">
                            <?php
                            if ($picked_for_select > 0) :
                                $picked_p = wc_get_product($picked_for_select);
                                if ($picked_p && $picked_p->is_type('variable')) :
                                    $variations = $this->get_variations_for_product($picked_for_select);
                                    if (!empty($variations)) :
                                        ?>
                                        <select class="aieo-sc-gift-variation-select"
                                                data-offer-id="<?php echo esc_attr((string) $offer_id); ?>"
                                                data-product-id="<?php echo esc_attr((string) $picked_for_select); ?>">
                                            <option value="0"<?php echo $picked_vid > 0 ? '' : ' selected'; ?>>
                                                <?php esc_html_e('— Pick variation —', 'ai-eshop-optimizer'); ?>
                                            </option>
                                            <?php foreach ($variations as $v) : ?>
                                                <option value="<?php echo (int) $v['variation_id']; ?>"
                                                        <?php selected((int) $v['variation_id'], $picked_vid); ?>>
                                                    <?php echo esc_html($v['label']); ?>
                                                </option>
                                            <?php endforeach; ?>
                                        </select>
                                    <?php endif;
                                endif;
                            endif;
                            ?>
                        </div>
                    </div>
                </div>
                <?php
                continue;       
            }
            ?>
            <div class="aieo-bg-rewards" data-offer-id="<?php echo esc_attr($offer_id); ?>">
                <div class="aieo-bg-rewards-head"><?php echo wp_kses_post($section_label); ?></div>
                <div class="aieo-bg-rewards-list">
                    <?php
                    foreach ($addable as $gpid) :
                        $gp = wc_get_product($gpid);
                        if (!$gp) { continue; }
                        $thumb     = get_the_post_thumbnail_url($gpid, 'thumbnail');
                        $name      = $gp->get_name();
                        $is_picked = ((int) $picked === (int) $gpid);
                        $type      = $gp->get_type();
                        $pill_text = '';
                        $pill_cls  = '';
                        if ($qualified && $is_picked) {
                            $pill_text = $this->gift_text($offer, 'pill_claimed',
                                __('Claimed', 'ai-eshop-optimizer'),
                                $pill_tokens, true);
                            $pill_cls  = 'is-claimed';
                        } elseif ($qualified) {
                            $pill_text = $this->gift_text($offer, 'pill_available',
                                __('Tap to swap', 'ai-eshop-optimizer'),
                                $pill_tokens, true);
                            $pill_cls  = 'is-available';
                        } else {
                            $pill_text = $this->gift_text($offer, 'pill_locked',
                                
                                __('Spend {remaining} more', 'ai-eshop-optimizer'),
                                $pill_tokens, true);
                            $pill_cls  = 'is-locked';
                        }
                        ?>
                        <button type="button"
                                class="aieo-bg-reward-card<?php echo $is_picked ? ' is-picked' : ''; ?> <?php echo esc_attr($pill_cls); ?>"
                                data-aieo-bg-claim
                                data-offer-id="<?php echo esc_attr($offer_id); ?>"
                                data-product-id="<?php echo esc_attr((int) $gpid); ?>"
                                data-product-type="<?php echo esc_attr($type); ?>"
                                <?php if (!$qualified) echo 'aria-disabled="true"'; ?>>
                            <span class="aieo-bg-reward-thumb">
                                <?php if ($thumb) : ?>
                                    <img src="<?php echo esc_url($thumb); ?>" alt="">
                                <?php endif; ?>
                            </span>
                            <span class="aieo-bg-reward-body">
                                <span class="aieo-bg-reward-name"><?php echo esc_html($name); ?></span>
                                <span class="aieo-bg-reward-pill"><?php echo esc_html($pill_text); ?></span>
                            </span>
                        </button>
                        <?php
                        
                        
                        
                        
                        
                        
                        if ($is_picked && $type === 'variable') :
                            $variations = $this->get_variations_for_product((int) $gpid);
                            if (!empty($variations)) :
                                ?>
                                <div class="aieo-sc-gift-variation aieo-bg-reward-variation"
                                     data-offer-id="<?php echo esc_attr($offer_id); ?>"
                                     data-product-id="<?php echo esc_attr((int) $gpid); ?>">
                                    <select class="aieo-bg-variation-select"
                                            data-offer-id="<?php echo esc_attr((string) $offer_id); ?>"
                                            data-product-id="<?php echo esc_attr((string) $gpid); ?>">
                                        <option value="0"<?php echo $picked_vid > 0 ? '' : ' selected'; ?>>
                                            <?php esc_html_e('— Pick variation —', 'ai-eshop-optimizer'); ?>
                                        </option>
                                        <?php foreach ($variations as $v) : ?>
                                            <option value="<?php echo (int) $v['variation_id']; ?>"
                                                    <?php selected((int) $v['variation_id'], $picked_vid); ?>>
                                                <?php echo esc_html($v['label']); ?>
                                            </option>
                                        <?php endforeach; ?>
                                    </select>
                                </div>
                            <?php endif;
                        endif;
                    endforeach;
                    ?>
                </div>
            </div>
            <?php
        }
        return (string) ob_get_clean();
    }

    
    private function parse_placeholders($text, array $status, $brand_names, $gift_name) {
        $text = wp_unslash((string) $text);
        $replacements = array(
            '{remaining}' => wc_price($status['remaining']),
            '{threshold}' => wc_price($status['threshold']),
            '{current}'   => wc_price($status['current']),
            '{brands}'    => $brand_names,
            '{gift}'      => esc_html($gift_name),
        );
        return str_replace(array_keys($replacements), array_values($replacements), $text);
    }

    
    private function resolve_brand_names_html(array $brand_ids) {
        $tax = class_exists('AIEO_DMM_Brand_Discounts') ? AIEO_DMM_Brand_Discounts::get_brand_taxonomy() : 'product_brand';
        if (!$tax) { $tax = 'product_brand'; }
        $links = array();
        foreach ($brand_ids as $bid) {
            $term = get_term((int) $bid, $tax);
            if (!$term || is_wp_error($term)) { continue; }
            $url = get_term_link($term, $tax);
            if (!is_wp_error($url)) {
                $links[] = '<a href="' . esc_url($url) . '">' . esc_html($term->name) . '</a>';
            } else {
                $links[] = esc_html($term->name);
            }
        }
        if (count($links) <= 1) { return implode('', $links); }
        $connector = apply_filters('aieo_dmm_brand_gifts_connector', 'ή');
        $last = array_pop($links);
        return implode(', ', $links) . ' ' . $connector . ' ' . $last;
    }
}
