<?php

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

class AIEO_Wishlist {

    
    const COOKIE_NAME = 'woocommerce_items_in_cart_merchant_wishlist';
    const COOKIE_DAYS = 30;

    
    const SCHEMA_VERSION = '2';

    
    const SCHEMA_OPTION  = 'aieo_wishlist_schema_version';
    const DISPLAY_OPTION = 'aieo_wishlist_display';

    
    const MIGRATION_OPTION = 'aieo_wishlist_ppe_migrated';

    
    private static $instance = null;

    public static function instance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function __construct() {
        
        
        add_action('wp_ajax_aieo_wishlist_toggle',        array($this, 'ajax_toggle'));
        add_action('wp_ajax_nopriv_aieo_wishlist_toggle', array($this, 'ajax_toggle'));
        add_action('wp_ajax_aieo_wishlist_get',           array($this, 'ajax_get'));
        add_action('wp_ajax_nopriv_aieo_wishlist_get',    array($this, 'ajax_get'));
        
        
        
        add_action('wp_ajax_aieo_get_followed_items',         array($this, 'ajax_get_followed_items'));
        add_action('wp_ajax_nopriv_aieo_get_followed_items',  array($this, 'ajax_get_followed_items'));
        add_action('wp_ajax_aieo_get_followed_brands',        array($this, 'ajax_get_followed_brands'));
        add_action('wp_ajax_nopriv_aieo_get_followed_brands', array($this, 'ajax_get_followed_brands'));

        
        
        
        
        add_action('wp_enqueue_scripts', array($this, 'enqueue_assets'));

        
        
        
        add_action('plugins_loaded', array($this, 'maybe_install'), 20);

        
        
        
        add_action('plugins_loaded', array($this, 'maybe_migrate_from_ppe'), 25);

        
        add_shortcode('aieo_wishlist', array($this, 'render_wishlist_shortcode'));

        
        
        
        
        
        
        
        add_filter('aieo_wishlist_valid_item_types',     array(__CLASS__, 'filter_enabled_types'));
        add_filter('aieo_wishlist_followed_items_types', array(__CLASS__, 'filter_enabled_types'));

        $d = self::get_display_settings();

        
        $product_on = self::is_type_enabled('product');
        if ($product_on && !empty($d['show_on_single']) && $d['show_on_single'] === 'yes') {
            $placement = (string) $d['single_placement'];
            $map = self::single_placement_map();
            $hook = isset($map[$placement]['action'])   ? $map[$placement]['action']   : 'woocommerce_single_product_summary';
            $pri  = isset($map[$placement]['priority']) ? $map[$placement]['priority'] : 35;
            add_action($hook, array($this, 'render_single_heart'), (int) $pri);
        }
        if ($product_on && !empty($d['show_on_archive']) && $d['show_on_archive'] === 'yes') {
            add_action('woocommerce_after_shop_loop_item', array($this, 'render_loop_heart'), 5);
        }
    }

    
    public static function single_placement_map() {
        return array(
            'before_title'        => array('action' => 'woocommerce_single_product_summary', 'priority' => 4),
            'after_title'         => array('action' => 'woocommerce_single_product_summary', 'priority' => 6),
            'after_price'         => array('action' => 'woocommerce_single_product_summary', 'priority' => 11),
            'after_excerpt'       => array('action' => 'woocommerce_single_product_summary', 'priority' => 21),
            'after_add_to_cart'   => array('action' => 'woocommerce_single_product_summary', 'priority' => 35),
            'after_meta'          => array('action' => 'woocommerce_single_product_summary', 'priority' => 41),
            'before_add_to_cart'  => array('action' => 'woocommerce_before_add_to_cart_form', 'priority' => 10),
            'after_add_to_cart_btn' => array('action' => 'woocommerce_after_add_to_cart_button', 'priority' => 10),
        );
    }

    
    
    

