<?php

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

class AIEO_DMM_Complementary extends AIEO_DMM_Module_Base {

    public function get_id()       { return 'complementary'; }
    public function get_label()    { return __('Complementary products', 'ai-eshop-optimizer'); }
    public function get_priority() { return 58; } 
    public function get_group()    { return 'product_management'; }

    
    public function default_offer_title() {
        return __('Complete your purchase with:', 'ai-eshop-optimizer');
    }

    public function default_button_text() {
        return __('Add selected to cart', 'ai-eshop-optimizer');
    }

    
    public function is_active() {
        
        if (class_exists('AIEO_DMM_Settings') && !AIEO_DMM_Settings::is_module_enabled('complementary')) {
            return false;
        }
        
        
        
        
        $stored = get_option('aieo_dmm_complementary_settings', array());
        if (!is_array($stored)) { $stored = array(); }
        if (isset($stored['enabled']) && empty($stored['enabled'])) {
            return false;
        }
        return true;
    }

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

        
        add_action('wp_ajax_aieo_dmm_complementary_save',     array($this, 'ajax_save'));
        add_action('wp_ajax_aieo_dmm_complementary_save_appearance', array($this, 'ajax_save_appearance'));
        add_action('wp_ajax_aieo_dmm_complementary_delete',   array($this, 'ajax_delete'));
        add_action('wp_ajax_aieo_dmm_complementary_import',   array($this, 'ajax_import_csv'));
        add_action('wp_ajax_aieo_dmm_complementary_export',   array($this, 'ajax_export_csv'));
        add_action('wp_ajax_aieo_dmm_complementary_migrate',  array($this, 'ajax_migrate_pods'));
        
        if (!has_action('wp_ajax_aieo_dmm_search_products')) {
            add_action('wp_ajax_aieo_dmm_search_products', array($this, 'ajax_search_products'));
        }

        
        add_action('wp_ajax_aieo_dmm_complementary_add',        array($this, 'ajax_bulk_add_to_cart'));
        add_action('wp_ajax_nopriv_aieo_dmm_complementary_add', array($this, 'ajax_bulk_add_to_cart'));

        
        
        
        
        
        
        
        
        $dash_on = class_exists('AIEO_DMM_Product_Display')
            && AIEO_DMM_Product_Display::module_is_enabled('aieo_dmm_complementary_settings');
        if (!$dash_on) {
            return;
        }

