<?php

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

class AIEO_DMM_AI_Chat_Analytics extends AIEO_DMM_Module_Base {

    const NONCE           = 'aieo_chat_analytics';
    const SETTINGS_OPTION = 'aieo_chat_analytics_settings';
    const STATS_CADENCES  = array('off', 'hourly', 'daily', 'weekly', 'monthly');

    public function get_id()        { return 'ai_chat_analytics'; }
    public function get_label()     { return __('AI Chat Analytics', 'ai-eshop-optimizer'); }
    public function get_priority()  { return 10; }
    public function get_group()     { return 'aichat'; }       
    public function get_section()   { return 'analytics'; }    
    public function is_pro_locked() { return true; }

    public function get_pro_promo() {
        return array(
            'title'       => __('AI Chat Analytics', 'ai-eshop-optimizer'),
            'description' => __('See exactly what your shoppers asked the AI assistant and how it answered, how happy they were, which pages drive chats, where the catalogue had gaps, and whether those chats led to orders.', 'ai-eshop-optimizer'),
            'bullets'     => array(
                __('Full, searchable conversation log with happiness ratings', 'ai-eshop-optimizer'),
                __('Volume + happiness trends, logged-in vs guest', 'ai-eshop-optimizer'),
                __('Which pages shoppers start chats from (via the Session Tracker)', 'ai-eshop-optimizer'),
                __('Catalogue gaps — questions that surfaced no products', 'ai-eshop-optimizer'),
                __('Chat-assisted conversions + revenue', 'ai-eshop-optimizer'),
            ),
        );
    }

    
    
    

    public function register_hooks() {
        if (!class_exists('AIEO_Chat_Analytics') && defined('AIEO_DIR') && file_exists(AIEO_DIR . 'includes/dmm/chat-analytics/class-aieo-chat-analytics.php')) {
            require_once AIEO_DIR . 'includes/dmm/chat-analytics/class-aieo-chat-analytics.php';
        }
        if (class_exists('AIEO_Chat_Analytics')) {
            add_action(AIEO_Chat_Analytics::STATS_REFRESH_HOOK, array('AIEO_Chat_Analytics', 'refresh_stats_cache'));
        }
        add_action('wp_ajax_aieo_chat_analytics_refresh_stats',  array($this, 'ajax_refresh_stats'));
        add_action('wp_ajax_aieo_chat_analytics_stats_cadence',  array($this, 'ajax_save_stats_cadence'));
        add_action('wp_ajax_aieo_chat_analytics_save_retention', array($this, 'ajax_save_retention'));
        
        add_filter('cron_schedules', array($this, 'ensure_cron_schedules'));
        
        add_action('admin_init', array($this, 'maybe_schedule_stats'));
        
        
        
        add_action('admin_init', array($this, 'ensure_chat_schema'));
    }

    public function ensure_chat_schema() {
        if (class_exists('AI_eShop_Chat_Database_Manager') && method_exists('AI_eShop_Chat_Database_Manager', 'ensure_chat_history_columns')) {
            AI_eShop_Chat_Database_Manager::ensure_chat_history_columns();
        }
    }

    public function enqueue_admin_assets() {
        $nonce = wp_create_nonce(self::NONCE);
        wp_register_script('aieo-cac-admin', false, array('jquery'), defined('AIEO_VERSION') ? AIEO_VERSION : '1', true);
        wp_enqueue_script('aieo-cac-admin');
        $js = 'jQuery(function($){var n="' . esc_js($nonce) . '",u=window.ajaxurl;'
            . '$("#aieo-cac-refresh").on("click",function(){var b=$(this);b.prop("disabled",true).text("…");$.post(u,{action:"aieo_chat_analytics_refresh_stats",nonce:n},function(){location.reload();}).fail(function(){b.prop("disabled",false).text("Refresh now");});});'
            . '$("#aieo-cac-cadence").on("change",function(){$.post(u,{action:"aieo_chat_analytics_stats_cadence",nonce:n,cadence:$(this).val()});});'
            . '$("#aieo-cac-retention-save").on("click",function(){var s=$("#aieo-cac-retention-status");s.text("…");$.post(u,{action:"aieo_chat_analytics_save_retention",nonce:n,days:$("#aieo-cac-retention").val()},function(r){s.text(r&&r.success?"Saved ✓":"Error");}).fail(function(){s.text("Error");});});'
            . 'if($(".aieo-cac-needs-build").length){$.post(u,{action:"aieo_chat_analytics_refresh_stats",nonce:n},function(){location.reload();});}'
            . '});';
        wp_add_inline_script('aieo-cac-admin', $js);
    }

    private static function get_settings() {
        $s = get_option(self::SETTINGS_OPTION, array());
        return is_array($s) ? $s : array();
    }

    public static function get_stats_cadence() {
        $s = self::get_settings();
        $c = isset($s['stats_refresh']) ? (string) $s['stats_refresh'] : 'daily';
        return in_array($c, self::STATS_CADENCES, true) ? $c : 'daily';
    }

    public function ensure_cron_schedules($schedules) {
        if (!is_array($schedules)) { $schedules = array(); }
        if (!isset($schedules['weekly'])) {
            $schedules['weekly'] = array('interval' => 7 * DAY_IN_SECONDS, 'display' => __('Once Weekly', 'ai-eshop-optimizer'));
        }
        if (!isset($schedules['monthly'])) {
            $schedules['monthly'] = array('interval' => 30 * DAY_IN_SECONDS, 'display' => __('Once Monthly', 'ai-eshop-optimizer'));
        }
        return $schedules;
    }

    public function maybe_schedule_stats() {
        if (!class_exists('AIEO_Chat_Analytics')) { return; }
        $hook    = AIEO_Chat_Analytics::STATS_REFRESH_HOOK;
        $current = wp_get_schedule($hook);
        $cadence = self::get_stats_cadence();
        if ('off' === $cadence || !$this->table_exists($this->chat_table())) {
            if (false !== $current) { wp_clear_scheduled_hook($hook); }
            return;
        }
        if ($current === $cadence) { return; }
        if (false !== $current) { wp_clear_scheduled_hook($hook); }
        wp_schedule_event(time() + 300, $cadence, $hook);
    }

    public function ajax_refresh_stats() {
        if (!check_ajax_referer(self::NONCE, 'nonce', false)) { wp_send_json_error(array('message' => __('Security check failed.', 'ai-eshop-optimizer'))); }
        if (!current_user_can('edit_posts') || !class_exists('AIEO_Chat_Analytics')) { wp_send_json_error(array('message' => __('Not allowed.', 'ai-eshop-optimizer'))); }
        $payload = AIEO_Chat_Analytics::refresh_stats_cache();
        wp_send_json_success(array('generated_at' => $payload['generated_at']));
    }