    public static function get_table_name() {
        global $wpdb;
        return $wpdb->prefix . 'aieo_wishlist';
    }

    
    public function maybe_install() {
        $installed = get_option(self::SCHEMA_OPTION, '');
        if ($installed === self::SCHEMA_VERSION) {
            return;
        }
        self::install();
        update_option(self::SCHEMA_OPTION, self::SCHEMA_VERSION, false);
    }

    
    public static function install() {
        global $wpdb;
        $table   = self::get_table_name();
        $charset = $wpdb->get_charset_collate();
        $sql = "CREATE TABLE {$table} (
            id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
            user_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
            session_id varchar(64) NOT NULL DEFAULT '',
            item_id bigint(20) UNSIGNED NOT NULL,
            item_type varchar(20) NOT NULL DEFAULT 'product',
            source_type varchar(50) NOT NULL DEFAULT '',
            source_id bigint(20) UNSIGNED NOT NULL DEFAULT 0,
            source_name varchar(255) NOT NULL DEFAULT '',
            date_added datetime NOT NULL,
            price_at_wishlist decimal(10,2) NULL DEFAULT NULL,
            PRIMARY KEY  (id),
            KEY user_id (user_id),
            KEY session_id (session_id),
            KEY item_id (item_id),
            UNIQUE KEY user_item (user_id, session_id, item_id, item_type)
        ) {$charset};";

        if (!function_exists('dbDelta')) {
            require_once ABSPATH . 'wp-admin/includes/upgrade.php';
        }
        dbDelta($sql);

        
        
        
        