        add_action('wp_enqueue_scripts', array($this, 'enqueue_frontend_assets'));
        $this->register_placement_hook();
    }

    
    private function register_placement_hook() {
        
        
        
        
        
        
        
        
        
        
        
        
        $is_block_theme = function_exists('wp_is_block_theme') && wp_is_block_theme();
        $use_wc_hook    = (bool) apply_filters('aieo_dmm_complementary_fse_use_hook', ! $is_block_theme);

        if ($use_wc_hook) {
            
            
            $hook     = (string) apply_filters('aieo_dmm_complementary_hook', 'woocommerce_before_add_to_cart_button');
            $priority = (int) apply_filters('aieo_dmm_complementary_priority', 25);
            add_action($hook, array($this, 'render_for_current_product'), $priority);
        }

        
        
        
        
        
        
        
        
        
        $fallback_priority = (int) apply_filters('aieo_dmm_complementary_fallback_priority', 31);
        add_action('woocommerce_simple_add_to_cart',    array($this, 'render_fallback_for_current_product'), $fallback_priority);
        add_action('woocommerce_after_add_to_cart_form', array($this, 'render_fallback_for_current_product'), $fallback_priority);
    }

    
    private $rendered_for = array();

    
    
    

    public function render_subtab() {
        $this->render_template('complementary.php', array(
            'rows'                 => $this->fetch_all_with_labels(),
            'module'               => $this,
            'has_legacy_pods_data' => $this->detect_legacy_pods_data(),
        ));
    }

    public function enqueue_admin_assets() {
        
        
    }

    
    public function fetch_all_with_labels() {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_complementary';
        if (!aieo_dmm_table_exists($table)) {
            return array();
        }

        
        $rows = $wpdb->get_results("SELECT * FROM {$table} ORDER BY enabled DESC, id DESC", ARRAY_A);
        if (!is_array($rows)) { return array(); }

        $out = array();
        foreach ($rows as $row) {
            $out[] = $this->hydrate_row($row);
        }
        return $out;
    }

    
    private function hydrate_row(array $row) {
        $pids = json_decode($row['product_ids'] ?? '[]', true);
        if (!is_array($pids)) { $pids = array(); }
        $pids = array_values(array_filter(array_map('intval', $pids)));

        $row['product_ids']        = $pids;
        $row['product_names']      = array_map(array($this, 'resolve_product_name'), $pids);
        $row['source_product_id']  = (int) ($row['source_product_id'] ?? 0);
        $row['source_product_name'] = $this->resolve_product_name($row['source_product_id']);
        $row['enabled']            = !empty($row['enabled']) ? 1 : 0;
        $row['offer_title']        = (string) ($row['offer_title'] ?? '');
        $row['button_text']        = (string) ($row['button_text'] ?? '');
        $row['placement']          = (string) ($row['placement'] ?? 'before_add_to_cart');
        $row['checkboxes_state']   = (string) ($row['checkboxes_state'] ?? 'unchecked');
        return $row;
    }

    private function resolve_product_name($product_id) {
        $product_id = (int) $product_id;
        if ($product_id <= 0) { return ''; }
        $title = get_the_title($product_id);
        return ($title !== '' && $title !== null) ? (string) $title : ('#' . $product_id);
    }

    
    private function render_product_link($product_id, $name) {
        $product_id = (int) $product_id;
        if ($product_id <= 0) { return ''; }
        $label = ($name !== '') ? $name : ('#' . $product_id);
        $url   = get_permalink($product_id);
        if (!$url) {
            return esc_html($label);
        }
        return '<a href="' . esc_url($url) . '" target="_blank" rel="noopener">' . esc_html($label) . '</a>';
    }

    
    public function render_row($row) {
        if (empty($row) || !is_array($row)) { return ''; }
        $data_attr = esc_attr(wp_json_encode($row));

        $label  = esc_html((string) ($row['label'] ?? ''));
        $src    = $this->render_product_link(
            (int) $row['source_product_id'],
            (string) $row['source_product_name']
        );
        $en     = !empty($row['enabled']) ? '✔' : '—';

        
        $pids  = array_pad($row['product_ids'],   3, 0);
        $names = array_pad($row['product_names'], 3, '');
        $cells = '';
        for ($i = 0; $i < 3; $i++) {
            $link = $this->render_product_link((int) $pids[$i], (string) $names[$i]);
            $cells .= '<td>' . ($link !== '' ? $link : '<em class="description">—</em>') . '</td>';
        }

        return '<tr data-id="' . (int) $row['id'] . '" data-row="' . $data_attr . '">'
            . '<td>' . $label . '</td>'
            . '<td>' . ($src !== '' ? $src : '<em class="description">—</em>') . '</td>'
            . $cells
            . '<td>' . $en . '</td>'
            . '<td>'
            .   '<button type="button" class="button button-small aieo-dmm-edit-complementary">'
            .     esc_html__('Edit', 'ai-eshop-optimizer')
            .   '</button> '
            .   '<button type="button" class="button button-small aieo-dmm-delete-row" data-action="aieo_dmm_complementary_delete">'
            .     esc_html__('Delete', 'ai-eshop-optimizer')
            .   '</button>'
            . '</td>'
            . '</tr>';
    }

    
    
    

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

        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_complementary';
        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;

        $source_id = isset($_POST['source_product_id']) ? absint(wp_unslash($_POST['source_product_id'])) : 0;
        if ($source_id <= 0) {
            wp_send_json_error(array('message' => __('Pick a source product.', 'ai-eshop-optimizer')));
        }

        $product_ids = array();
        if (isset($_POST['product_ids']) && is_array($_POST['product_ids'])) {
            $product_ids = array_values(array_filter(array_map('absint', wp_unslash($_POST['product_ids']))));
        }
        $product_ids = array_slice(array_unique($product_ids), 0, 3); 
        if (empty($product_ids)) {
            wp_send_json_error(array('message' => __('Pick at least one complementary product.', 'ai-eshop-optimizer')));
        }
        if (in_array($source_id, $product_ids, true)) {
            wp_send_json_error(array('message' => __('A product can\'t complement itself — remove it from the complementary list.', 'ai-eshop-optimizer')));
        }

        
        if (!$is_update) {
            $existing = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$table} WHERE source_product_id = %d LIMIT 1",
                $source_id
            ));
            if ($existing > 0) {
                wp_send_json_error(array(
                    'message' => __('A complementary set already exists for this source product. Edit it instead.', 'ai-eshop-optimizer'),
                    'existing_id' => $existing,
                ));
            }
        } else {
            
            $existing = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$table} WHERE source_product_id = %d AND id <> %d LIMIT 1",
                $source_id, $id
            ));
            if ($existing > 0) {
                wp_send_json_error(array('message' => __('Another row already targets this source product.', 'ai-eshop-optimizer')));
            }
        }

        $placement_allowed = array('before_add_to_cart', 'after_add_to_cart', 'after_summary');
        $placement = isset($_POST['placement']) ? sanitize_key(wp_unslash($_POST['placement'])) : 'before_add_to_cart';
        if (!in_array($placement, $placement_allowed, true)) { $placement = 'before_add_to_cart'; }

        $checkboxes_state = (isset($_POST['checkboxes_state']) && sanitize_text_field(wp_unslash($_POST['checkboxes_state'])) === 'checked') ? 'checked' : 'unchecked';

        $data = array(
            'enabled'           => !empty($_POST['enabled']) ? 1 : 0,
            'label'             => isset($_POST['label']) ? sanitize_text_field(wp_unslash($_POST['label'])) : '',
            'source_product_id' => $source_id,
            'product_ids'       => wp_json_encode($product_ids),
            'offer_title'       => isset($_POST['offer_title']) ? sanitize_text_field(wp_unslash($_POST['offer_title'])) : '',
            'button_text'       => isset($_POST['button_text']) ? sanitize_text_field(wp_unslash($_POST['button_text'])) : '',
            'placement'         => $placement,
            'checkboxes_state'  => $checkboxes_state,
        );
        $formats = array('%d', '%s', '%d', '%s', '%s', '%s', '%s', '%s');

        if ($is_update) {
            $wpdb->update($table, $data, array('id' => $id), $formats, array('%d'));
        } else {
            $wpdb->insert($table, $data, $formats);
            $id = (int) $wpdb->insert_id;
        }

        AIEO_DMM_Cache::bump_version('complementary');

        $row = $this->hydrate_row(
            $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table} WHERE id = %d", $id), ARRAY_A) ?: array()
        );
        wp_send_json_success(array(
            'id'        => $id,
            'is_update' => $is_update,
            'row'       => $row,
            'row_html'  => $this->render_row($row),
            'message'   => __('Complementary set saved.', 'ai-eshop-optimizer'),
        ));
    }

    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_complementary', array('id' => $id), array('%d'));
        AIEO_DMM_Cache::bump_version('complementary');
        wp_send_json_success();
    }

    
    public function ajax_search_products() {
        AIEO_DMM::verify_ajax_request();
        $q = isset($_GET['q']) ? sanitize_text_field(wp_unslash($_GET['q'])) : '';
        if (!function_exists('wc_get_products')) {
            wp_send_json(array('results' => array()));
        }
        $products = wc_get_products(array(
            'status'  => array('publish', 'private'),
            'limit'   => 25,
            's'       => $q,
            'orderby' => 'title',
            'order'   => 'ASC',
        ));
        $results = array();
        foreach ($products as $p) {
            $results[] = array('id' => (int) $p->get_id(), 'text' => $p->get_name() . ' (#' . (int) $p->get_id() . ')');
        }
        wp_send_json(array('results' => $results));
    }

    
    
    

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

        
        if (empty($_FILES['csv']['tmp_name']) || !is_uploaded_file($_FILES['csv']['tmp_name'])) {
            wp_send_json_error(array('message' => __('No CSV uploaded.', 'ai-eshop-optimizer')));
        }
        $fh = fopen($_FILES['csv']['tmp_name'], 'r');
        
        if (!$fh) {
            wp_send_json_error(array('message' => __('Could not open uploaded file.', 'ai-eshop-optimizer')));
        }

        $header = fgetcsv($fh);
        if (!$header) {
            fclose($fh);
            wp_send_json_error(array('message' => __('Empty CSV.', 'ai-eshop-optimizer')));
        }
        $idx = array_flip(array_map('trim', $header));
        $required = array('source_sku', 'product_1_sku');
        foreach ($required as $col) {
            if (!isset($idx[$col])) {
                fclose($fh);
                wp_send_json_error(array(
                    
                    'message' => sprintf(__('Missing required column: %s', 'ai-eshop-optimizer'), $col),
                ));
            }
        }

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

        $stats = array('inserted' => 0, 'updated' => 0, 'skipped' => 0, 'errors' => array());

        while (($row = fgetcsv($fh)) !== false) {
            $get = function ($key) use ($row, $idx) {
                return isset($idx[$key]) && isset($row[$idx[$key]]) ? trim((string) $row[$idx[$key]]) : '';
            };

            $source_sku = $get('source_sku');
            if ($source_sku === '') { $stats['skipped']++; continue; }
            $source_id  = wc_get_product_id_by_sku($source_sku);
            if (!$source_id) {
                
                $stats['errors'][] = sprintf(__('Unknown source SKU: %s', 'ai-eshop-optimizer'), $source_sku);
                $stats['skipped']++;
                continue;
            }

            $pids = array();
            foreach (array('product_1_sku', 'product_2_sku', 'product_3_sku') as $k) {
                $sku = $get($k);
                if ($sku === '') { continue; }
                $pid = wc_get_product_id_by_sku($sku);
                if ($pid) { $pids[] = (int) $pid; }
                else {
                    
                    $stats['errors'][] = sprintf(__('Unknown SKU: %1$s (in row for %2$s)', 'ai-eshop-optimizer'), $sku, $source_sku);
                }
            }
            if (empty($pids)) { $stats['skipped']++; continue; }
            $pids = array_slice(array_unique($pids), 0, 3);
            if (in_array((int) $source_id, $pids, true)) {
                $pids = array_values(array_diff($pids, array((int) $source_id)));
            }
            if (empty($pids)) { $stats['skipped']++; continue; }

            $data = array(
                'enabled'           => $get('enabled') === '0' ? 0 : 1,
                'label'             => $get('label'),
                'source_product_id' => (int) $source_id,
                'product_ids'       => wp_json_encode($pids),
                'offer_title'       => $get('offer_title'),
                'button_text'       => $get('button_text'),
                'placement'         => 'before_add_to_cart',
                'checkboxes_state'  => 'unchecked',
            );
            $formats = array('%d', '%s', '%d', '%s', '%s', '%s', '%s', '%s');

            
            $existing_id = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$table} WHERE source_product_id = %d",
                (int) $source_id
            ));
            if ($existing_id > 0) {
                $wpdb->update($table, $data, array('id' => $existing_id), $formats, array('%d'));
                $stats['updated']++;
            } else {
                $wpdb->insert($table, $data, $formats);
                $stats['inserted']++;
            }
        }
        fclose($fh);

        AIEO_DMM_Cache::bump_version('complementary');

        wp_send_json_success(array(
            'message' => sprintf(
                
                __('Import complete: %1$d inserted, %2$d updated, %3$d skipped.', 'ai-eshop-optimizer'),
                $stats['inserted'], $stats['updated'], $stats['skipped']
            ),
            'stats' => $stats,
        ));
    }

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

        global $wpdb;
        $rows = $wpdb->get_results(
            "SELECT * FROM " . $wpdb->prefix . "aieo_dmm_complementary ORDER BY id ASC",
            ARRAY_A
        );

        
        
        $tmp = fopen('php://temp', 'w+');
        fputcsv($tmp, array('source_sku', 'product_1_sku', 'product_2_sku', 'product_3_sku', 'label', 'enabled', 'offer_title', 'button_text', 'placement'));

        foreach ((array) $rows as $row) {
            $source = wc_get_product((int) $row['source_product_id']);
            if (!$source) { continue; }

            $pids = json_decode($row['product_ids'] ?? '[]', true);
            if (!is_array($pids)) { $pids = array(); }
            $pid_skus = array_pad(array_map(function ($id) {
                $p = wc_get_product((int) $id);
                return $p ? (string) $p->get_sku() : '';
            }, $pids), 3, '');

            fputcsv($tmp, array(
                (string) $source->get_sku(),
                $pid_skus[0],
                $pid_skus[1],
                $pid_skus[2],
                (string) $row['label'],
                !empty($row['enabled']) ? '1' : '0',
                (string) $row['offer_title'],
                (string) $row['button_text'],
                (string) $row['placement'],
            ));
        }

        rewind($tmp);
        $csv = stream_get_contents($tmp);
        fclose($tmp);

        wp_send_json_success(array(
            'filename' => 'aieo-complementary-' . gmdate('Ymd-His') . '.csv',
            'mime'     => 'text/csv',
            'b64'      => base64_encode($csv),
        ));
    }

    
    
    

    
    private function detect_legacy_pods_data() {
        global $wpdb;
        $table = $wpdb->prefix . 'pods_promo_campaign';
        if (!aieo_dmm_table_exists($table)) { return false; }
        $count = (int) $wpdb->get_var(
            "SELECT COUNT(*) FROM {$table} WHERE is_active = 1 AND campaign_type = 1"
        );
        return $count > 0;
    }

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

        global $wpdb;
        $table        = $wpdb->prefix . 'aieo_dmm_complementary';
        $legacy_table = $wpdb->prefix . 'pods_promo_campaign';

        if (!aieo_dmm_table_exists($legacy_table)) {
            wp_send_json_error(array('message' => __('No legacy `wp_pods_promo_campaign` table — nothing to migrate.', 'ai-eshop-optimizer')));
        }

        $stats = array('inserted' => 0, 'updated' => 0, 'skipped' => 0);
        $rows  = $wpdb->get_results(
            "SELECT name, source_product, product_1, product_2, product_3
             FROM {$legacy_table}
             WHERE is_active = 1 AND campaign_type = 1",
            ARRAY_A
        );
        if (!is_array($rows)) {
            wp_send_json_error(array('message' => __('Could not read the legacy table.', 'ai-eshop-optimizer')));
        }

        
        
        
        $resolve_pid = function ($value) {
            $value = trim((string) $value);
            if ($value === '') { return 0; }
            if (ctype_digit($value)) {
                $pid = (int) $value;
                if ($pid > 0 && get_post_type($pid) === 'product') {
                    return $pid;
                }
                
            }
            return (int) wc_get_product_id_by_sku($value);
        };

        foreach ($rows as $r) {
            $source_id = $resolve_pid($r['source_product'] ?? '');
            if (!$source_id) { $stats['skipped']++; continue; }

            $pids = array();
            foreach (array('product_1', 'product_2', 'product_3') as $k) {
                $pid = $resolve_pid($r[$k] ?? '');
                if ($pid) { $pids[] = $pid; }
            }
            if (empty($pids)) { $stats['skipped']++; continue; }
            $pids = array_slice(array_unique($pids), 0, 3);

            $data = array(
                'enabled'           => 1,
                'label'             => isset($r['name']) ? (string) $r['name'] : '',
                'source_product_id' => (int) $source_id,
                'product_ids'       => wp_json_encode($pids),
                'offer_title'       => '',
                'button_text'       => '',
                'placement'         => 'before_add_to_cart',
                'checkboxes_state'  => 'unchecked',
            );
            $formats = array('%d', '%s', '%d', '%s', '%s', '%s', '%s', '%s');

            $existing_id = (int) $wpdb->get_var($wpdb->prepare(
                "SELECT id FROM {$table} WHERE source_product_id = %d",
                (int) $source_id
            ));
            if ($existing_id > 0) {
                $wpdb->update($table, $data, array('id' => $existing_id), $formats, array('%d'));
                $stats['updated']++;
            } else {
                $wpdb->insert($table, $data, $formats);
                $stats['inserted']++;
            }
        }

        AIEO_DMM_Cache::bump_version('complementary');

        wp_send_json_success(array(
            'message' => sprintf(
                
                __('Migration complete: %1$d inserted, %2$d updated, %3$d skipped. You can now deactivate Pods.', 'ai-eshop-optimizer'),
                $stats['inserted'], $stats['updated'], $stats['skipped']
            ),
            'stats' => $stats,
        ));
    }

    
    
    

    public function enqueue_frontend_assets() {
        if (!is_product()) { return; }

        $css_rel  = 'assets/css/aieo-complementary.css';
        $js_rel   = 'assets/js/aieo-complementary.js';
        $css_path = AIEO_DIR . $css_rel;
        $js_path  = AIEO_DIR . $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-complementary',  AIEO_URI . $css_rel, array(), $css_ver);

        
        
        
        
        $a = self::get_appearance_settings();
        
        
        
        $cb_bg     = trim((string) ($a['btn_bg_color']     ?? ''));
        $cb_text   = trim((string) ($a['btn_text_color']   ?? ''));
        $cb_border = trim((string) ($a['btn_border_color'] ?? ''));
        $cb_bw     = (string) ($a['btn_border_width']  ?? '');
        $cb_br     = (string) ($a['btn_border_radius'] ?? '');
        $vars = sprintf(
            '.aieo-compl{'
          . '--aieo-compl-bg:%s;'
          . '--aieo-compl-border:%s;'
          . '--aieo-compl-border-w:%dpx;'
          . '--aieo-compl-border-r:%dpx;'
          . '--aieo-compl-title-size:%dpx;'
          . '--aieo-compl-text-size:%dpx;'
          . '--aieo-compl-btn-bg:%s;'
          . '--aieo-compl-btn-text:%s;'
          . '--aieo-compl-btn-border:%s;'
          . '--aieo-compl-btn-border-w:%s;'
          . '--aieo-compl-btn-border-r:%s;'
          . '}',
            esc_attr((string) $a['bg_color']),
            esc_attr((string) $a['border_color']),
            (int) $a['border_width'],
            (int) $a['border_radius'],
            (int) $a['title_size'],
            (int) $a['text_size'],
            $cb_bg     !== '' ? esc_attr($cb_bg)     : 'var(--aieo-btn-bg,#222222)',
            $cb_text   !== '' ? esc_attr($cb_text)   : 'var(--aieo-btn-fg,#ffffff)',
            $cb_border !== '' ? esc_attr($cb_border) : 'var(--aieo-btn-border,#222222)',
            $cb_bw     !== '' ? ((int) $cb_bw . 'px') : 'var(--aieo-btn-border-w,0px)',
            $cb_br     !== '' ? ((int) $cb_br . 'px') : 'var(--aieo-btn-radius,4px)'
        );
        wp_add_inline_style('aieo-complementary', $vars);

        
        $iapi_on = method_exists('AIEO_DMM', 'is_iapi_enabled') && AIEO_DMM::is_iapi_enabled('complementary');
        if ($iapi_on
            && function_exists('wp_enqueue_script_module')
            && defined('AIEO_RUNTIME_DIR')
            && file_exists(AIEO_RUNTIME_DIR . 'assets/js/aieo-complementary-iapi.js')
        ) {
            wp_register_script_module(
                '@aieo/complementary-iapi',
                AIEO_RUNTIME_URI . 'assets/js/aieo-complementary-iapi.js',
                array('@wordpress/interactivity', '@aieo/iapi-bootstrap'),
                (string) filemtime(AIEO_RUNTIME_DIR . 'assets/js/aieo-complementary-iapi.js')
            );
            wp_enqueue_script_module('@aieo/complementary-iapi');
        } else {
            wp_enqueue_script('aieo-complementary', AIEO_URI . $js_rel,  array('jquery'), $js_ver, true);
        }

        $compl_data = array(
            'ajaxUrl' => admin_url('admin-ajax.php'),
            'nonce'   => wp_create_nonce('aieo_dmm_complementary_add'),
            'i18n'    => array(
                'adding'        => __('Adding…', 'ai-eshop-optimizer'),
                'added'         => __('Added to cart.', 'ai-eshop-optimizer'),
                'failed'        => __('Could not add — please try again.', 'ai-eshop-optimizer'),
                'pickOne'       => __('Please tick at least one product first.', 'ai-eshop-optimizer'),
                'pickVariation' => __('Pick a variation for each variable product.', 'ai-eshop-optimizer'),
            ),
        );
        if ($iapi_on) {
            add_action('wp_print_footer_scripts', static function () use ($compl_data) {
                echo '<script id="aieo-complementary-data">'
                    . 'window.aieoComplementary = ' . wp_json_encode($compl_data) . ';'
                    . '</script>' . "\n";
            }, 5);
        } else {
            wp_localize_script('aieo-complementary', 'aieoComplementary', $compl_data);
        }
    }

    
    public function render_for_current_product() {
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        $row = $this->get_row_for_source((int) $product->get_id());
        if (!$row || empty($row['enabled'])) { return; }
        $this->render_picker_html($row);
    }

    
    public function render_fallback_for_current_product() {
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        
        if ($product->is_purchasable() && $product->is_in_stock()) { return; }
        $row = $this->get_row_for_source((int) $product->get_id());
        if (!$row || empty($row['enabled'])) { return; }
        $this->render_picker_html($row);
    }

    
    public function get_row_for_source($source_product_id) {
        global $wpdb;
        $table = $wpdb->prefix . 'aieo_dmm_complementary';
        if (!aieo_dmm_table_exists($table)) { return null; }

        return AIEO_DMM_Cache::remember('complementary', 'src_' . (int) $source_product_id, function () use ($wpdb, $table, $source_product_id) {
            $row = $wpdb->get_row($wpdb->prepare(
                "SELECT * FROM {$table} WHERE source_product_id = %d AND enabled = 1 LIMIT 1",
                (int) $source_product_id
            ), ARRAY_A);
            if (!$row) { return null; }
            return $this->hydrate_row($row);
        }, AIEO_DMM_Cache::TTL_SHORT);
    }

    
    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_COMPLEMENTARY] = $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') && !AIEO_DMM_Settings::is_module_enabled('complementary')) {
            return array('eligible' => false);
        }
        $instance = self::eligibility_instance();
        $row = $instance->get_row_for_source($product_id);
        if (!$row || empty($row['product_ids'])) { return array('eligible' => false); }
        return array(
            'eligible' => true,
            'offer_id' => isset($row['id']) ? (int) $row['id'] : null,
            'payload'  => array(
                'count' => count((array) $row['product_ids']),
            ),
        );
    }

    private static function eligibility_instance() {
        static $inst = null;
        if ($inst === null) {
            if (class_exists('AIEO_DMM') && method_exists('AIEO_DMM', 'instance')) {
                $mod = AIEO_DMM::instance()->get_module('complementary');
                $inst = ($mod instanceof self) ? $mod : new self();
            } else {
                $inst = new self();
            }
        }
        return $inst;
    }

    
    public function render_picker_html(array $row) {
        $source_id = (int) ($row['source_product_id'] ?? 0);
        if ($source_id > 0 && !empty($this->rendered_for[$source_id])) { return; }

        $title  = $row['offer_title'] !== '' ? $row['offer_title'] : $this->default_offer_title();
        $btn    = $row['button_text'] !== '' ? $row['button_text'] : $this->default_button_text();
        $checked = ($row['checkboxes_state'] === 'checked') ? ' checked' : '';

        $items = array();
        foreach ($row['product_ids'] as $pid) {
            $p = wc_get_product((int) $pid);
            if (!$p || !$p->is_purchasable() || !$p->is_in_stock()) { continue; }
            $items[] = $p;
        }
        if (empty($items)) { return; }
        if ($source_id > 0) { $this->rendered_for[$source_id] = true; }

        
        
        
        
        
        
        ?>
        <div class="aieo-compl" data-source="<?php echo esc_attr((int) $row['source_product_id']); ?>">
            <h4 class="aieo-compl-title"><?php echo esc_html($title); ?></h4>
            <ul class="aieo-compl-list">
                <?php foreach ($items as $p) :
                    $is_variable = $p->is_type('variable');
                    $variations  = $is_variable ? self::get_variations_for_product($p) : array();
                ?>
                <li class="aieo-compl-item<?php echo $is_variable ? ' aieo-compl-item--variable' : ''; ?>">
                    <label class="aieo-compl-label">
                        <input type="checkbox" class="aieo-compl-check" value="<?php echo esc_attr((int) $p->get_id()); ?>"<?php echo $checked ? ' checked="checked"' : ''; ?>>
                        <span class="aieo-compl-thumb">
                            <?php echo $p->get_image('thumbnail'); ?>
                        </span>
                        <span class="aieo-compl-meta">
                            <span class="aieo-compl-name"><?php echo esc_html($p->get_name()); ?></span>
                            <span class="aieo-compl-price"><?php echo wp_kses_post($p->get_price_html()); ?></span>
                            <?php if ($is_variable && !empty($variations)) : ?>
                                <select class="aieo-compl-variation" data-product-id="<?php echo esc_attr((int) $p->get_id()); ?>" aria-label="<?php esc_attr_e('Pick variation', 'ai-eshop-optimizer'); ?>">
                                    <option value="0">— <?php esc_html_e('Pick variation', 'ai-eshop-optimizer'); ?> —</option>
                                    <?php foreach ($variations as $v) : ?>
                                        <option value="<?php echo esc_attr((int) $v['variation_id']); ?>"><?php echo esc_html($v['label']); ?></option>
                                    <?php endforeach; ?>
                                </select>
                            <?php elseif ($is_variable) : ?>
                                <small class="aieo-compl-novar" style="color:#9a3412;">— <?php esc_html_e('No in-stock variations available.', 'ai-eshop-optimizer'); ?> —</small>
                            <?php endif; ?>
                        </span>
                    </label>
                    <?php
                    
                    
                    
                    
                    
                    
                    $product_url = $p->get_permalink();
                    if ($product_url) :
                    ?>
                    <a class="aieo-compl-visit"
                       href="<?php echo esc_url($product_url); ?>"
                       target="_blank"
                       rel="noopener noreferrer"
                       aria-label="<?php echo esc_attr(sprintf( __('View product: %s (opens in a new tab)', 'ai-eshop-optimizer'), $p->get_name())); ?>"
                       title="<?php esc_attr_e('View product', 'ai-eshop-optimizer'); ?>">
                        <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" focusable="false">
                            <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6"></path>
                            <polyline points="15 3 21 3 21 9"></polyline>
                            <line x1="10" y1="14" x2="21" y2="3"></line>
                        </svg>
                    </a>
                    <?php endif; ?>
                </li>
                <?php endforeach; ?>
            </ul>
            <button type="button" class="aieo-compl-add button"><?php echo esc_html($btn); ?></button>
            <span class="aieo-compl-status" aria-live="polite"></span>
        </div>
        <?php
    }

    
    public function ajax_bulk_add_to_cart() {
        check_ajax_referer('aieo_dmm_complementary_add', 'nonce');

        if (!function_exists('WC') || !WC()->cart) {
            wp_send_json_error(array('message' => __('Cart unavailable.', 'ai-eshop-optimizer')));
        }

        $ids = isset($_POST['product_ids']) && is_array($_POST['product_ids'])
            ? array_values(array_filter(array_map('absint', wp_unslash($_POST['product_ids']))))
            : array();
        if (empty($ids)) {
            wp_send_json_error(array('message' => __('No products selected.', 'ai-eshop-optimizer')));
        }
        $ids = array_slice(array_unique($ids), 0, 6); 

        
        
        
        
        $variation_map = array();
        if (isset($_POST['variations']) && is_array($_POST['variations'])) {
            foreach (wp_unslash($_POST['variations']) as $pid_key => $vid_val) {
                $pid_key = absint($pid_key);
                $vid_val = absint($vid_val);
                if ($pid_key > 0 && $vid_val > 0) {
                    $variation_map[$pid_key] = $vid_val;
                }
            }
        }

        
        
        
        $source_pid = isset($_POST['source_id']) ? absint(wp_unslash($_POST['source_id'])) : 0;
        $attribution = class_exists('AIEO_Attribution') ? AIEO_Attribution::instance() : null;

        $added = 0;
        foreach ($ids as $pid) {
            $product = wc_get_product($pid);
            if (!$product || !$product->is_purchasable() || !$product->is_in_stock()) { continue; }

            
            
            
            
            
            
            
            
            
            
            
            $variation_id = 0;
            $variation_attrs = array();
            $unit_price_for_log = (float) $product->get_price();
            if ($product->is_type('variable')) {
                
                
                
                
                
                $explicit_vid = isset($variation_map[(int) $pid]) ? (int) $variation_map[(int) $pid] : 0;
                if ($explicit_vid > 0) {
                    $variation = wc_get_product($explicit_vid);
                    if ($variation && $variation->is_type('variation')
                        && $variation->is_purchasable() && $variation->is_in_stock()
                        && (int) $variation->get_parent_id() === (int) $pid) {
                        $variation_id    = $explicit_vid;
                        $variation_attrs = $variation->get_variation_attributes();
                        $unit_price_for_log = (float) $variation->get_price();
                    }
                }
                if ($variation_id === 0) {
                    $picked = self::pick_default_variation($product);
                    if (!$picked) { continue; }
                    $variation_id    = (int) $picked['id'];
                    $variation_attrs = (array) $picked['attributes'];
                    $unit_price_for_log = (float) $picked['price'];
                }
            }

            
            
            
            
            
            $key = WC()->cart->add_to_cart((int) $pid, 1, $variation_id, $variation_attrs, array());
            if (!$key) { continue; }
            if (isset(WC()->cart->cart_contents[$key])) {
                WC()->cart->cart_contents[$key]['aieo_attribution_source'] = 'complementary';
            }
            $added++;

            
            
            
            if ($attribution && method_exists($attribution, 'log_event')) {
                $attribution->log_event(array(
                    'product_id' => (int) $pid,
                    'quantity'   => 1,
                    'unit_price' => $unit_price_for_log,
                    'source'     => 'complementary',
                    'source_pid' => $source_pid,
                ));
            }
        }

        if ($added === 0) {
            wp_send_json_error(array('message' => __('Could not add any of the selected products.', 'ai-eshop-optimizer')));
        }

        WC()->cart->calculate_totals();

        
        ob_start();
        woocommerce_mini_cart();
        $mini = ob_get_clean();

        wp_send_json_success(array(
            'added'     => $added,
            'cart_url'  => wc_get_cart_url(),
            
            'fragments' => apply_filters('woocommerce_add_to_cart_fragments', array(
                'div.widget_shopping_cart_content' => '<div class="widget_shopping_cart_content">' . $mini . '</div>',
            )),
        ));
    }

    
    public static function get_variations_for_product($product) {
        if (!is_object($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_disp = (string) $attr_val;
                if ($is_global && taxonomy_exists($taxonomy)) {
                    $term = get_term_by('slug', $attr_val, $taxonomy);
                    if ($term && !is_wp_error($term)) {
                        $value_disp = (string) $term->name;
                    }
                }
                $key_disp = function_exists('wc_attribute_label')
                    ? wc_attribute_label($taxonomy)
                    : ucfirst(str_replace(array('-', '_'), ' ', $taxonomy));
                $label_parts[] = $key_disp . ': ' . $value_disp;
            }
            $out[] = array(
                'variation_id' => (int) $v['variation_id'],
                'label'        => implode(' / ', $label_parts) ?: ('#' . (int) $v['variation_id']),
            );
        }
        return $out;
    }

    
    private static function pick_default_variation($product) {
        if (!is_callable(array($product, 'get_available_variations'))) { return null; }
        $variations = $product->get_available_variations();
        if (empty($variations) || !is_array($variations)) { return null; }

        
        
        $defaults = method_exists($product, 'get_default_attributes') ? $product->get_default_attributes() : array();
        if (!empty($defaults)) {
            foreach ($variations as $v) {
                if (empty($v['is_in_stock']) || empty($v['is_purchasable'])) { continue; }
                $attrs = isset($v['attributes']) && is_array($v['attributes']) ? $v['attributes'] : array();
                $matches = true;
                foreach ($defaults as $a_key => $a_val) {
                    $expected = strtolower((string) $a_val);
                    $actual   = strtolower((string) ($attrs['attribute_' . $a_key] ?? $attrs[$a_key] ?? ''));
                    if ($expected !== '' && $actual !== '' && $expected !== $actual) {
                        $matches = false;
                        break;
                    }
                }
                if ($matches) {
                    return array(
                        'id'         => (int) ($v['variation_id'] ?? 0),
                        'price'      => (float) ($v['display_price'] ?? 0),
                        'attributes' => $attrs,
                    );
                }
            }
        }

        
        
        
        $cheapest = null;
        foreach ($variations as $v) {
            if (empty($v['is_in_stock']) || empty($v['is_purchasable'])) { continue; }
            $price = (float) ($v['display_price'] ?? 0);
            if ($cheapest === null || $price < $cheapest['price']) {
                $cheapest = array(
                    'id'         => (int) ($v['variation_id'] ?? 0),
                    'price'      => $price,
                    'attributes' => isset($v['attributes']) && is_array($v['attributes']) ? $v['attributes'] : array(),
                );
            }
        }
        return $cheapest;
    }

    
    
    
    
    

    const APPEARANCE_OPTION = 'aieo_dmm_complementary_appearance';

    public static function get_appearance_settings(): array {
        $stored = get_option(self::APPEARANCE_OPTION, array());
        if (!is_array($stored)) { $stored = array(); }
        return array_merge(array(
            'title_size'        => 15,
            'text_size'         => 14,
            'bg_color'          => '#fafafa',
            'border_color'      => '#e2e2e2',
            'border_width'      => 1,
            'border_radius'     => 8,
            
            
            
            'btn_bg_color'      => '',
            'btn_text_color'    => '',
            'btn_border_color'  => '',
            'btn_border_width'  => '',
            'btn_border_radius' => '',
        ), $stored);
    }

    public function ajax_save_appearance(): void {
        AIEO_DMM::verify_ajax_request();

        $cur = self::get_appearance_settings();

        $num_clamps = array(
            'title_size'        => array(8, 48),
            'text_size'         => array(8, 32),
            'border_width'      => array(0, 10),
            'border_radius'     => array(0, 40),
            'btn_border_width'  => array(0, 10),
            'btn_border_radius' => array(0, 40),
        );
        foreach ($num_clamps as $k => list($min, $max)) {
            if (isset($_POST[$k])) {
                $cur[$k] = max($min, min($max, (int) wp_unslash($_POST[$k])));
            }
        }
        foreach (array('bg_color', 'border_color', 'btn_bg_color', 'btn_text_color', 'btn_border_color') as $k) {
            if (isset($_POST[$k])) {
                $v = sanitize_hex_color(wp_unslash((string) $_POST[$k]));
                if ($v !== null && $v !== '') { $cur[$k] = $v; }
            }
        }

        update_option(self::APPEARANCE_OPTION, $cur, false);
        wp_send_json_success(array('message' => __('Complementary Products appearance saved.', 'ai-eshop-optimizer')));
    }
}