    public function ajax_save_stats_cadence() {
        if (!check_ajax_referer(self::NONCE, 'nonce', false)) { wp_send_json_error(array('message' => __('Security check failed.', 'ai-eshop-optimizer'))); }
        if (!current_user_can('edit_posts')) { wp_send_json_error(array('message' => __('Not allowed.', 'ai-eshop-optimizer'))); }
        $cadence = isset($_POST['cadence']) ? sanitize_key(wp_unslash($_POST['cadence'])) : 'daily';
        if (!in_array($cadence, self::STATS_CADENCES, true)) { $cadence = 'daily'; }
        $s = self::get_settings();
        $s['stats_refresh'] = $cadence;
        update_option(self::SETTINGS_OPTION, $s, false);
        $this->maybe_schedule_stats();
        wp_send_json_success(array('cadence' => $cadence));
    }

    public function ajax_save_retention() {
        if (!check_ajax_referer(self::NONCE, 'nonce', false)) { wp_send_json_error(array('message' => __('Security check failed.', 'ai-eshop-optimizer'))); }
        if (!current_user_can('edit_posts')) { wp_send_json_error(array('message' => __('Not allowed.', 'ai-eshop-optimizer'))); }
        $days = isset($_POST['days']) ? (int) wp_unslash($_POST['days']) : 0;
        $days = max(1, min(3650, $days));
        update_option('aieo_chat_retention_days', $days, false);
        wp_send_json_success(array('days' => $days));
    }

    
    
    

    public function render_subtab() {
        $h = $this->chat_table();

        echo '<div class="aieo-dmm-section">';
        echo '<h2>' . esc_html__('AI Chat Analytics', 'ai-eshop-optimizer') . '</h2>';
        echo '<p class="description">' . esc_html__('What your shoppers asked the AI assistant, how it answered, how happy they were, which pages they chatted from, and whether those chats led to orders.', 'ai-eshop-optimizer') . '</p>';

        if (!$this->table_exists($h)) {
            echo '<div class="aieo-dmm-card"><p>' . esc_html__('No chat history yet — the table installs when the AI chat is set up. Once shoppers start chatting, their conversations appear here.', 'ai-eshop-optimizer') . '</p></div>';
            echo '</div>';
            return;
        }

        $logging = get_option('aieo_chat_history_enabled', '1');
        if ($logging !== '1' && $logging !== 1) {
            echo '<div class="notice notice-warning inline" style="margin:0 0 14px;"><p>' . esc_html__('Chat history logging is currently OFF, so new conversations are not being recorded. Existing data is shown below.', 'ai-eshop-optimizer') . '</p></div>';
        }

        $base = add_query_arg(array('page' => AIEO_DMM::MENU_SLUG, 'dmm_tab' => $this->get_id()), admin_url('admin.php'));
        $sections = array(
            'overview'      => __('Overview', 'ai-eshop-optimizer'),
            'conversations' => __('Conversations', 'ai-eshop-optimizer'),
            'happiness'     => __('Happiness', 'ai-eshop-optimizer'),
            'origins'       => __('Page origins', 'ai-eshop-optimizer'),
            'products'      => __('Products & gaps', 'ai-eshop-optimizer'),
            'conversions'   => __('Conversions', 'ai-eshop-optimizer'),
        );
        $section = isset($_GET['cac_section']) ? sanitize_key(wp_unslash($_GET['cac_section'])) : 'overview';
        if (!isset($sections[$section])) { $section = 'overview'; }

        echo '<h2 class="nav-tab-wrapper" style="margin-bottom:16px;">';
        foreach ($sections as $slug => $label) {
            $cls = 'nav-tab' . ($slug === $section ? ' nav-tab-active' : '');
            echo '<a href="' . esc_url(add_query_arg('cac_section', $slug, $base)) . '" class="' . esc_attr($cls) . '">' . esc_html($label) . '</a>';
        }
        echo '</h2>';

        switch ($section) {
            case 'conversations': $this->render_conversations($base, $h); break;
            case 'happiness':     $this->render_happiness($base, $h);     break;
            case 'origins':       $this->render_origins($base, $h);       break;
            case 'products':      $this->render_products($base, $h);      break;
            case 'conversions':   $this->render_conversions($base, $h);   break;
            case 'overview':
            default:              $this->render_overview($base, $h);      break;
        }

        echo '</div>';
    }

    
    
    

    private function render_overview($base, $h) {
        $cache = class_exists('AIEO_Chat_Analytics') ? AIEO_Chat_Analytics::get_cached_stats() : null;
        $ov  = ($cache && isset($cache['overview'])) ? (array) $cache['overview'] : null;
        $gen = ($cache && !empty($cache['generated_at'])) ? (string) $cache['generated_at'] : '';

        $this->render_cache_controls($gen);

        if (!$ov) {
            echo '<div class="aieo-dmm-card"><p class="description aieo-cac-needs-build">' . esc_html__('Preparing analytics… this runs in the background and can take a few seconds the first time. The panel refreshes automatically when it’s ready.', 'ai-eshop-optimizer') . '</p></div>';
            $this->render_retention_card();
            return;
        }

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Overview', 'ai-eshop-optimizer') . '</h3>';
        echo '<div class="aieo-attr-tiles">';
        $this->tile(__('Messages', 'ai-eshop-optimizer'),        number_format_i18n((int) $ov['turns']));
        $this->tile(__('Conversations', 'ai-eshop-optimizer'),   number_format_i18n((int) $ov['conversations']));
        $this->tile(__('Unique sessions', 'ai-eshop-optimizer'), number_format_i18n((int) $ov['sessions']));
        $this->tile(__('Logged-in / guest', 'ai-eshop-optimizer'), number_format_i18n((int) $ov['logged_in']) . ' / ' . number_format_i18n((int) $ov['guest']));
        $avg = ($ov['avg_rating'] !== null) ? number_format_i18n((float) $ov['avg_rating'], 1) . ' / 100' : '—';
        $this->tile(__('Avg happiness', 'ai-eshop-optimizer'), $avg);
        $rated_pct = ((int) $ov['turns'] > 0) ? round(100 * (int) $ov['rated_turns'] / (int) $ov['turns'], 1) : 0;
        $this->tile(__('Rated answers', 'ai-eshop-optimizer'), number_format_i18n((int) $ov['rated_turns']) . ' (' . $rated_pct . '%)');
        $zero_pct = ((int) $ov['turns'] > 0) ? round(100 * (int) $ov['zero_product_turns'] / (int) $ov['turns'], 1) : 0;
        $this->tile(__('Answers with 0 products', 'ai-eshop-optimizer'), number_format_i18n((int) $ov['zero_product_turns']) . ' (' . $zero_pct . '%)');
        $range = '—';
        if (!empty($ov['first_at']) && !empty($ov['last_at'])) {
            $range = date_i18n('Y-m-d', strtotime($ov['first_at'] . ' UTC')) . ' → ' . date_i18n('Y-m-d', strtotime($ov['last_at'] . ' UTC'));
        }
        $this->tile(__('Date range', 'ai-eshop-optimizer'), $range);
        echo '</div></div>';

        $this->render_trend_card(isset($ov['trend']) ? (array) $ov['trend'] : array());
        $this->render_retention_card();
    }