        $col = $wpdb->get_var("SHOW COLUMNS FROM {$table} LIKE 'price_at_wishlist'");
        if (!$col) {
            $wpdb->query("ALTER TABLE {$table} ADD COLUMN price_at_wishlist DECIMAL(10,2) NULL DEFAULT NULL AFTER date_added");
        }
    }

    
    
    

    
    public function enqueue_assets() {
        if (is_admin()) {
            return;
        }
        
        
        
        
        
        
        
        
        $aieo_ver  = defined('AIEO_VERSION') ? AIEO_VERSION : (defined('AIEO_RUNTIME_VERSION') ? AIEO_RUNTIME_VERSION : '0.0.0');
        $aieo_file = defined('AIEO_FILE')    ? AIEO_FILE    : (defined('AIEO_RUNTIME_FILE')    ? AIEO_RUNTIME_FILE    : __FILE__);

        
        
        
        $payload = array(
            'ajaxUrl'      => admin_url('admin-ajax.php'),
            'nonce'        => wp_create_nonce('aieo_wishlist'),
            'cookie'       => self::COOKIE_NAME,
            'enabledTypes' => self::enabled_types_list(),
        );
        wp_register_script('aieo-wishlist-globals', '', array(), $aieo_ver, false);
        wp_enqueue_script('aieo-wishlist-globals');
        wp_add_inline_script(
            'aieo-wishlist-globals',
            'window.aieoWishlist = ' . wp_json_encode($payload) . ';',
            'before'
        );

        
        
        
        
        
        $css_rel = 'assets/css/aieo-wishlist-heart.css';
        $js_rel  = 'assets/js/aieo-wishlist-heart.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_ver;
        $js_ver   = file_exists($js_path)  ? filemtime($js_path)  : $aieo_ver;
        wp_enqueue_style('aieo-wishlist-heart',  plugins_url($css_rel, $aieo_file), array(), $css_ver);

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

        $d = self::get_display_settings();
        $size_desktop = (int) $d['size'];
        $size_mobile  = (int) ($d['size_mobile'] ?? 0);
        wp_add_inline_style('aieo-wishlist-heart', sprintf(
            '.aieo-wishlist-heart{'
          . '--aieo-wl-empty:%s;--aieo-wl-filled:%s;--aieo-wl-hover:%s;'
          . '--aieo-wl-size:%dpx;}',
            esc_attr($d['color_empty']),
            esc_attr($d['color_filled']),
            esc_attr($d['color_hover']),
            $size_desktop
        ));
        
        
        if ($size_mobile > 0 && $size_mobile !== $size_desktop) {
            wp_add_inline_style('aieo-wishlist-heart', sprintf(
                '@media (max-width:768px){.aieo-wishlist-heart{--aieo-wl-size:%dpx;}}',
                $size_mobile
            ));
        }
        
        
        
        
        wp_add_inline_style('aieo-wishlist-heart',
            '.aieo-sc-fav-section{margin:0 0 16px;}'
          . '.aieo-sc-fav-section__title{margin:0 0 8px;font-size:11px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:#9ca3af;}'
          . '.aieo-sc-fav-brand-list{list-style:none;margin:0;padding:0;display:flex;flex-direction:column;gap:6px;}'
          . '.aieo-sc-fav-brand{margin:0;}'
          . '.aieo-sc-fav-brand__link{display:flex;align-items:center;gap:10px;padding:8px 10px;border:1px solid #e5e7eb;border-radius:8px;text-decoration:none;color:#1f2937;background:#fff;transition:border-color 120ms ease,transform 120ms ease;}'
          . '.aieo-sc-fav-brand__link:hover{border-color:#F46767;transform:translateY(-1px);}'
          . '.aieo-sc-fav-brand__logo{flex:0 0 40px;width:40px;height:40px;display:flex;align-items:center;justify-content:center;background:#f9fafb;border-radius:6px;overflow:hidden;font-weight:700;color:#F46767;font-size:18px;}'
          . '.aieo-sc-fav-brand__logo img{max-width:100%;max-height:100%;object-fit:contain;}'
          . '.aieo-sc-fav-brand__body{display:flex;flex-direction:column;gap:2px;min-width:0;flex:1 1 auto;}'
          . '.aieo-sc-fav-brand__name{font-weight:600;font-size:13px;text-overflow:ellipsis;overflow:hidden;white-space:nowrap;text-transform:uppercase;letter-spacing:.02em;}'
          . '.aieo-sc-fav-brand__meta{font-size:11px;color:#6b7280;}'
        );
        $wishlist_url = !empty($d['wishlist_page_id'])
            ? (string) get_permalink((int) $d['wishlist_page_id'])
            : '';
        $heart_data = array(
            'tooltipAdd'     => (string) $d['tooltip_add'],
            'tooltipRemove'  => (string) $d['tooltip_remove'],
            'showTooltip'    => !empty($d['show_tooltip']) && $d['show_tooltip'] === 'yes',
            'wishlistUrl'    => $wishlist_url,
            'archivePosition'=> (string) $d['archive_position'],
        );
        if ($iapi_on) {
            
            add_action('wp_print_footer_scripts', static function () use ($heart_data) {
                echo '<script id="aieo-wishlist-heart-data">'
                    . 'window.aieoWishlistHeart = ' . wp_json_encode($heart_data) . ';'
                    . '</script>' . "\n";
            }, 5);
        } else {
            wp_localize_script('aieo-wishlist-heart', 'aieoWishlistHeart', $heart_data);
        }
    }

    
    public static function get_display_settings() {
        $stored = get_option(self::DISPLAY_OPTION, array());
        if (!is_array($stored)) { $stored = array(); }
        return array_merge(array(
            
            'color_empty'       => '#c0c4c9',
            'color_filled'      => '#e0245e',
            'color_hover'       => '#a01c48',
            'size'              => 22,
            
            
            
            
            
            'size_mobile'       => 18,
            
            'tooltip_add'       => __('Add to wishlist', 'ai-eshop-optimizer'),
            'tooltip_remove'    => __('Remove from wishlist', 'ai-eshop-optimizer'),
            'show_tooltip'      => 'yes',
            
            'show_on_single'    => 'yes',
            'show_on_archive'   => 'yes',
            
            'single_placement'  => 'after_add_to_cart',  
            'archive_position'  => 'top-right',           
            
            
            'wishlist_page_id'  => 0,
            
            
            
            
            'single_label_add'  => __('Add to your favourites', 'ai-eshop-optimizer'),
            'single_label_view' => __('See your favourites', 'ai-eshop-optimizer'),
            'single_show_label' => 'yes',
            
            
            
            'wishlist_type_product'  => 'yes',
            'wishlist_type_brand'    => 'yes',
            'wishlist_type_category' => 'yes',
            'wishlist_type_need'     => 'yes',
            'wishlist_type_blogpost' => 'yes',
        ), $stored);
    }

    
    
    

    
    public function render_single_heart() {
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        
        echo $this->build_heart_html($product, 'single_product');
    }

    
    public function render_loop_heart() {
        global $product;
        if (!$product || !is_a($product, 'WC_Product')) { return; }
        
        echo $this->build_heart_html($product, 'archive');
    }

    
    private function build_heart_html($product, $source_type) {
        $pid     = (int) $product->get_id();
        $ids     = $this->get_items_for_viewer(get_current_user_id(), 'product');
        $in_list = in_array($pid, array_map('intval', (array) $ids), true);
        $cookie  = $this->cookie_ids();
        if (!$in_list && in_array($pid, $cookie, true)) { $in_list = true; }

        $d = self::get_display_settings();
        $classes = 'aieo-wishlist-heart';
        $classes .= ' aieo-wishlist-heart--' . $source_type;      
        if ($source_type === 'archive') {
            $classes .= ' aieo-wishlist-pos-' . sanitize_html_class($d['archive_position']);
        }
        if ($in_list) { $classes .= ' is-in-list'; }

        $tooltip = $in_list ? (string) $d['tooltip_remove'] : (string) $d['tooltip_add'];

        $btn = '<button type="button"'
            . ' class="' . esc_attr($classes) . '"'
            . ' data-aieo-wishlist-product="' . esc_attr((string) $pid) . '"'
            . ' data-aieo-wishlist-source="' . esc_attr($source_type) . '"'
            . ' data-tooltip-add="' . esc_attr((string) $d['tooltip_add']) . '"'
            . ' data-tooltip-remove="' . esc_attr((string) $d['tooltip_remove']) . '"'
            . ' aria-label="' . esc_attr($tooltip) . '"'
            . ' aria-pressed="' . ($in_list ? 'true' : 'false') . '">'
            .   '<svg class="aieo-wishlist-heart-icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">'
            .     '<path class="aieo-wishlist-heart-outline" d="M12 21s-7.5-4.7-9.5-9.4C1.1 8.3 3 5 6.2 5c1.9 0 3.4 1 4.5 2.7C11.7 6 13.2 5 15.1 5c3.2 0 5.1 3.3 3.7 6.6C18.5 16.3 12 21 12 21z" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round"/>'
            .     '<path class="aieo-wishlist-heart-fill"    d="M12 21s-7.5-4.7-9.5-9.4C1.1 8.3 3 5 6.2 5c1.9 0 3.4 1 4.5 2.7C11.7 6 13.2 5 15.1 5c3.2 0 5.1 3.3 3.7 6.6C18.5 16.3 12 21 12 21z" fill="currentColor"/>'
            .   '</svg>'
            . (!empty($d['show_tooltip']) && $d['show_tooltip'] === 'yes' && $source_type !== 'single_product'
                ? '<span class="aieo-wishlist-heart-tooltip">' . esc_html($tooltip) . '</span>'
                : '')
            . '</button>';

        
        
        
        
        
        
        
        if ($source_type !== 'single_product') {
            return $btn;
        }
        if (empty($d['single_show_label']) || $d['single_show_label'] !== 'yes') {
            return $btn;
        }
        $label_text = $in_list ? (string) $d['single_label_view'] : (string) $d['single_label_add'];
        $label_html = '<a href="#" class="aieo-wishlist-heart-label"'
            . ' data-aieo-wishlist-label="' . esc_attr((string) $pid) . '"'
            . ' data-label-add="' . esc_attr((string) $d['single_label_add']) . '"'
            . ' data-label-view="' . esc_attr((string) $d['single_label_view']) . '">'
            .   esc_html($label_text)
            . '</a>';
        return '<div class="aieo-wishlist-heart-wrap' . ($in_list ? ' is-in-list' : '') . '">'
            .  $btn . $label_html
            . '</div>';
    }

    
    
    

    
    public function ajax_toggle() {
        check_ajax_referer('aieo_wishlist', 'nonce');

        $item_id = isset($_POST['item_id']) ? absint(wp_unslash($_POST['item_id'])) : 0;
        if (!$item_id) {
            $item_id = isset($_POST['product_id']) ? absint(wp_unslash($_POST['product_id'])) : 0;
        }
        if (!$item_id) {
            wp_send_json_error(array('message' => __('Invalid item ID.', 'ai-eshop-optimizer')));
        }

        $item_type = isset($_POST['item_type']) ? sanitize_key((string) $_POST['item_type']) : 'product';
        
        
        
        
        
        
        $valid_types = (array) apply_filters(
            'aieo_wishlist_valid_item_types',
            array('product', 'post', 'archive', 'page', 'brand', 'product_cat', 'pa-need')
        );
        
        
        if ($item_type !== '' && !self::is_type_enabled($item_type)) {
            wp_send_json_error(array('message' => __('This wishlist type is disabled.', 'ai-eshop-optimizer')));
        }
        if (!in_array($item_type, $valid_types, true)) {
            $item_type = 'product';
        }

        
        
        
        if ($item_type === 'product') {
            $post_type = get_post_type($item_id);
            if ($post_type !== 'product' && $post_type !== 'product_variation') {
                wp_send_json_error(array('message' => __('Invalid product ID.', 'ai-eshop-optimizer')));
            }
        } else {
            $taxonomy = self::taxonomy_for_item_type($item_type);
            if ($taxonomy !== '' && !term_exists($item_id, $taxonomy)) {
                wp_send_json_error(array('message' => sprintf(
                    
                    __('Invalid %s term ID.', 'ai-eshop-optimizer'),
                    $item_type
                )));
            }
        }

        $action_type = isset($_POST['wishlist_action']) ? sanitize_key((string) $_POST['wishlist_action']) : 'add';
        if ($action_type !== 'add' && $action_type !== 'remove') {
            $action_type = 'add';
        }

        $source_type = isset($_POST['source_type']) ? sanitize_key((string) $_POST['source_type']) : '';
        $source_id   = isset($_POST['source_id'])   ? absint(wp_unslash($_POST['source_id'])) : 0;
        $source_name = isset($_POST['source_name']) ? sanitize_text_field((string) wp_unslash($_POST['source_name'])) : '';

        $user_id = get_current_user_id();

        if ($action_type === 'add') {
            $this->add_item($item_id, $item_type, $user_id, $source_type, $source_id, $source_name);
        } else {
            $this->remove_item($item_id, $item_type, $user_id);
        }

        
        
        
        
        if ($item_type === 'product') {
            $cookie = $this->cookie_ids();
            if ($action_type === 'add' && !in_array($item_id, $cookie, true)) {
                $cookie[] = $item_id;
            } elseif ($action_type === 'remove') {
                $cookie = array_values(array_diff($cookie, array($item_id)));
            }
            $this->write_cookie($cookie);
            wp_send_json_success(array(
                'count'     => count($cookie),
                'action'    => $action_type,
                'in_list'   => in_array($item_id, $cookie, true),
                'item_type' => $item_type,
            ));
        }

        wp_send_json_success(array(
            'action'    => $action_type,
            'item_id'   => $item_id,
            'item_type' => $item_type,
        ));
    }

    
    public function ajax_get() {
        check_ajax_referer('aieo_wishlist', 'nonce');
        $item_type = isset($_POST['item_type']) ? sanitize_key((string) $_POST['item_type']) : 'product';
        $user_id   = get_current_user_id();
        $ids       = $this->get_items_for_viewer($user_id, $item_type);
        wp_send_json_success(array(
            'ids'   => array_values($ids),
            'count' => count($ids),
        ));
    }

    
    public static function taxonomy_for_item_type($item_type) {
        switch ((string) $item_type) {
            case 'brand':       return 'product_brand';
            case 'product_cat': return 'product_cat';
            case 'pa-need':     return 'pa-need';
        }
        return '';
    }

    
    public static function type_setting_key($item_type) {
        switch ((string) $item_type) {
            case 'product':     return 'wishlist_type_product';
            case 'brand':       return 'wishlist_type_brand';
            case 'product_cat': return 'wishlist_type_category';
            case 'pa-need':     return 'wishlist_type_need';
            case 'post':        return 'wishlist_type_blogpost';
        }
        return '';
    }

    
    public static function is_type_enabled($item_type) {
        $key = self::type_setting_key($item_type);
        if ($key === '') { return true; }
        $d = self::get_display_settings();
        return !isset($d[$key]) || $d[$key] === 'yes';
    }

    
    public static function enabled_types_list() {
        $all = array('product', 'brand', 'product_cat', 'pa-need', 'post');
        return array_values(array_filter($all, array(__CLASS__, 'is_type_enabled')));
    }

    
    public static function filter_enabled_types($types) {
        return array_values(array_filter((array) $types, array(__CLASS__, 'is_type_enabled')));
    }

    
    public function ajax_get_followed_items() {
        check_ajax_referer('aieo_wishlist', 'nonce');
        $item_type = isset($_POST['item_type']) ? sanitize_key((string) $_POST['item_type']) : 'brand';
        
        
        
        $valid = (array) apply_filters(
            'aieo_wishlist_followed_items_types',
            array('brand', 'product_cat', 'pa-need', 'post')
        );
        if (!in_array($item_type, $valid, true)) {
            wp_send_json_error(array('message' => __('Unsupported item_type.', 'ai-eshop-optimizer')));
        }

        $user_id = get_current_user_id();
        $ids     = $this->get_items_for_viewer($user_id, $item_type);
        $items   = self::shape_items_for_type($item_type, $ids);
        wp_send_json_success(array(
            'item_type' => $item_type,
            'items'     => $items,
            'count'     => count($items),
        ));
    }

    
    public function ajax_get_followed_brands() {
        check_ajax_referer('aieo_wishlist', 'nonce');
        $user_id = get_current_user_id();
        $ids     = $this->get_items_for_viewer($user_id, 'brand');
        $brands  = self::shape_items_for_type('brand', $ids);
        wp_send_json_success(array('brands' => $brands, 'count' => count($brands)));
    }

    
    public static function shape_items_for_type($item_type, array $ids) {
        $ids = array_values(array_filter(array_map('intval', $ids), function ($v) { return $v > 0; }));
        if (empty($ids)) { return array(); }

        if ($item_type === 'brand' && class_exists('AIEO_Core_Brand_Vitals')) {
            $rows = AIEO_Core_Brand_Vitals::instance()->get_by_ids($ids);
            $out  = array();
            foreach ($rows as $b) {
                $out[] = array(
                    'id'        => (int) $b['term_id'],
                    'name'      => (string) $b['name'],
                    'permalink' => (string) $b['permalink'],
                    'logo_url'  => (string) $b['logo_url'],
                    'count'     => (int) $b['product_count'],
                    'item_type' => 'brand',
                );
            }
            return apply_filters('aieo_wishlist_shape_items', $out, $item_type, $ids);
        }

        
        
        if ($item_type === 'post') {
            $out = array();
            foreach ($ids as $pid) {
                $post = get_post($pid);
                if (!$post || $post->post_status !== 'publish') { continue; }
                $thumb = (string) get_the_post_thumbnail_url($pid, 'medium');
                $excerpt = wp_strip_all_tags((string) get_the_excerpt($pid));
                $out[] = array(
                    'id'        => (int) $post->ID,
                    'name'      => (string) get_the_title($pid),
                    'permalink' => (string) get_permalink($pid),
                    'logo_url'  => $thumb,
                    'excerpt'   => wp_trim_words($excerpt, 14),
                    'count'     => 0,
                    'item_type' => 'post',
                );
            }
            return apply_filters('aieo_wishlist_shape_items', $out, $item_type, $ids);
        }

        
        
        
        $taxonomy = self::taxonomy_for_item_type($item_type);
        $out = array();
        if ($taxonomy !== '') {
            foreach ($ids as $tid) {
                $term = get_term($tid, $taxonomy);
                if (!$term || is_wp_error($term)) { continue; }
                $thumb_id = (int) get_term_meta($tid, 'thumbnail_id', true);
                $thumb    = $thumb_id > 0 ? (string) wp_get_attachment_image_url($thumb_id, 'medium') : '';
                $out[] = array(
                    'id'        => (int) $term->term_id,
                    'name'      => (string) $term->name,
                    'permalink' => is_wp_error(get_term_link($term)) ? '' : (string) get_term_link($term),
                    'logo_url'  => $thumb,
                    'count'     => (int) ($term->count ?? 0),
                    'item_type' => $item_type,
                );
            }
        }
        return apply_filters('aieo_wishlist_shape_items', $out, $item_type, $ids);
    }

    
    
    

    public function add_item($item_id, $item_type, $user_id, $source_type = '', $source_id = 0, $source_name = '') {
        global $wpdb;
        $item_id = (int) $item_id;
        if ($item_id <= 0) { return false; }

        $session_id = $user_id ? '' : $this->get_or_create_session_id();

        
        $exists = (int) $wpdb->get_var($wpdb->prepare(
            "SELECT id FROM " . self::get_table_name() . "
             WHERE user_id = %d AND session_id = %s AND item_id = %d AND item_type = %s
             LIMIT 1",
            $user_id, $session_id, $item_id, $item_type
        ));
        if ($exists > 0) { return $exists; }

        
        
        $price_at_wishlist = null;
        if (function_exists('wc_get_product') && $item_type === 'product') {
            $product = wc_get_product($item_id);
            if ($product) {
                $p = (float) $product->get_price();
                if ($p > 0) { $price_at_wishlist = round($p, 2); }
            }
        }

        $wpdb->insert(
            self::get_table_name(),
            array(
                'user_id'           => (int) $user_id,
                'session_id'        => (string) $session_id,
                'item_id'           => $item_id,
                'item_type'         => $item_type,
                'source_type'       => (string) $source_type,
                'source_id'         => (int) $source_id,
                'source_name'       => (string) $source_name,
                'date_added'        => current_time('mysql', true),
                'price_at_wishlist' => $price_at_wishlist,
            ),
            array('%d', '%s', '%d', '%s', '%s', '%d', '%s', '%s', '%f')
        );
        $insert_id = (int) $wpdb->insert_id;

        
        do_action('aieo_wishlist_item_added', $insert_id, $item_id, $item_type, (int) $user_id, $session_id);

        return $insert_id;
    }

    public function remove_item($item_id, $item_type, $user_id) {
        global $wpdb;
        $item_id = (int) $item_id;
        if ($item_id <= 0) { return 0; }
        $session_id = $user_id ? '' : $this->get_or_create_session_id();
        return (int) $wpdb->delete(
            self::get_table_name(),
            array(
                'user_id'    => (int) $user_id,
                'session_id' => (string) $session_id,
                'item_id'    => $item_id,
                'item_type'  => $item_type,
            ),
            array('%d', '%s', '%d', '%s')
        );
    }

    
    public function get_items_for_viewer($user_id, $item_type = 'product') {
        global $wpdb;
        $user_id = (int) $user_id;
        $rows = array();

        if ($user_id > 0) {
            $rows = $wpdb->get_col($wpdb->prepare(
                "SELECT item_id FROM " . self::get_table_name() . "
                 WHERE user_id = %d AND item_type = %s
                 ORDER BY date_added DESC",
                $user_id, $item_type
            ));
        } else {
            $session_id = $this->get_or_create_session_id();
            if ($session_id !== '') {
                $rows = $wpdb->get_col($wpdb->prepare(
                    "SELECT item_id FROM " . self::get_table_name() . "
                     WHERE user_id = 0 AND session_id = %s AND item_type = %s
                     ORDER BY date_added DESC",
                    $session_id, $item_type
                ));
            }
        }

        $rows = array_map('intval', (array) $rows);

        
        
        
        if ($item_type === 'product') {
            $cookie = $this->cookie_ids();
            foreach ($cookie as $cid) {
                if (!in_array($cid, $rows, true)) {
                    $rows[] = $cid;
                }
            }
        }

        return $rows;
    }

    public function is_wishlisted($item_id, $item_type = 'product') {
        $items = $this->get_items_for_viewer(get_current_user_id(), $item_type);
        return in_array((int) $item_id, $items, true);
    }

    
    
    

    public function cookie_ids() {
        if (!isset($_COOKIE[self::COOKIE_NAME])) { return array(); }
        $raw = sanitize_text_field((string) wp_unslash($_COOKIE[self::COOKIE_NAME]));
        if ($raw === '') { return array(); }
        return array_values(array_filter(array_map('absint', explode(',', $raw))));
    }

    public function write_cookie(array $ids) {
        $value   = implode(',', array_map('intval', $ids));
        $expires = time() + (self::COOKIE_DAYS * DAY_IN_SECONDS);
        $path    = COOKIEPATH ? COOKIEPATH : '/';
        if (!headers_sent()) {
            setcookie(self::COOKIE_NAME, $value, $expires, $path, COOKIE_DOMAIN);
        }
        $_COOKIE[self::COOKIE_NAME] = $value;
    }

    
    
    

    
    public function maybe_migrate_from_ppe() {
        if (get_option(self::MIGRATION_OPTION) === '1') {
            return;
        }
        global $wpdb;
        $ppe_table = $wpdb->prefix . 'om_ppe_wishlist';
        $exists = (string) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $ppe_table));
        if ($exists !== $ppe_table) {
            
            update_option(self::MIGRATION_OPTION, '1', false);
            return;
        }
        $aieo_table = self::get_table_name();
        
        
        
        $wpdb->query("
            INSERT IGNORE INTO {$aieo_table}
                (user_id, session_id, item_id, item_type, source_type, source_id, source_name, date_added)
            SELECT
                user_id, session_id, item_id, item_type, source_type, source_id, source_name, date_added
            FROM {$ppe_table}
        ");
        update_option(self::MIGRATION_OPTION, '1', false);
    }

    
    public static function force_migrate_from_ppe() {
        delete_option(self::MIGRATION_OPTION);
        self::instance()->maybe_migrate_from_ppe();
    }

    
    
    

    
    public function render_wishlist_shortcode($atts = array()) {
        $atts = shortcode_atts(array(
            'columns'       => 4,
            'empty_message' => __('Your wishlist is empty.', 'ai-eshop-optimizer'),
            'continue_text' => __('Continue Shopping', 'ai-eshop-optimizer'),
            'continue_url'  => function_exists('wc_get_page_permalink') ? wc_get_page_permalink('shop') : home_url('/'),
        ), $atts, 'aieo_wishlist');

        $ids = $this->get_items_for_viewer(get_current_user_id(), 'product');
        $columns = max(1, min(6, absint($atts['columns'])));

        ob_start();
        ?>
        <div class="aieo-wishlist-page">
            <?php if (empty($ids)) : ?>
                <div class="aieo-wishlist-empty">
                    <p class="aieo-wishlist-empty-message"><?php echo esc_html($atts['empty_message']); ?></p>
                    <a href="<?php echo esc_url($atts['continue_url']); ?>" class="button aieo-wishlist-continue-btn">
                        <?php echo esc_html($atts['continue_text']); ?>
                    </a>
                </div>
            <?php else :
                $products = array_filter(array_map('wc_get_product', $ids), function ($p) {
                    return $p && $p->exists();
                });
                if (empty($products)) : ?>
                    <div class="aieo-wishlist-empty">
                        <p class="aieo-wishlist-empty-message"><?php echo esc_html($atts['empty_message']); ?></p>
                        <a href="<?php echo esc_url($atts['continue_url']); ?>" class="button aieo-wishlist-continue-btn">
                            <?php echo esc_html($atts['continue_text']); ?>
                        </a>
                    </div>
                <?php else : ?>
                    <ul class="products columns-<?php echo (int) $columns; ?> aieo-wishlist-products">
                        <?php foreach ($products as $product) :
                            $post_object = get_post($product->get_id());
                            $GLOBALS['post'] = $post_object;
                            setup_postdata($post_object);
                            ?>
                            <li <?php wc_product_class('', $product); ?>>
                                <?php $this->render_wishlist_remove_button($product); ?>
                                <?php
                                
                                do_action('woocommerce_before_shop_loop_item');
                                
                                do_action('woocommerce_before_shop_loop_item_title');
                                
                                do_action('woocommerce_shop_loop_item_title');
                                
                                do_action('woocommerce_after_shop_loop_item_title');
                                
                                do_action('woocommerce_after_shop_loop_item');
                                ?>
                            </li>
                        <?php endforeach; wp_reset_postdata(); ?>
                    </ul>
                <?php endif; ?>
            <?php endif; ?>
        </div>
        <?php
        return ob_get_clean();
    }

    
    private function render_wishlist_remove_button($product) {
        $pid = (int) $product->get_id();
        ?>
        <button type="button"
                class="aieo-wishlist-remove-btn"
                data-aieo-wishlist-remove="<?php echo esc_attr((string) $pid); ?>"
                aria-label="<?php echo esc_attr(sprintf(
                    
                    __('Remove %s from wishlist', 'ai-eshop-optimizer'),
                    wp_strip_all_tags($product->get_name())
                )); ?>">
            <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
                <line x1="18" y1="6" x2="6" y2="18"></line>
                <line x1="6" y1="6" x2="18" y2="18"></line>
            </svg>
        </button>
        <?php
    }

    
    private function get_or_create_session_id() {
        if (function_exists('WC') && WC()->session && method_exists(WC()->session, 'get_customer_id')) {
            $sid = (string) WC()->session->get_customer_id();
            if ($sid !== '') { return $sid; }
        }
        $cookie = 'aieo_wishlist_sid';
        if (isset($_COOKIE[$cookie]) && (string) $_COOKIE[$cookie] !== '') {
            return sanitize_text_field((string) wp_unslash($_COOKIE[$cookie]));
        }
        $sid = wp_generate_password(32, false, false);
        if (!headers_sent()) {
            setcookie($cookie, $sid, time() + (180 * DAY_IN_SECONDS), COOKIEPATH ? COOKIEPATH : '/', COOKIE_DOMAIN);
        }
        $_COOKIE[$cookie] = $sid;
        return $sid;
    }
}