    private function render_trend_card($trend) {
        $max = 1;
        foreach ($trend as $t) { $max = max($max, (int) $t['n']); }
        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Messages per day (last 30 days)', 'ai-eshop-optimizer') . '</h3>';
        echo '<div style="display:flex;align-items:flex-end;gap:3px;height:120px;padding-top:8px;">';
        foreach ($trend as $t) {
            $n   = (int) $t['n'];
            $hpx = (int) round(4 + 112 * ($n / $max));
            echo '<div title="' . esc_attr($t['d'] . ': ' . $n) . '" style="flex:1 1 0;min-width:4px;height:' . (int) $hpx . 'px;background:#4f46e5;border-radius:2px 2px 0 0;opacity:' . ($n > 0 ? '1' : '0.25') . ';"></div>';
        }
        echo '</div>';
        echo '<p class="description" style="margin-top:6px;">' . esc_html__('GMT day buckets.', 'ai-eshop-optimizer') . '</p>';
        echo '</div>';
    }

    private function render_retention_card() {
        $days = (int) get_option('aieo_chat_retention_days', 0);
        $eff  = $days > 0 ? $days : 30;
        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('History retention', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin:0 0 8px;">' . esc_html__('How many days of chat history to keep. Older conversations are pruned daily — longer retention means longer trends but more storage. Default is 30 days.', 'ai-eshop-optimizer') . '</p>';
        echo '<input type="number" min="1" max="3650" id="aieo-cac-retention" value="' . esc_attr((string) $eff) . '" class="small-text"> ';
        echo '<button type="button" class="button button-small" id="aieo-cac-retention-save">' . esc_html__('Save', 'ai-eshop-optimizer') . '</button>';
        echo ' <span id="aieo-cac-retention-status" style="color:#646970;font-size:12px;margin-left:8px;"></span>';
        echo '</div>';
    }

    private function render_cache_controls($gen) {
        $asof = '';
        if ($gen !== '') {
            
            $asof = sprintf(__('updated %s ago', 'ai-eshop-optimizer'), human_time_diff(strtotime($gen . ' UTC'), current_time('timestamp', true)));
        }
        $cadence  = self::get_stats_cadence();
        $cad_opts = array(
            'off'     => __('Off', 'ai-eshop-optimizer'),
            'hourly'  => __('Hourly', 'ai-eshop-optimizer'),
            'daily'   => __('Daily', 'ai-eshop-optimizer'),
            'weekly'  => __('Weekly', 'ai-eshop-optimizer'),
            'monthly' => __('Monthly', 'ai-eshop-optimizer'),
        );
        $sel = '<select id="aieo-cac-cadence" style="font-size:12px;height:26px;padding:0 4px;">';
        foreach ($cad_opts as $v => $l) { $sel .= '<option value="' . esc_attr($v) . '"' . selected($cadence, $v, false) . '>' . esc_html($l) . '</option>'; }
        $sel .= '</select>';
        echo '<p style="display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin:0 0 12px;">';
        echo '<button type="button" class="button button-small" id="aieo-cac-refresh">' . esc_html__('Refresh now', 'ai-eshop-optimizer') . '</button>';
        echo '<label style="font-size:12px;color:#646970;display:inline-flex;align-items:center;gap:5px;">' . esc_html__('Auto-refresh', 'ai-eshop-optimizer') . ' ' . $sel . '</label>';
        echo '<span id="aieo-cac-asof" style="color:#646970;font-size:12px;">' . esc_html($asof) . '</span>';
        echo '</p>';
    }

    
    
    

    private function render_conversations($base, $h) {
        $cid = isset($_GET['cac_cid']) ? sanitize_text_field(wp_unslash($_GET['cac_cid'])) : '';
        if ($cid !== '') { $this->render_conversation_thread($base, $h, $cid); return; }

        global $wpdb;
        $from  = isset($_GET['cac_from'])  ? sanitize_text_field(wp_unslash($_GET['cac_from']))  : '';
        $to    = isset($_GET['cac_to'])    ? sanitize_text_field(wp_unslash($_GET['cac_to']))    : '';
        $band  = isset($_GET['cac_band'])  ? sanitize_key(wp_unslash($_GET['cac_band']))         : '';
        $aud   = isset($_GET['cac_aud'])   ? sanitize_key(wp_unslash($_GET['cac_aud']))          : '';
        $model = isset($_GET['cac_model']) ? sanitize_text_field(wp_unslash($_GET['cac_model'])) : '';
        $q     = isset($_GET['cac_q'])     ? sanitize_text_field(wp_unslash($_GET['cac_q']))     : '';
        $sort  = isset($_GET['cac_sort'])  ? sanitize_key(wp_unslash($_GET['cac_sort']))         : 'new';

        $where = array('1=1');
        $params = array();
        if ($from !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $from)) { $where[] = 'created_at >= %s'; $params[] = get_gmt_from_date($from . ' 00:00:00'); }
        if ($to   !== '' && preg_match('/^\d{4}-\d{2}-\d{2}$/', $to))   { $where[] = 'created_at <= %s'; $params[] = get_gmt_from_date($to . ' 23:59:59'); }
        $bw = $this->rating_band_where($band);
        if ($bw !== '') { $where[] = $bw; }
        if ($aud === 'in')    { $where[] = 'user_id > 0'; }
        elseif ($aud === 'guest') { $where[] = '(user_id IS NULL OR user_id = 0)'; }
        if ($model !== '') { $where[] = 'model_used = %s'; $params[] = $model; }
        if ($q !== '')     { $where[] = 'user_message LIKE %s'; $params[] = '%' . $wpdb->esc_like($q) . '%'; }
        $where_sql = implode(' AND ', $where);

        $sort_map = array(
            'new'  => 'created_at DESC',
            'old'  => 'created_at ASC',
            'low'  => 'user_rating ASC, created_at DESC',
            'high' => 'user_rating DESC, created_at DESC',
        );
        $order_by = isset($sort_map[$sort]) ? $sort_map[$sort] : $sort_map['new'];

        $count_sql = "SELECT COUNT(*) FROM {$h} WHERE {$where_sql}";
        $total = (int) ($params ? $wpdb->get_var($wpdb->prepare($count_sql, $params)) : $wpdb->get_var($count_sql));

        $per    = 50;
        $pageno = isset($_GET['cac_p']) ? max(1, (int) $_GET['cac_p']) : 1;
        $offset = ($pageno - 1) * $per;

        $sql = "SELECT id, conversation_id, session_id, user_id, user_message, assistant_message, model_used, products_found, user_rating, created_at
                FROM {$h} WHERE {$where_sql} ORDER BY {$order_by} LIMIT %d OFFSET %d";
        $rows = $wpdb->get_results($wpdb->prepare($sql, array_merge($params, array($per, $offset))), ARRAY_A);

        $this->render_conversations_filter($base, compact('from', 'to', 'band', 'aud', 'model', 'q', 'sort'), $h);

        echo '<div class="aieo-dmm-card">';
        
        echo '<p class="description" style="margin-top:0;">' . esc_html(sprintf(__('%s matching messages.', 'ai-eshop-optimizer'), number_format_i18n($total))) . '</p>';
        echo '<table class="wp-list-table widefat striped"><thead><tr>';
        echo '<th style="width:130px;">' . esc_html__('When', 'ai-eshop-optimizer') . '</th>';
        echo '<th style="width:120px;">' . esc_html__('Who', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Question', 'ai-eshop-optimizer') . '</th>';
        echo '<th>' . esc_html__('Answer', 'ai-eshop-optimizer') . '</th>';
        echo '<th style="width:60px;">' . esc_html__('Products', 'ai-eshop-optimizer') . '</th>';
        echo '<th style="width:80px;">' . esc_html__('Rating', 'ai-eshop-optimizer') . '</th>';
        echo '<th style="width:80px;">' . esc_html__('Thread', 'ai-eshop-optimizer') . '</th>';
        echo '</tr></thead><tbody>';
        if (empty($rows)) {
            echo '<tr><td colspan="7" style="text-align:center;color:#646970;">' . esc_html__('No messages match these filters.', 'ai-eshop-optimizer') . '</td></tr>';
        } else {
            foreach ($rows as $r) {
                $when = date_i18n('Y-m-d H:i', strtotime($r['created_at'] . ' UTC'));
                $who  = ((int) $r['user_id'] > 0) ? $this->user_label((int) $r['user_id']) : '<span style="color:#888;">' . esc_html__('Guest', 'ai-eshop-optimizer') . '</span>';
                $pf   = json_decode((string) $r['products_found'], true);
                $pc   = is_array($pf) ? count($pf) : 0;
                $turl = esc_url(add_query_arg(array('cac_section' => 'conversations', 'cac_cid' => $r['conversation_id']), $base));
                echo '<tr>';
                echo '<td>' . esc_html($when) . '</td>';
                echo '<td>' . $who . '</td>';
                echo '<td>' . $this->expander($r['user_message']) . '</td>';
                echo '<td>' . $this->expander($r['assistant_message']) . '</td>';
                echo '<td>' . (int) $pc . '</td>';
                echo '<td>' . $this->rating_chip($r['user_rating']) . '</td>';
                echo '<td><a href="' . $turl . '" class="button button-small">' . esc_html__('View', 'ai-eshop-optimizer') . '</a></td>';
                echo '</tr>';
            }
        }
        echo '</tbody></table>';
        $this->render_pager($base, $total, $per, $pageno, array(
            'cac_section' => 'conversations', 'cac_from' => $from, 'cac_to' => $to,
            'cac_band' => $band, 'cac_aud' => $aud, 'cac_model' => $model, 'cac_q' => $q, 'cac_sort' => $sort,
        ));
        echo '</div>';
    }

    private function render_conversations_filter($base, $f, $h) {
        global $wpdb;
        $models = $wpdb->get_col("SELECT DISTINCT model_used FROM {$h} WHERE model_used <> '' ORDER BY model_used ASC");
        echo '<form method="get" class="aieo-dmm-card" style="margin-bottom:14px;">';
        echo '<input type="hidden" name="page" value="' . esc_attr(AIEO_DMM::MENU_SLUG) . '">';
        echo '<input type="hidden" name="dmm_tab" value="' . esc_attr($this->get_id()) . '">';
        echo '<input type="hidden" name="cac_section" value="conversations">';
        echo '<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:flex-end;">';
        echo '<label style="font-size:12px;">' . esc_html__('From', 'ai-eshop-optimizer') . '<br><input type="date" name="cac_from" value="' . esc_attr($f['from']) . '"></label>';
        echo '<label style="font-size:12px;">' . esc_html__('To', 'ai-eshop-optimizer') . '<br><input type="date" name="cac_to" value="' . esc_attr($f['to']) . '"></label>';
        $bands = array('' => __('Any', 'ai-eshop-optimizer'), 'happy' => __('Happy (>60)', 'ai-eshop-optimizer'), 'neutral' => __('Neutral (40–60)', 'ai-eshop-optimizer'), 'unhappy' => __('Unhappy (<40)', 'ai-eshop-optimizer'), 'unrated' => __('Unrated', 'ai-eshop-optimizer'));
        echo '<label style="font-size:12px;">' . esc_html__('Happiness', 'ai-eshop-optimizer') . '<br><select name="cac_band">';
        foreach ($bands as $v => $l) { echo '<option value="' . esc_attr($v) . '"' . selected($f['band'], $v, false) . '>' . esc_html($l) . '</option>'; }
        echo '</select></label>';
        $auds = array('' => __('All', 'ai-eshop-optimizer'), 'in' => __('Logged in', 'ai-eshop-optimizer'), 'guest' => __('Guests', 'ai-eshop-optimizer'));
        echo '<label style="font-size:12px;">' . esc_html__('Audience', 'ai-eshop-optimizer') . '<br><select name="cac_aud">';
        foreach ($auds as $v => $l) { echo '<option value="' . esc_attr($v) . '"' . selected($f['aud'], $v, false) . '>' . esc_html($l) . '</option>'; }
        echo '</select></label>';
        echo '<label style="font-size:12px;">' . esc_html__('Model', 'ai-eshop-optimizer') . '<br><select name="cac_model">';
        echo '<option value="">' . esc_html__('Any', 'ai-eshop-optimizer') . '</option>';
        foreach ((array) $models as $m) { echo '<option value="' . esc_attr($m) . '"' . selected($f['model'], $m, false) . '>' . esc_html($m) . '</option>'; }
        echo '</select></label>';
        $sorts = array('new' => __('Newest', 'ai-eshop-optimizer'), 'old' => __('Oldest', 'ai-eshop-optimizer'), 'low' => __('Lowest rating', 'ai-eshop-optimizer'), 'high' => __('Highest rating', 'ai-eshop-optimizer'));
        echo '<label style="font-size:12px;">' . esc_html__('Sort', 'ai-eshop-optimizer') . '<br><select name="cac_sort">';
        foreach ($sorts as $v => $l) { echo '<option value="' . esc_attr($v) . '"' . selected($f['sort'], $v, false) . '>' . esc_html($l) . '</option>'; }
        echo '</select></label>';
        echo '<label style="font-size:12px;flex:1 1 180px;">' . esc_html__('Search question', 'ai-eshop-optimizer') . '<br><input type="text" name="cac_q" value="' . esc_attr($f['q']) . '" style="width:100%;"></label>';
        echo '<button type="submit" class="button">' . esc_html__('Filter', 'ai-eshop-optimizer') . '</button>';
        echo '</div></form>';
    }

    private function render_conversation_thread($base, $h, $cid) {
        global $wpdb;
        $rows = $wpdb->get_results($wpdb->prepare(
            "SELECT id, session_id, user_id, user_message, assistant_message, model_used, products_found, potential_suggestions_found, user_rating, created_at
             FROM {$h} WHERE conversation_id = %s ORDER BY created_at ASC, id ASC",
            $cid
        ), ARRAY_A);

        echo '<p><a href="' . esc_url(add_query_arg(array('cac_section' => 'conversations'), $base)) . '" class="button button-small">&larr; ' . esc_html__('Back to conversations', 'ai-eshop-optimizer') . '</a></p>';
        if (empty($rows)) {
            echo '<div class="aieo-dmm-card"><p>' . esc_html__('This conversation no longer exists (it may have been pruned).', 'ai-eshop-optimizer') . '</p></div>';
            return;
        }
        $first = $rows[0];
        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Conversation', 'ai-eshop-optimizer') . ' <code style="font-size:11px;">' . esc_html($cid) . '</code></h3>';
        $who = ((int) $first['user_id'] > 0) ? $this->user_label((int) $first['user_id']) : esc_html__('Guest', 'ai-eshop-optimizer');
        echo '<p class="description">'
            . esc_html__('Who:', 'ai-eshop-optimizer') . ' ' . $who
            . ' · ' . esc_html__('Turns:', 'ai-eshop-optimizer') . ' ' . count($rows)
            . ' · ' . esc_html__('Model:', 'ai-eshop-optimizer') . ' ' . esc_html((string) $first['model_used'])
            . ' · ' . esc_html__('Session:', 'ai-eshop-optimizer') . ' <code style="font-size:11px;">' . esc_html((string) $first['session_id']) . '</code></p>';
        foreach ($rows as $r) {
            $when = date_i18n('Y-m-d H:i', strtotime($r['created_at'] . ' UTC'));
            echo '<div style="margin:14px 0;padding:12px 14px;border:1px solid #e6e6e8;border-radius:8px;">';
            echo '<div style="font-size:11px;color:#888;margin-bottom:6px;">' . esc_html($when) . ' · ' . $this->rating_chip($r['user_rating']) . '</div>';
            echo '<div style="margin-bottom:8px;"><strong>' . esc_html__('Q:', 'ai-eshop-optimizer') . '</strong> <span style="white-space:pre-wrap;">' . esc_html((string) $r['user_message']) . '</span></div>';
            echo '<div><strong>' . esc_html__('A:', 'ai-eshop-optimizer') . '</strong> <span style="white-space:pre-wrap;">' . esc_html((string) $r['assistant_message']) . '</span></div>';
            $pf = json_decode((string) $r['products_found'], true);
            if (is_array($pf) && $pf) {
                $names = array();
                foreach (array_slice($pf, 0, 12) as $pid) { $t = get_the_title((int) $pid); $names[] = ($t !== '') ? $t : ('#' . (int) $pid); }
                
                echo '<details style="margin-top:8px;"><summary style="cursor:pointer;font-size:12px;color:#646970;">' . esc_html(sprintf(__('%d products surfaced', 'ai-eshop-optimizer'), count($pf))) . '</summary><div style="font-size:12px;margin-top:4px;">' . esc_html(implode(', ', $names)) . '</div></details>';
            }
            echo '</div>';
        }
        echo '</div>';
    }

    
    
    

    private function render_happiness($base, $h) {
        global $wpdb;
        $d = $wpdb->get_row(
            "SELECT
                SUM(CASE WHEN user_rating > 60 THEN 1 ELSE 0 END)                            AS happy,
                SUM(CASE WHEN user_rating BETWEEN 40 AND 60 THEN 1 ELSE 0 END)               AS neutral,
                SUM(CASE WHEN user_rating < 40 AND user_rating IS NOT NULL THEN 1 ELSE 0 END) AS unhappy,
                SUM(CASE WHEN user_rating IS NULL THEN 1 ELSE 0 END)                          AS unrated,
                AVG(user_rating)                                                             AS avg_r,
                SUM(CASE WHEN user_rating IS NOT NULL THEN 1 ELSE 0 END)                      AS rated,
                COUNT(*)                                                                     AS total
             FROM {$h}",
            ARRAY_A
        );
        $d = is_array($d) ? $d : array();
        $happy = (int) ($d['happy'] ?? 0); $neutral = (int) ($d['neutral'] ?? 0); $unhappy = (int) ($d['unhappy'] ?? 0);
        $unrated = (int) ($d['unrated'] ?? 0); $rated = (int) ($d['rated'] ?? 0); $total = (int) ($d['total'] ?? 0);
        $avg = ($rated > 0 && isset($d['avg_r']) && $d['avg_r'] !== null) ? round((float) $d['avg_r'], 1) : null;

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Happiness', 'ai-eshop-optimizer') . '</h3>';
        echo '<div class="aieo-attr-tiles">';
        $this->tile(__('Avg rating', 'ai-eshop-optimizer'), $avg !== null ? number_format_i18n($avg, 1) . ' / 100' : '—');
        $this->tile(__('Rated answers', 'ai-eshop-optimizer'), number_format_i18n($rated) . ($total > 0 ? ' (' . round(100 * $rated / $total, 1) . '%)' : ''));
        $this->tile(__('Happy', 'ai-eshop-optimizer'),   number_format_i18n($happy));
        $this->tile(__('Neutral', 'ai-eshop-optimizer'), number_format_i18n($neutral));
        $this->tile(__('Unhappy', 'ai-eshop-optimizer'), number_format_i18n($unhappy));
        echo '</div>';

        $bands = array(
            array($happy,   '#22c55e', __('Happy (>60)', 'ai-eshop-optimizer')),
            array($neutral, '#f5b800', __('Neutral (40–60)', 'ai-eshop-optimizer')),
            array($unhappy, '#ef4444', __('Unhappy (<40)', 'ai-eshop-optimizer')),
        );
        $rated_total = $happy + $neutral + $unhappy;
        echo '<table class="widefat striped" style="margin-top:12px;"><thead><tr><th style="width:160px;">' . esc_html__('Band', 'ai-eshop-optimizer') . '</th><th>' . esc_html__('Distribution', 'ai-eshop-optimizer') . '</th><th style="width:90px;text-align:right;">' . esc_html__('Count', 'ai-eshop-optimizer') . '</th></tr></thead><tbody>';
        foreach ($bands as $bd) {
            list($n, $col, $lbl) = $bd;
            $pct = $rated_total > 0 ? round(100 * $n / $rated_total, 1) : 0;
            echo '<tr><td>' . esc_html($lbl) . '</td><td><div style="background:#f3f4f6;border-radius:4px;overflow:hidden;height:14px;"><div style="height:14px;background:' . esc_attr($col) . ';width:' . esc_attr((string) $pct) . '%;"></div></div><span style="font-size:12px;color:#1f2937;">' . esc_html((string) $pct) . '%</span></td><td style="text-align:right;">' . esc_html(number_format_i18n($n)) . '</td></tr>';
        }
        echo '</tbody></table>';
        
        echo '<p class="description" style="margin-top:6px;">' . esc_html(sprintf(__('%s answers were left unrated.', 'ai-eshop-optimizer'), number_format_i18n($unrated))) . '</p>';
        echo '</div>';

        $low = $wpdb->get_results("SELECT conversation_id, user_message, user_rating, created_at FROM {$h} WHERE user_rating IS NOT NULL ORDER BY user_rating ASC, created_at DESC LIMIT 25", ARRAY_A);
        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Lowest-rated answers', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Where shoppers were least happy — review these to improve answers or catalogue coverage.', 'ai-eshop-optimizer') . '</p>';
        if (empty($low)) {
            echo '<p style="color:#646970;">' . esc_html__('No ratings yet.', 'ai-eshop-optimizer') . '</p>';
        } else {
            echo '<table class="wp-list-table widefat striped"><thead><tr><th style="width:80px;">' . esc_html__('Rating', 'ai-eshop-optimizer') . '</th><th>' . esc_html__('Question', 'ai-eshop-optimizer') . '</th><th style="width:130px;">' . esc_html__('When', 'ai-eshop-optimizer') . '</th><th style="width:80px;">' . esc_html__('Thread', 'ai-eshop-optimizer') . '</th></tr></thead><tbody>';
            foreach ($low as $r) {
                $when = date_i18n('Y-m-d H:i', strtotime($r['created_at'] . ' UTC'));
                $turl = esc_url(add_query_arg(array('cac_section' => 'conversations', 'cac_cid' => $r['conversation_id']), $base));
                echo '<tr><td>' . $this->rating_chip($r['user_rating']) . '</td><td>' . $this->expander($r['user_message']) . '</td><td>' . esc_html($when) . '</td><td><a class="button button-small" href="' . $turl . '">' . esc_html__('View', 'ai-eshop-optimizer') . '</a></td></tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';
    }

    
    
    

    private function render_origins($base, $h) {
        global $wpdb;
        $se = $wpdb->prefix . 'aieo_sessions';
        $ss = $wpdb->prefix . 'aieo_sessions_statics';
        $se_exists = $this->table_exists($se);
        $ss_exists = $this->table_exists($ss);

        if (!$se_exists && !$ss_exists) {
            echo '<div class="aieo-dmm-card"><p>' . esc_html__('Page origins come from the Session Tracker, which isn’t active yet. Enable Session Tracking (Customer Profiling → User Vitals) to see where shoppers start chats.', 'ai-eshop-optimizer') . '</p></div>';
            return;
        }

        $rows = array();
        if ($se_exists) {
            $rows = $wpdb->get_results("SELECT page_url, COUNT(*) AS n FROM {$se} WHERE event_type IN ('chat_open','chat_message') AND page_url <> '' GROUP BY page_url ORDER BY n DESC LIMIT 500", ARRAY_A);
        }
        $buckets = array(); $urls = array(); $total = 0;
        foreach ((array) $rows as $r) {
            $n = (int) $r['n']; $total += $n;
            $b = $this->classify_origin($r['page_url']);
            $buckets[$b] = isset($buckets[$b]) ? $buckets[$b] + $n : $n;
            $urls[] = array('url' => $r['page_url'], 'n' => $n);
        }

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Where shoppers start chats', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Recorded by the Session Tracker when a shopper opens the chat or sends a message.', 'ai-eshop-optimizer') . '</p>';
        if ($total === 0) {
            echo '<p style="color:#646970;">' . esc_html__('No chat-origin events recorded yet — they start accruing once shoppers chat with Session Tracking on. The fallback below uses each chat session’s landing page in the meantime.', 'ai-eshop-optimizer') . '</p>';
        } else {
            arsort($buckets);
            echo '<table class="widefat striped"><thead><tr><th>' . esc_html__('Page type', 'ai-eshop-optimizer') . '</th><th>' . esc_html__('Share', 'ai-eshop-optimizer') . '</th><th style="width:90px;text-align:right;">' . esc_html__('Chats', 'ai-eshop-optimizer') . '</th></tr></thead><tbody>';
            foreach ($buckets as $b => $n) {
                $pct = $total > 0 ? round(100 * $n / $total, 1) : 0;
                echo '<tr><td>' . esc_html($this->origin_label($b)) . '</td><td><div style="background:#f3f4f6;border-radius:4px;overflow:hidden;height:14px;max-width:260px;"><div style="height:14px;background:#4f46e5;width:' . esc_attr((string) $pct) . '%;"></div></div><span style="font-size:12px;color:#1f2937;">' . esc_html((string) $pct) . '%</span></td><td style="text-align:right;">' . esc_html(number_format_i18n($n)) . '</td></tr>';
            }
            echo '</tbody></table>';
            echo '<h4 style="margin:14px 0 6px;">' . esc_html__('Top pages', 'ai-eshop-optimizer') . '</h4>';
            echo '<table class="widefat striped aieo-attr-sortable-table"><thead><tr><th data-sort-type="text">' . esc_html__('URL', 'ai-eshop-optimizer') . ' <span class="aieo-attr-dt-sort-ind">⇅</span></th><th data-sort-type="num">' . esc_html__('Chats', 'ai-eshop-optimizer') . ' <span class="aieo-attr-dt-sort-ind">⇅</span></th></tr></thead><tbody>';
            foreach (array_slice($urls, 0, 20) as $u) {
                echo '<tr><td data-sort-value="' . esc_attr($u['url']) . '"><code style="font-size:11px;">' . esc_html($u['url']) . '</code></td><td data-sort-value="' . (int) $u['n'] . '">' . esc_html(number_format_i18n((int) $u['n'])) . '</td></tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';

        if ($ss_exists) {
            $this->render_origin_fallback($h, $ss);
        }
    }

    private function render_origin_fallback($h, $ss) {
        global $wpdb;
        $cast = $this->collation_cast($h, $ss, 'session_id');
        $wpdb->suppress_errors(true);
        $rows = $wpdb->get_results(
            "SELECT ss.landing_page AS url, COUNT(DISTINCT ss.session_id) AS n
             FROM (SELECT DISTINCT session_id FROM {$h} WHERE session_id <> '') ch
             JOIN {$ss} ss ON ss.session_id = ch.session_id{$cast}
             WHERE ss.landing_page <> ''
             GROUP BY ss.landing_page ORDER BY n DESC LIMIT 300",
            ARRAY_A
        );
        $wpdb->suppress_errors(false);
        $buckets = array(); $total = 0;
        foreach ((array) $rows as $r) { $n = (int) $r['n']; $total += $n; $b = $this->classify_origin($r['url']); $buckets[$b] = isset($buckets[$b]) ? $buckets[$b] + $n : $n; }

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Chat session landing pages', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Where chat sessions first landed on the site — covers chats from before per-chat origin tracking, approximated by the session’s entry page.', 'ai-eshop-optimizer') . '</p>';
        if ($total === 0) {
            echo '<p style="color:#646970;">' . esc_html__('No linked session data yet.', 'ai-eshop-optimizer') . '</p>';
        } else {
            arsort($buckets);
            echo '<table class="widefat striped"><thead><tr><th>' . esc_html__('Page type', 'ai-eshop-optimizer') . '</th><th>' . esc_html__('Share', 'ai-eshop-optimizer') . '</th><th style="width:90px;text-align:right;">' . esc_html__('Sessions', 'ai-eshop-optimizer') . '</th></tr></thead><tbody>';
            foreach ($buckets as $b => $n) {
                $pct = $total > 0 ? round(100 * $n / $total, 1) : 0;
                echo '<tr><td>' . esc_html($this->origin_label($b)) . '</td><td><div style="background:#f3f4f6;border-radius:4px;overflow:hidden;height:14px;max-width:260px;"><div style="height:14px;background:#10b981;width:' . esc_attr((string) $pct) . '%;"></div></div><span style="font-size:12px;color:#1f2937;">' . esc_html((string) $pct) . '%</span></td><td style="text-align:right;">' . esc_html(number_format_i18n($n)) . '</td></tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';
    }

    
    
    

    private function render_products($base, $h) {
        global $wpdb;
        $cache    = class_exists('AIEO_Chat_Analytics') ? AIEO_Chat_Analytics::get_cached_stats() : null;
        $products = ($cache && isset($cache['products'])) ? (array) $cache['products'] : null;
        $gen      = ($cache && !empty($cache['generated_at'])) ? (string) $cache['generated_at'] : '';

        $this->render_cache_controls($gen);

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Most-recommended products', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Products the assistant surfaced most often across all chats (precomputed).', 'ai-eshop-optimizer') . '</p>';
        if ($products === null) {
            echo '<p class="description aieo-cac-needs-build">' . esc_html__('Preparing… building in the background.', 'ai-eshop-optimizer') . '</p>';
        } elseif (empty($products)) {
            echo '<p style="color:#646970;">' . esc_html__('No products surfaced in chats yet.', 'ai-eshop-optimizer') . '</p>';
        } else {
            echo '<table class="widefat striped aieo-attr-sortable-table"><thead><tr>';
            echo '<th style="width:50px;">#</th>';
            echo '<th data-sort-type="text">' . esc_html__('Product', 'ai-eshop-optimizer') . ' <span class="aieo-attr-dt-sort-ind">⇅</span></th>';
            echo '<th data-sort-type="num">' . esc_html__('Times recommended', 'ai-eshop-optimizer') . ' <span class="aieo-attr-dt-sort-ind">⇅</span></th>';
            echo '</tr></thead><tbody>';
            foreach ($products as $i => $p) {
                $pid  = (int) $p['post_id'];
                $name = (string) $p['title'];
                $edit = get_edit_post_link($pid);
                echo '<tr><td>' . (int) ($i + 1) . '</td>';
                echo '<td data-sort-value="' . esc_attr($name) . '">';
                echo $edit ? '<a href="' . esc_url($edit) . '">' . esc_html($name) . '</a>' : esc_html($name);
                echo ' <small style="color:#888;">#' . (int) $pid . '</small></td>';
                echo '<td data-sort-value="' . (int) $p['recommended'] . '">' . esc_html(number_format_i18n((int) $p['recommended'])) . '</td></tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';

        
        $rows = $wpdb->get_results("SELECT conversation_id, user_message, user_rating, created_at FROM {$h} WHERE (products_found IS NULL OR products_found = '' OR products_found = '[]') ORDER BY created_at DESC LIMIT 50", ARRAY_A);
        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Questions that returned no products', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Catalogue / answer gaps — questions where the assistant found nothing to recommend. Good candidates for new products, better descriptions, or business-info entries.', 'ai-eshop-optimizer') . '</p>';
        if (empty($rows)) {
            echo '<p style="color:#646970;">' . esc_html__('None — every answer surfaced at least one product.', 'ai-eshop-optimizer') . '</p>';
        } else {
            echo '<table class="wp-list-table widefat striped"><thead><tr><th style="width:130px;">' . esc_html__('When', 'ai-eshop-optimizer') . '</th><th>' . esc_html__('Question', 'ai-eshop-optimizer') . '</th><th style="width:80px;">' . esc_html__('Rating', 'ai-eshop-optimizer') . '</th><th style="width:80px;">' . esc_html__('Thread', 'ai-eshop-optimizer') . '</th></tr></thead><tbody>';
            foreach ($rows as $r) {
                $when = date_i18n('Y-m-d H:i', strtotime($r['created_at'] . ' UTC'));
                $turl = esc_url(add_query_arg(array('cac_section' => 'conversations', 'cac_cid' => $r['conversation_id']), $base));
                echo '<tr><td>' . esc_html($when) . '</td><td>' . $this->expander($r['user_message']) . '</td><td>' . $this->rating_chip($r['user_rating']) . '</td><td><a class="button button-small" href="' . $turl . '">' . esc_html__('View', 'ai-eshop-optimizer') . '</a></td></tr>';
            }
            echo '</tbody></table>';
        }
        echo '</div>';
    }

    
    
    

    private function render_conversions($base, $h) {
        unset($base, $h);
        $cache = class_exists('AIEO_Chat_Analytics') ? AIEO_Chat_Analytics::get_cached_stats() : null;
        $c     = ($cache && isset($cache['conversions'])) ? (array) $cache['conversions'] : null;
        $gen   = ($cache && !empty($cache['generated_at'])) ? (string) $cache['generated_at'] : '';

        $this->render_cache_controls($gen);

        echo '<div class="aieo-dmm-card">';
        echo '<h3>' . esc_html__('Chat-assisted conversions', 'ai-eshop-optimizer') . '</h3>';
        echo '<p class="description" style="margin-top:0;">' . esc_html__('Sessions where a shopper used the AI chat AND placed an order. Session-coincidence attribution (the chat was part of the journey), not last-click — computed in the background from the Session Tracker, never on page load.', 'ai-eshop-optimizer') . '</p>';
        if ($c === null) {
            echo '<p class="description aieo-cac-needs-build">' . esc_html__('Preparing… building in the background.', 'ai-eshop-optimizer') . '</p>';
        } elseif (empty($c['available'])) {
            echo '<p style="color:#646970;">' . esc_html__('Session Tracking isn’t active yet, so order data can’t be linked to chats. Enable Session Tracking to see chat-assisted conversions.', 'ai-eshop-optimizer') . '</p>';
        } else {
            $cur = function_exists('get_woocommerce_currency_symbol') ? get_woocommerce_currency_symbol() : '';
            echo '<div class="aieo-attr-tiles">';
            $this->tile(__('Chat sessions', 'ai-eshop-optimizer'),    number_format_i18n((int) $c['chat_sessions']));
            $this->tile(__('Converted', 'ai-eshop-optimizer'),        number_format_i18n((int) $c['converted']));
            $this->tile(__('Conversion rate', 'ai-eshop-optimizer'),  number_format_i18n((float) $c['rate'], 1) . '%');
            $this->tile(__('Assisted revenue', 'ai-eshop-optimizer'), $cur . number_format_i18n((float) $c['revenue'], 2));
            $this->tile(__('Avg order value', 'ai-eshop-optimizer'),  $cur . number_format_i18n((float) $c['aov'], 2));
            echo '</div>';
        }
        echo '</div>';
    }

    
    
    

    private function tile($label, $value) {
        echo '<div class="aieo-attr-tile"><div class="aieo-attr-tile-label">' . esc_html($label) . '</div><div class="aieo-attr-tile-value">' . esc_html((string) $value) . '</div></div>';
    }

    
    private function rating_band_where($band) {
        switch ($band) {
            case 'happy':   return 'user_rating > 60';
            case 'neutral': return 'user_rating BETWEEN 40 AND 60';
            case 'unhappy': return 'user_rating < 40 AND user_rating IS NOT NULL';
            case 'unrated': return 'user_rating IS NULL';
            default:        return '';
        }
    }

    
    private function rating_chip($rating) {
        if ($rating === null || $rating === '') {
            return '<span style="color:#9ca3af;font-size:12px;">—</span>';
        }
        $r = (int) $rating;
        if ($r > 60)      { $bg = '#dcfce7'; $fg = '#166534'; }
        elseif ($r >= 40) { $bg = '#fef9c3'; $fg = '#854d0e'; }
        else              { $bg = '#fee2e2'; $fg = '#991b1b'; }
        return '<span style="display:inline-block;padding:1px 8px;border-radius:10px;font-size:12px;font-weight:600;background:' . esc_attr($bg) . ';color:' . esc_attr($fg) . ';">' . (int) $r . '</span>';
    }

    
    private function expander($text) {
        $plain = trim(wp_strip_all_tags((string) $text));
        if ($plain === '') { return '<span style="color:#9ca3af;">—</span>'; }
        if (mb_strlen($plain) <= 90) {
            return '<span>' . esc_html($plain) . '</span>';
        }
        $short = wp_trim_words($plain, 16, '…');
        return '<details><summary style="cursor:pointer;">' . esc_html($short) . '</summary><div style="margin-top:6px;white-space:pre-wrap;">' . esc_html($plain) . '</div></details>';
    }

    
    private function user_label($uid) {
        $u = get_user_by('id', $uid);
        if (!$u) { return '<span style="color:#888;">#' . (int) $uid . '</span>'; }
        $name = $u->display_name ? $u->display_name : $u->user_login;
        $edit = get_edit_user_link($uid);
        return $edit ? '<a href="' . esc_url($edit) . '">' . esc_html($name) . '</a>' : esc_html($name);
    }

    private function render_pager($base, $total, $per, $pageno, $args) {
        $pages = (int) ceil($total / max(1, $per));
        if ($pages <= 1) { return; }
        echo '<p style="margin-top:10px;">';
        $shown = min($pages, 12);
        for ($i = 1; $i <= $shown; $i++) {
            $url = esc_url(add_query_arg(array_merge($args, array('cac_p' => $i)), $base));
            if ($i === $pageno) { echo '<strong style="margin:0 4px;">' . (int) $i . '</strong>'; }
            else { echo '<a href="' . $url . '" style="margin:0 4px;">' . (int) $i . '</a>'; }
        }
        
        if ($pages > $shown) { echo '<span style="color:#646970;"> … ' . esc_html(sprintf(__('of %d', 'ai-eshop-optimizer'), $pages)) . '</span>'; }
        echo '</p>';
    }

    private function classify_origin($url) {
        $path = strtolower((string) wp_parse_url((string) $url, PHP_URL_PATH));
        if ($path === '' || $path === '/') { return 'home'; }
        if (strpos($path, '/product/') !== false)          { return 'product'; }
        if (strpos($path, '/product-category/') !== false
            || strpos($path, '/brand') !== false
            || strpos($path, '/need') !== false)           { return 'category'; }
        if (strpos($path, '/checkout') !== false)          { return 'checkout'; }
        if (strpos($path, '/cart') !== false)              { return 'cart'; }
        if (strpos($path, '/shop') !== false)              { return 'shop'; }
        if (strpos($path, '/my-account') !== false)        { return 'account'; }
        if (strpos($path, '/blog') !== false
            || strpos($path, '/category/') !== false
            || strpos($path, '/tag/') !== false)           { return 'blog'; }
        return 'other';
    }

    private function origin_label($b) {
        $m = array(
            'home'     => __('Home', 'ai-eshop-optimizer'),
            'product'  => __('Product page', 'ai-eshop-optimizer'),
            'category' => __('Category / brand / need', 'ai-eshop-optimizer'),
            'checkout' => __('Checkout', 'ai-eshop-optimizer'),
            'cart'     => __('Cart', 'ai-eshop-optimizer'),
            'shop'     => __('Shop', 'ai-eshop-optimizer'),
            'account'  => __('My account', 'ai-eshop-optimizer'),
            'blog'     => __('Blog', 'ai-eshop-optimizer'),
            'other'    => __('Other', 'ai-eshop-optimizer'),
        );
        return isset($m[$b]) ? $m[$b] : $b;
    }

    private function chat_table() { global $wpdb; return $wpdb->prefix . 'aieo_chat_history'; }

    private function table_exists($name) {
        global $wpdb;
        static $cache = array();
        if (!array_key_exists($name, $cache)) {
            $cache[$name] = ((string) $wpdb->get_var($wpdb->prepare('SHOW TABLES LIKE %s', $name)) === $name);
        }
        return $cache[$name];
    }

    
    private function collation_cast($table_a, $table_b, $col) {
        $a = $this->column_collation($table_a, $col);
        $b = $this->column_collation($table_b, $col);
        if ($a !== '' && $b !== '' && $a !== $b && preg_match('/^[A-Za-z0-9_]+$/', $b)) {
            return ' COLLATE ' . $b;
        }
        return '';
    }

    private function column_collation($table, $col) {
        global $wpdb;
        $v = $wpdb->get_var($wpdb->prepare(
            "SELECT COLLATION_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = %s AND TABLE_NAME = %s AND COLUMN_NAME = %s",
            DB_NAME, $table, $col
        ));
        return $v ? (string) $v : '';
    }
}
