<?php
if (!defined('ABSPATH')) exit;
$nonce = wp_create_nonce('af_stats_admin');
$export_base = admin_url('admin-ajax.php?action=af_stats_export&nonce=' . $nonce);
// Chart.js is bundled with the plugin (no CDN dependency / version drift).
$af_chart_js = plugins_url('admin/assets/js/chart.umd.min.js', dirname(__DIR__, 3) . '/auctionforge.php');
if (defined('AUCTIONFORGE_VERSION')) { $af_chart_js = add_query_arg('ver', AUCTIONFORGE_VERSION, $af_chart_js); }
?>
<div class="wrap af-stats-wrap">
    <h1 style="display:flex;align-items:center;gap:10px;">
        <span class="dashicons dashicons-chart-area" style="font-size:28px;width:28px;height:28px;"></span>
        Site Statistics
    </h1>

    <!-- Tab Navigation -->
    <nav class="nav-tab-wrapper af-stats-tabs" style="margin-bottom:20px;">
        <a href="#" class="nav-tab nav-tab-active" data-tab="dashboard">Dashboard</a>
        <a href="#" class="nav-tab" data-tab="pages">Pages</a>
        <a href="#" class="nav-tab" data-tab="referrers">Referrers</a>
        <a href="#" class="nav-tab" data-tab="countries">Countries</a>
        <a href="#" class="nav-tab" data-tab="technology">Technology</a>
        <a href="#" class="nav-tab" data-tab="searches">Searches</a>
        <a href="#" class="nav-tab" data-tab="errors">404 Errors</a>
        <a href="#" class="nav-tab" data-tab="realtime">Real-Time</a>
        <a href="#" class="nav-tab" data-tab="lot-analytics">Lot Analytics</a>
        <a href="#" class="nav-tab" data-tab="settings">Settings</a>
    </nav>

    <!-- Date Range Picker -->
    <div class="af-stats-toolbar" style="display:flex;gap:10px;align-items:center;margin-bottom:20px;flex-wrap:wrap;">
        <select id="af-stats-preset" style="padding:4px 8px;">
            <option value="7">Last 7 days</option>
            <option value="14">Last 14 days</option>
            <option value="30" selected>Last 30 days</option>
            <option value="90">Last 90 days</option>
            <option value="365">Last 12 months</option>
            <option value="custom">Custom Range</option>
        </select>
        <input type="date" id="af-stats-from" style="padding:4px 8px;" />
        <span>to</span>
        <input type="date" id="af-stats-to" style="padding:4px 8px;" />
        <button id="af-stats-refresh" class="button button-primary">
            <span class="dashicons dashicons-update" style="vertical-align:middle;margin-top:-2px;"></span> Refresh
        </button>
        <span id="af-stats-loading" style="display:none;color:#666;">
            <span class="spinner is-active" style="float:none;margin:0 5px 0 0;"></span> Loading...
        </span>
    </div>

    <!-- Dashboard Tab -->
    <div class="af-stats-tab-content" id="tab-dashboard">
        <!-- KPI Cards -->
        <div class="af-stats-cards" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:15px;margin-bottom:25px;">
            <div class="af-stats-card">
                <div class="af-card-label">Visitors</div>
                <div class="af-card-value" id="kpi-visitors">-</div>
                <div class="af-card-change" id="kpi-visitors-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">New Visitors</div>
                <div class="af-card-value" id="kpi-new-visitors">-</div>
                <div class="af-card-change" id="kpi-new-visitors-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Returning Visitors</div>
                <div class="af-card-value" id="kpi-returning-visitors">-</div>
                <div class="af-card-change" id="kpi-returning-visitors-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Sessions</div>
                <div class="af-card-value" id="kpi-sessions">-</div>
                <div class="af-card-change" id="kpi-sessions-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Pageviews</div>
                <div class="af-card-value" id="kpi-pageviews">-</div>
                <div class="af-card-change" id="kpi-pageviews-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Bounce Rate</div>
                <div class="af-card-value" id="kpi-bounce">-</div>
                <div class="af-card-change" id="kpi-bounce-change"></div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Avg. Duration</div>
                <div class="af-card-value" id="kpi-duration">-</div>
            </div>
            <div class="af-stats-card">
                <div class="af-card-label">Pages / Session</div>
                <div class="af-card-value" id="kpi-pps">-</div>
            </div>
        </div>

        <!-- Charts Row 1 -->
        <div style="display:grid;grid-template-columns:2fr 1fr;gap:20px;margin-bottom:25px;">
            <div class="af-stats-panel">
                <h3>Traffic Over Time</h3>
                <div style="position:relative;height:280px;"><canvas id="chart-traffic"></canvas></div>
                <div id="traffic-auctions-note" style="font-size:11px;color:#888;margin-top:6px;"></div>
            </div>
            <div class="af-stats-panel">
                <h3>Traffic Channels</h3>
                <div style="position:relative;height:280px;"><canvas id="chart-channels"></canvas></div>
            </div>
        </div>

        <!-- Charts Row 2 -->
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:25px;">
            <div class="af-stats-panel">
                <h3>Hourly Distribution</h3>
                <div class="af-dow-tabs" id="hourly-dow-tabs"></div>
                <div style="position:relative;height:220px;"><canvas id="chart-hourly"></canvas></div>
            </div>
            <div class="af-stats-panel">
                <h3>Devices</h3>
                <div style="position:relative;height:220px;"><canvas id="chart-devices"></canvas></div>
            </div>
        </div>

        <!-- Funnel Row -->
        <div style="margin-bottom:25px;">
            <div class="af-stats-panel">
                <h3>Engagement Funnel</h3>
                <div id="dash-funnel"></div>
                <p style="font-size:11px;color:#888;margin-top:10px;">Stages 1–3 are unique visitors measured from site analytics (each a subset of the one above). Bidders is counted differently — unique people identified from Bidspirit bid and lot-alert notifications — so it is not a like-for-like conversion of the stage above, and it includes bidders who used the Bidspirit app or live room without a tracked site visit. It shows “not tracked” until Bidspirit notifications have been received.</p>
            </div>
        </div>

        <!-- Tables Row -->
        <div style="display:grid;grid-template-columns:1fr 1fr 1fr;gap:20px;margin-bottom:25px;">
            <div class="af-stats-panel">
                <h3>Top Lots</h3>
                <table class="wp-list-table widefat fixed striped" id="dash-top-pages">
                    <thead><tr><th>Lot</th><th style="width:60px;">Views</th></tr></thead>
                    <tbody></tbody>
                </table>
            </div>
            <div class="af-stats-panel">
                <h3>Top Referrers</h3>
                <table class="wp-list-table widefat fixed striped" id="dash-top-referrers">
                    <thead><tr><th>Referrer</th><th style="width:60px;">Sessions</th></tr></thead>
                    <tbody></tbody>
                </table>
            </div>
            <div class="af-stats-panel">
                <h3>Top Countries</h3>
                <table class="wp-list-table widefat fixed striped" id="dash-top-countries">
                    <thead><tr><th>Country</th><th style="width:70px;">Visitors</th></tr></thead>
                    <tbody></tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Pages Tab -->
    <div class="af-stats-tab-content" id="tab-pages" style="display:none;">
        <div style="display:flex;gap:10px;margin-bottom:15px;align-items:center;">
            <input type="text" id="pages-search" placeholder="Search pages..." style="width:300px;padding:6px 10px;" />
            <button class="button" id="pages-search-btn">Search</button>
            <a id="pages-export" href="#" class="button">Export CSV</a>
        </div>
        <table class="wp-list-table widefat fixed striped">
            <thead><tr>
                <th>URL</th><th>Title</th><th style="width:80px;">Views</th>
                <th style="width:80px;">Visitors</th><th style="width:90px;">Avg Time</th>
            </tr></thead>
            <tbody id="pages-tbody"></tbody>
        </table>
        <div id="pages-pagination" style="margin-top:10px;display:flex;gap:10px;align-items:center;">
            <button class="button" id="pages-prev" disabled>&laquo; Prev</button>
            <span id="pages-info"></span>
            <button class="button" id="pages-next" disabled>Next &raquo;</button>
        </div>
    </div>

    <!-- Referrers Tab -->
    <div class="af-stats-tab-content" id="tab-referrers" style="display:none;">
        <div style="margin-bottom:15px;">
            <a id="referrers-export" href="#" class="button">Export CSV</a>
        </div>
        <table class="wp-list-table widefat fixed striped">
            <thead><tr>
                <th>Referrer</th><th style="width:100px;">Channel</th><th style="width:80px;">Sessions</th>
                <th style="width:90px;">Pageviews</th><th style="width:100px;">Avg Duration</th>
                <th style="width:100px;">Bounce Rate</th>
            </tr></thead>
            <tbody id="referrers-tbody"></tbody>
        </table>
        <div id="referrers-pagination" style="margin-top:10px;display:flex;gap:10px;align-items:center;">
            <button class="button" id="referrers-prev" disabled>&laquo; Prev</button>
            <span id="referrers-info"></span>
            <button class="button" id="referrers-next" disabled>Next &raquo;</button>
        </div>
    </div>

    <!-- Countries Tab -->
    <div class="af-stats-tab-content" id="tab-countries" style="display:none;">
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;">
            <div class="af-stats-panel">
                <h3>Visitors by Country</h3>
                <div style="position:relative;height:300px;"><canvas id="chart-countries"></canvas></div>
            </div>
            <div>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Country</th><th style="width:80px;">Visitors</th><th style="width:90px;">Pageviews</th></tr></thead>
                    <tbody id="countries-tbody"></tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Technology Tab -->
    <div class="af-stats-tab-content" id="tab-technology" style="display:none;">
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;">
            <div>
                <h3>Browsers &amp; Devices</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Browser</th><th>OS</th><th>Device</th><th style="width:70px;">Visitors</th></tr></thead>
                    <tbody id="tech-browsers-tbody"></tbody>
                </table>
            </div>
            <div>
                <h3>Screen Resolutions</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Resolution</th><th style="width:70px;">Visitors</th></tr></thead>
                    <tbody id="tech-screens-tbody"></tbody>
                </table>
            </div>
        </div>
    </div>

    <!-- Searches Tab -->
    <div class="af-stats-tab-content" id="tab-searches" style="display:none;">
        <table class="wp-list-table widefat fixed striped">
            <thead><tr><th>Search Query</th><th style="width:100px;">Type</th><th style="width:70px;">Count</th><th style="width:150px;">Last Searched</th></tr></thead>
            <tbody id="searches-tbody"></tbody>
        </table>
    </div>

    <!-- 404 Errors Tab -->
    <div class="af-stats-tab-content" id="tab-errors" style="display:none;">
        <table class="wp-list-table widefat fixed striped">
            <thead><tr><th>URL</th><th>Referrer</th><th style="width:60px;">Hits</th><th style="width:130px;">First Seen</th><th style="width:130px;">Last Seen</th></tr></thead>
            <tbody id="errors-tbody"></tbody>
        </table>
    </div>

    <!-- Real-Time Tab -->
    <div class="af-stats-tab-content" id="tab-realtime" style="display:none;">
        <div class="af-stats-cards" style="display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:15px;margin-bottom:20px;">
            <div class="af-stats-card" style="border-left:4px solid #00a32a;">
                <div class="af-card-label">Active Visitors (5 min)</div>
                <div class="af-card-value" id="rt-active" style="font-size:36px;">0</div>
            </div>
        </div>
        <h3>Recent Pageviews</h3>
        <table class="wp-list-table widefat fixed striped">
            <thead><tr><th>Page</th><th style="width:80px;">Country</th><th style="width:80px;">Browser</th><th style="width:80px;">Device</th><th style="width:130px;">Time</th></tr></thead>
            <tbody id="rt-tbody"></tbody>
        </table>
        <p style="color:#666;font-size:12px;">Auto-refreshes every 10 seconds.</p>
    </div>

    <!-- Lot Analytics Tab -->
    <div class="af-stats-tab-content" id="tab-lot-analytics" style="display:none;">
        <?php
        $settings = get_option('bidspirit_settings', array());
        $lotAnalyticsEnabled = isset($settings['enable_lot_analytics']) ? $settings['enable_lot_analytics'] : 'off';
        ?>
        <?php if ($lotAnalyticsEnabled !== 'on'): ?>
            <div class="notice notice-warning" style="margin:0 0 15px;"><p>Lot Analytics is currently <strong>disabled</strong>. Enable it in <strong>AuctionForge &gt; Settings</strong> to start tracking lot views and favorites.</p></div>
        <?php endif; ?>

        <div style="display:flex;gap:10px;margin-bottom:15px;flex-wrap:wrap;align-items:center;">
            <select id="la-auction-filter" style="min-width:250px;">
                <option value="">All Catalogues</option>
            </select>
            <button class="button button-primary" id="la-refresh">Refresh Data</button>
            <button class="button" id="la-backfill">Backfill from Pageviews</button>
            <span id="la-status" style="line-height:30px;color:#666;"></span>
        </div>

        <!-- Auction Stats -->
        <div class="af-stats-panel" style="margin-bottom:20px;">
            <h3>Auction Performance</h3>
            <table class="wp-list-table widefat fixed striped" id="la-auctions-table">
                <thead><tr>
                    <th>Auction</th>
                    <th style="width:100px;">Date</th>
                    <th style="width:75px;">Status</th>
                    <th style="width:90px;">Total Views</th>
                    <th style="width:100px;">Total Favorites</th>
                    <th style="width:80px;">Lots</th>
                    <th style="width:100px;">Avg Views/Lot</th>
                </tr></thead>
                <tbody id="la-auctions-tbody"><tr><td colspan="7" style="text-align:center;color:#666;">Click "Refresh Data" to load</td></tr></tbody>
            </table>
        </div>

        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px;">
            <!-- Most Viewed -->
            <div class="af-stats-panel">
                <h3>Most Viewed Lots (All Time)</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Lot</th><th style="width:60px;">Views</th><th style="width:70px;">Unique</th><th style="width:60px;">Favs</th></tr></thead>
                    <tbody id="la-most-viewed-tbody"><tr><td colspan="4" style="text-align:center;color:#666;">—</td></tr></tbody>
                </table>
            </div>
            <!-- Most Favorited -->
            <div class="af-stats-panel">
                <h3>Most Favorited Lots</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Lot</th><th style="width:60px;">Favs</th><th style="width:60px;">Views</th></tr></thead>
                    <tbody id="la-most-fav-tbody"><tr><td colspan="3" style="text-align:center;color:#666;">—</td></tr></tbody>
                </table>
            </div>
        </div>

        <!-- Trending -->
        <div class="af-stats-panel" style="margin-bottom:20px;">
            <h3>Trending Lots (Last 7 Days)</h3>
            <table class="wp-list-table widefat fixed striped">
                <thead><tr><th>Lot</th><th>Auction</th><th style="width:90px;">Recent Views</th><th style="width:100px;">Unique Visitors</th></tr></thead>
                <tbody id="la-trending-tbody"><tr><td colspan="4" style="text-align:center;color:#666;">—</td></tr></tbody>
            </table>
        </div>

        <!-- Conversion Tracking -->
        <div class="af-stats-panel" style="margin-bottom:20px;">
            <h3>Conversion Tracking (Views → Bids/Sales)</h3>
            <div style="display:flex;gap:15px;margin-bottom:12px;" id="la-conversion-summary"></div>
            <table class="wp-list-table widefat fixed striped">
                <thead><tr>
                    <th>Lot</th>
                    <th style="width:60px;">Views</th>
                    <th style="width:70px;">Cat. Click</th>
                    <th style="width:70px;">Ext. Click</th>
                    <th style="width:50px;">Favs</th>
                    <th style="width:55px;">Shares</th>
                    <th style="width:65px;">Status</th>
                    <th style="width:70px;">Sold Price</th>
                </tr></thead>
                <tbody id="la-conversion-tbody"><tr><td colspan="8" style="text-align:center;color:#666;">—</td></tr></tbody>
            </table>
        </div>

        <!-- Peak Viewing Times + Pre-sale vs Live -->
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px;">
            <div class="af-stats-panel">
                <h3>Peak Viewing Times</h3>
                <div class="af-dow-tabs" id="la-peak-dow-tabs"></div>
                <div style="position:relative;height:220px;"><canvas id="la-heatmap-chart"></canvas></div>
                <p id="la-peak-summary" style="font-size:12px;color:#666;margin-top:8px;"></p>
            </div>
            <div class="af-stats-panel">
                <h3>Pre-Sale vs Live Views</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Auction</th><th style="width:80px;">Pre-Sale</th><th style="width:60px;">Live</th><th style="width:60px;">Total</th><th style="width:70px;">Pre %</th></tr></thead>
                    <tbody id="la-presale-tbody"><tr><td colspan="5" style="text-align:center;color:#666;">—</td></tr></tbody>
                </table>
            </div>
        </div>

        <!-- Category Analytics + Shares -->
        <div style="display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px;">
            <div class="af-stats-panel">
                <h3>Category Performance</h3>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Category</th><th style="width:55px;">Views</th><th style="width:45px;">Lots</th><th style="width:45px;">Favs</th><th style="width:45px;">Sold</th><th style="width:60px;">Avg Views</th></tr></thead>
                    <tbody id="la-categories-tbody"><tr><td colspan="6" style="text-align:center;color:#666;">—</td></tr></tbody>
                </table>
            </div>
            <div class="af-stats-panel">
                <h3>Share Analytics</h3>
                <div id="la-share-channels" style="margin-bottom:12px;"></div>
                <h4 style="font-size:13px;margin:8px 0 4px;">Most Shared Lots</h4>
                <table class="wp-list-table widefat fixed striped">
                    <thead><tr><th>Lot</th><th style="width:55px;">Shares</th><th style="width:100px;">Channels</th></tr></thead>
                    <tbody id="la-shares-tbody"><tr><td colspan="3" style="text-align:center;color:#666;">—</td></tr></tbody>
                </table>
            </div>
        </div>

        <!-- Search Funnel -->
        <div class="af-stats-panel" style="margin-bottom:20px;">
            <h3>Search → View Funnel</h3>
            <table class="wp-list-table widefat fixed striped">
                <thead><tr><th>Search Query</th><th style="width:90px;">Searches</th><th style="width:90px;">Lot Views</th><th style="width:100px;">Unique Lots</th></tr></thead>
                <tbody id="la-search-tbody"><tr><td colspan="4" style="text-align:center;color:#666;">—</td></tr></tbody>
            </table>
        </div>

        <!-- Export -->
        <div class="af-stats-panel" style="margin-bottom:20px;">
            <h3>Export Data</h3>
            <p style="font-size:13px;color:#666;margin-bottom:10px;">Download all lot analytics data as a CSV file. Uses the catalogue filter above if selected.</p>
            <button class="button button-primary" id="la-export-csv">Export to CSV</button>
            <span id="la-export-status" style="margin-left:10px;color:#666;"></span>
        </div>
    </div>

    <!-- Settings Tab -->
    <div class="af-stats-tab-content" id="tab-settings" style="display:none;">
        <div class="af-stats-panel" style="max-width:600px;">
            <h3>Statistics Settings</h3>
            <form id="af-stats-settings-form">
                <table class="form-table">
                    <tr>
                        <th>Enable Tracking</th>
                        <td><label><input type="checkbox" name="enabled" id="set-enabled" <?php checked(get_option('af_stats_enabled', 'on'), 'on'); ?> /> Collect statistics data</label></td>
                    </tr>
                    <tr>
                        <th>Track Logged-in Users</th>
                        <td><label><input type="checkbox" name="track_logged_in" id="set-track-logged-in" <?php checked(get_option('af_stats_track_logged_in', 'on'), 'on'); ?> /> Include logged-in users in stats</label></td>
                    </tr>
                    <tr>
                        <th>Anonymize IPs</th>
                        <td><label><input type="checkbox" name="anonymize_ip" id="set-anonymize" <?php checked(get_option('af_stats_anonymize_ip', 'off'), 'on'); ?> /> Hash last octet of IP (GDPR)</label></td>
                    </tr>
                    <tr>
                        <th>Exclude IPs</th>
                        <td><textarea name="exclude_ips" id="set-exclude-ips" rows="3" style="width:100%;"><?php echo esc_textarea(get_option('af_stats_exclude_ips', '')); ?></textarea>
                        <p class="description">One IP per line. These IPs will not be tracked.</p></td>
                    </tr>
                    <tr>
                        <th>Exclude Roles</th>
                        <td><input type="text" name="exclude_roles" id="set-exclude-roles" value="<?php echo esc_attr(get_option('af_stats_exclude_roles', 'administrator')); ?>" style="width:100%;" />
                        <p class="description">Comma-separated roles (e.g., administrator,editor)</p></td>
                    </tr>
                    <tr>
                        <th>Data Retention</th>
                        <td><input type="number" name="retention_days" id="set-retention" value="<?php echo esc_attr(get_option('af_stats_retention_days', 0)); ?>" min="0" style="width:100px;" /> days
                        <p class="description">0 = keep data forever. Otherwise, data older than this is auto-purged daily.</p></td>
                    </tr>
                    <tr>
                        <th colspan="2" style="padding-top:18px;border-top:1px solid #e2e4e7;"><h4 style="margin:0;font-size:14px;">Weekly Email Report</h4></th>
                    </tr>
                    <tr>
                        <th>Send Weekly Email</th>
                        <td><label><input type="checkbox" name="weekly_email" id="set-weekly-email" <?php checked(get_option('af_stats_weekly_email', 'off'), 'on'); ?> /> Email a summary of the last 7 days</label></td>
                    </tr>
                    <tr>
                        <th>Recipient(s)</th>
                        <td><input type="text" name="weekly_email_to" id="set-weekly-email-to" value="<?php echo esc_attr(get_option('af_stats_weekly_email_to', get_option('admin_email'))); ?>" style="width:100%;" />
                        <p class="description">One address, or several separated by commas.</p></td>
                    </tr>
                    <tr>
                        <th>Send On</th>
                        <td>
                            <select name="weekly_email_day" id="set-weekly-email-day">
                                <?php
                                $af_days = array(1=>'Monday',2=>'Tuesday',3=>'Wednesday',4=>'Thursday',5=>'Friday',6=>'Saturday',7=>'Sunday');
                                $af_day_sel = intval(get_option('af_stats_weekly_email_day', 1));
                                foreach ($af_days as $af_n => $af_lbl) {
                                    echo '<option value="' . $af_n . '" ' . selected($af_day_sel, $af_n, false) . '>' . esc_html($af_lbl) . '</option>';
                                }
                                ?>
                            </select>
                            <button type="button" class="button" id="set-weekly-test" style="margin-left:10px;">Send test now</button>
                            <span id="weekly-test-status" style="margin-left:8px;font-size:12px;"></span>
                            <p class="description">A daily check sends the report once on the chosen day. Disabled by default.</p>
                        </td>
                    </tr>
                </table>
                <p><button type="submit" class="button button-primary">Save Settings</button> <span id="settings-status" style="margin-left:10px;"></span></p>
            </form>
        </div>
    </div>
</div>

<style>
.af-stats-wrap { max-width: 1400px; }
.af-stats-card {
    background: #fff; border: 1px solid #c3c4c7; border-radius: 4px; padding: 16px 20px;
    box-shadow: 0 1px 1px rgba(0,0,0,0.04);
}
.af-card-label { font-size: 12px; color: #646970; text-transform: uppercase; letter-spacing: 0.5px; margin-bottom: 4px; }
.af-card-value { font-size: 28px; font-weight: 600; color: #1d2327; line-height: 1.2; }
.af-card-change { font-size: 12px; margin-top: 4px; }
.af-card-change.up { color: #00a32a; }
.af-card-change.down { color: #d63638; }
.af-card-change.neutral { color: #646970; }
.af-stats-panel {
    background: #fff; border: 1px solid #c3c4c7; border-radius: 4px; padding: 16px 20px;
    box-shadow: 0 1px 1px rgba(0,0,0,0.04);
}
.af-stats-panel h3 { margin: 0 0 12px 0; font-size: 14px; color: #1d2327; }
.af-stats-panel table td { font-size: 12.5px; }
.af-stats-tabs .nav-tab { cursor: pointer; }
.af-stats-channel-badge {
    display: inline-block; padding: 2px 8px; border-radius: 3px; font-size: 11px; font-weight: 600;
}
.channel-organic_search { background: #d4edda; color: #155724; }
.channel-direct { background: #e2e3e5; color: #383d41; }
.channel-referral { background: #cce5ff; color: #004085; }
.channel-social { background: #f8d7da; color: #721c24; }
.channel-email { background: #fff3cd; color: #856404; }
.channel-paid_search { background: #d6d8db; color: #1b1e21; }
/* Day-of-week tab strip for the hourly charts (Hourly Distribution + Peak Viewing Times) */
.af-dow-tabs { display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 12px 0; }
.af-dow-tab {
    cursor: pointer; padding: 3px 11px; border: 1px solid #c3c4c7; border-radius: 14px;
    background: #f6f7f7; font-size: 12px; line-height: 1.7; color: #1d2327; user-select: none;
}
.af-dow-tab:hover { background: #f0f0f1; }
.af-dow-tab small { color: #787c82; margin-left: 3px; font-size: 11px; }
.af-dow-tab.active { background: #2271b1; border-color: #2271b1; color: #fff; }
.af-dow-tab.active small { color: #cfe2f3; }
</style>

<script src="<?php echo esc_url($af_chart_js); ?>"></script>
<script>
(function($) {
    var nonce = '<?php echo esc_js($nonce); ?>';
    var exportBase = '<?php echo esc_js($export_base); ?>';
    var charts = {};
    var rtTimer = null;
    var pagesPage = 1, referrersPage = 1;

    // ==================== UTILITY ====================

    function getDateRange() {
        return { from: $('#af-stats-from').val(), to: $('#af-stats-to').val() };
    }

    function formatDuration(s) {
        if (!s || s <= 0) return '0s';
        s = parseInt(s);
        if (s < 60) return s + 's';
        var m = Math.floor(s / 60);
        var sec = s % 60;
        if (m < 60) return m + 'm ' + sec + 's';
        var h = Math.floor(m / 60);
        return h + 'h ' + (m % 60) + 'm';
    }

    function formatNumber(n) {
        if (n === undefined || n === null) return '0';
        return parseInt(n).toLocaleString();
    }

    // Country cells/labels show the readable name resolved server-side
    // (country_name), falling back to the raw ISO code on older cached
    // responses so a row can never render empty.
    function countryLabel(r) {
        if (!r) return 'Unknown';
        return r.country_name || r.country || 'Unknown';
    }

    function pctChange(current, previous) {
        if (previous === 0 && current === 0) return { text: '—', cls: 'neutral' };
        if (previous === 0) return { text: '+100%', cls: 'up' };
        var pct = ((current - previous) / previous * 100).toFixed(1);
        if (pct > 0) return { text: '+' + pct + '%', cls: 'up' };
        if (pct < 0) return { text: pct + '%', cls: 'down' };
        return { text: '0%', cls: 'neutral' };
    }

    function updateKpi(id, value, change) {
        $(id).text(value);
        if (change) {
            var ch = pctChange(change.current, change.previous);
            $(id + '-change').text(ch.text + ' vs prev period').removeClass('up down neutral').addClass(ch.cls);
        }
    }

    function apiCall(action, extra, callback) {
        var range = getDateRange();
        var data = $.extend({ action: action, nonce: nonce, from: range.from, to: range.to }, extra || {});
        $('#af-stats-loading').show();
        $.post(ajaxurl, data, function(resp) {
            $('#af-stats-loading').hide();
            if (resp.success) callback(resp.data);
        }).fail(function() { $('#af-stats-loading').hide(); });
    }

    // ==================== CHARTS ====================

    var chartColors = {
        blue: 'rgba(54, 162, 235, 1)', blueLight: 'rgba(54, 162, 235, 0.15)',
        green: 'rgba(75, 192, 192, 1)', greenLight: 'rgba(75, 192, 192, 0.15)',
        orange: 'rgba(255, 159, 64, 1)', orangeLight: 'rgba(255, 159, 64, 0.15)',
        red: 'rgba(255, 99, 132, 1)', purple: 'rgba(153, 102, 255, 1)',
        grey: 'rgba(201, 203, 207, 1)', yellow: 'rgba(255, 205, 86, 1)',
    };

    function destroyChart(id) {
        if (charts[id]) { charts[id].destroy(); delete charts[id]; }
    }

    // Inline Chart.js plugin: draws dashed vertical lines + a ▲ marker at each
    // auction start date on a category (date-label) x-axis. Events come via
    // options.plugins.afAuctionMarkers.events = [{date:'YYYY-MM-DD', name}].
    var afAuctionMarkers = {
        id: 'afAuctionMarkers',
        afterDraw: function(chart, args, opts) {
            var events = (opts && opts.events) || [];
            var xScale = chart.scales.x;
            if (!events.length || !xScale || !chart.chartArea) return;
            var top = chart.chartArea.top, bottom = chart.chartArea.bottom, ctx = chart.ctx;
            var labels = chart.data.labels || [];
            events.forEach(function(ev) {
                var idx = labels.indexOf(ev.date);
                if (idx < 0) return;
                var x = xScale.getPixelForValue(idx);
                if (x == null || isNaN(x)) return;
                ctx.save();
                ctx.strokeStyle = 'rgba(214,54,56,0.7)';
                ctx.lineWidth = 1;
                ctx.setLineDash([4, 3]);
                ctx.beginPath(); ctx.moveTo(x, top); ctx.lineTo(x, bottom); ctx.stroke();
                ctx.setLineDash([]);
                ctx.fillStyle = 'rgba(214,54,56,0.9)';
                ctx.textAlign = 'center';
                ctx.font = '9px sans-serif';
                ctx.fillText('▲', x, top - 1);
                ctx.restore();
            });
        }
    };

    function buildTrafficChart(data, auctionEvents) {
        destroyChart('traffic');
        var ctx = document.getElementById('chart-traffic');
        if (!ctx) return;

        // Fill in missing dates
        var range = getDateRange();
        var dateMap = { pv: {}, vis: {}, sess: {} };
        (data.daily_pageviews || []).forEach(function(r) { dateMap.pv[r.date] = parseInt(r.count); });
        (data.daily_visitors || []).forEach(function(r) { dateMap.vis[r.date] = parseInt(r.count); });
        (data.daily_sessions || []).forEach(function(r) { dateMap.sess[r.date] = parseInt(r.count); });

        var labels = [], pvData = [], visData = [], sessData = [];
        var d = new Date(range.from); var end = new Date(range.to);
        while (d <= end) {
            var ds = d.toISOString().split('T')[0];
            labels.push(ds);
            pvData.push(dateMap.pv[ds] || 0);
            visData.push(dateMap.vis[ds] || 0);
            sessData.push(dateMap.sess[ds] || 0);
            d.setDate(d.getDate() + 1);
        }

        var events = auctionEvents || [];
        charts['traffic'] = new Chart(ctx, {
            type: 'line',
            data: {
                labels: labels,
                datasets: [
                    { label: 'Pageviews', data: pvData, borderColor: chartColors.blue, backgroundColor: chartColors.blueLight, fill: true, tension: 0.3, pointRadius: labels.length > 60 ? 0 : 3 },
                    { label: 'Visitors', data: visData, borderColor: chartColors.green, backgroundColor: chartColors.greenLight, fill: true, tension: 0.3, pointRadius: labels.length > 60 ? 0 : 3 },
                    { label: 'Sessions', data: sessData, borderColor: chartColors.orange, backgroundColor: chartColors.orangeLight, fill: true, tension: 0.3, pointRadius: labels.length > 60 ? 0 : 3 }
                ]
            },
            options: { responsive: true, maintainAspectRatio: false,
                plugins: { legend: { position: 'top' }, afAuctionMarkers: { events: events } },
                scales: { x: { ticks: { maxTicksLimit: 15 } }, y: { beginAtZero: true } } },
            plugins: [afAuctionMarkers]
        });

        // Caption naming the auction-start markers drawn on the chart
        var note = '';
        if (events.length) {
            note = '▲ Auction dates: ' + events.map(function(e) {
                var p = (e.date || '').split('-'); // YYYY-MM-DD → D/M
                return e.name + (p.length === 3 ? ' (' + parseInt(p[2], 10) + '/' + parseInt(p[1], 10) + ')' : '');
            }).join('  ·  ');
        }
        $('#traffic-auctions-note').text(note);
    }

    function buildChannelsChart(data) {
        destroyChart('channels');
        var ctx = document.getElementById('chart-channels');
        if (!ctx) return;
        var labels = [], values = [], colors = [chartColors.green, chartColors.blue, chartColors.orange, chartColors.red, chartColors.purple, chartColors.yellow, chartColors.grey];
        (data.channels || []).forEach(function(r, i) {
            labels.push(r.traffic_channel.replace('_', ' '));
            values.push(parseInt(r.count));
        });
        charts['channels'] = new Chart(ctx, {
            type: 'doughnut',
            data: { labels: labels, datasets: [{ data: values, backgroundColor: colors.slice(0, labels.length) }] },
            options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'right' } } }
        });
    }

    function buildHourlyChart(data) {
        // data.hourly rows are now { dow, hour, count }; render as tabbed days.
        var rows = (data.hourly || []).map(function(r) { return { dow: r.dow, hour: r.hour, val: r.count }; });
        renderDowHourly(rows, { key: 'hourly', tabsId: 'hourly-dow-tabs', canvasId: 'chart-hourly', chartVar: 'hourly', label: 'Pageviews' });
    }

    function buildDevicesChart(data) {
        destroyChart('devices');
        var ctx = document.getElementById('chart-devices');
        if (!ctx) return;
        var labels = [], values = [];
        (data.devices || []).forEach(function(r) { labels.push(r.device_type); values.push(parseInt(r.count)); });
        charts['devices'] = new Chart(ctx, {
            type: 'pie',
            data: { labels: labels, datasets: [{ data: values, backgroundColor: [chartColors.blue, chartColors.green, chartColors.orange] }] },
            options: { responsive: true, maintainAspectRatio: false, plugins: { legend: { position: 'right' } } }
        });
    }

    function buildCountriesChart(data) {
        destroyChart('countries');
        var ctx = document.getElementById('chart-countries');
        if (!ctx) return;
        var labels = [], values = [], colors = [chartColors.blue, chartColors.green, chartColors.orange, chartColors.red, chartColors.purple, chartColors.yellow, chartColors.grey, 'rgba(100,149,237,0.8)', 'rgba(60,179,113,0.8)', 'rgba(238,130,238,0.8)'];
        (data || []).slice(0, 10).forEach(function(r) { labels.push(countryLabel(r)); values.push(parseInt(r.visitors)); });
        charts['countries'] = new Chart(ctx, {
            type: 'bar',
            data: { labels: labels, datasets: [{ label: 'Visitors', data: values, backgroundColor: colors.slice(0, labels.length) }] },
            options: { responsive: true, maintainAspectRatio: false, indexAxis: 'y', plugins: { legend: { display: false } } }
        });
    }

    // CSS/HTML horizontal funnel (no chart dependency). stages: [{label, count}]
    function renderFunnel(stages) {
        stages = stages || [];
        var el = document.getElementById('dash-funnel');
        if (!el) return;
        var top = stages.length ? (parseInt(stages[0].count, 10) || 0) : 0;
        var colors = [chartColors.blue, chartColors.green, chartColors.orange, chartColors.purple];
        var html = '';
        stages.forEach(function(s, i) {
            var c = parseInt(s.count, 10) || 0;
            // A stage with no data source is reported as "not tracked" rather
            // than 0, so an unwired metric can't read as a real business result.
            var unmeasured = (s.measured === false);
            // A stage flagged nested:false is not a subset of stage 1, so a
            // "% of visitors" would divide two different populations — and an
            // unclamped bar could overflow its track.
            var nested = (s.nested !== false);
            var pct = top > 0 ? Math.min(100, Math.round(c / top * 100)) : 0;
            var width = top > 0 ? Math.min(100, Math.max(1.5, c / top * 100)) : 0;
            var right = unmeasured
                ? '<span style="color:#888;font-style:italic;">not tracked</span>'
                : '<strong>' + formatNumber(c) + '</strong>'
                  + (nested ? ' <span style="color:#888;">(' + pct + '% of visitors)</span>' : '');
            var bar = unmeasured
                ? '<div style="height:100%;width:100%;background:repeating-linear-gradient(45deg,#f3f4f6,#f3f4f6 6px,#e9ebee 6px,#e9ebee 12px);"></div>'
                : '<div style="height:100%;width:' + width + '%;background:' + colors[i % colors.length] + ';transition:width .3s;"></div>';
            html += '<div style="margin-bottom:8px;"' + (s.note ? ' title="' + String(s.note).replace(/"/g, '&quot;') + '"' : '') + '>'
                + '<div style="display:flex;justify-content:space-between;font-size:12px;margin-bottom:2px;">'
                + '<span>' + (i + 1) + '. ' + s.label + '</span>'
                + '<span>' + right + '</span>'
                + '</div>'
                + '<div style="background:#eef1f4;border-radius:3px;height:22px;overflow:hidden;">'
                + bar
                + '</div></div>';
        });
        el.innerHTML = html || '<div style="color:#666;">No data</div>';
    }

    // ==================== DAY-OF-WEEK HOURLY (tabbed) ====================
    // Shared renderer for "Hourly Distribution" (site stats) and "Peak Viewing
    // Times" (lot analytics). Consolidates every weekday across the selected
    // range and lets the user tab between days (dw per MySQL DAYOFWEEK:
    // 1=Sun … 7=Sat), plus an "All days" view (dw 0) that sums them.
    var dowState = {};
    var DOW_TABS = [
        { dw: 0, label: 'All days' },
        { dw: 2, label: 'Mon' }, { dw: 3, label: 'Tue' }, { dw: 4, label: 'Wed' },
        { dw: 5, label: 'Thu' }, { dw: 6, label: 'Fri' }, { dw: 7, label: 'Sat' },
        { dw: 1, label: 'Sun' }
    ];
    function dowLabel(dw) {
        var m = { 0: 'all days', 1: 'Sun', 2: 'Mon', 3: 'Tue', 4: 'Wed', 5: 'Thu', 6: 'Fri', 7: 'Sat' };
        return m[dw] || '';
    }

    // rows: array of { dow, hour, val }. cfg: { key, tabsId, canvasId, chartVar,
    // label, summaryId?, noun?, summarySuffix? }
    function renderDowHourly(rows, cfg) {
        var perDay = {}, all = [], dayTotals = { 0: 0 };
        for (var h = 0; h < 24; h++) all.push(0);
        for (var dw = 1; dw <= 7; dw++) { perDay[dw] = []; dayTotals[dw] = 0; for (var i = 0; i < 24; i++) perDay[dw].push(0); }
        (rows || []).forEach(function(r) {
            var hr = parseInt(r.hour, 10), v = parseInt(r.val, 10) || 0, d = parseInt(r.dow, 10);
            if (isNaN(hr) || hr < 0 || hr > 23) return;
            all[hr] += v; dayTotals[0] += v;                       // "All days" always works, even if dow is absent
            if (d >= 1 && d <= 7) { perDay[d][hr] += v; dayTotals[d] += v; }
        });
        var st = dowState[cfg.key] || (dowState[cfg.key] = { active: 0 });
        st.perDay = perDay; st.all = all; st.dayTotals = dayTotals; st.cfg = cfg;

        var $tabs = $('#' + cfg.tabsId).attr('data-key', cfg.key).empty();
        DOW_TABS.forEach(function(o) {
            var $t = $('<span class="af-dow-tab"></span>').attr('data-dw', o.dw).text(o.label)
                .append(' ').append($('<small></small>').text(formatNumber(dayTotals[o.dw] || 0)));
            if (o.dw === st.active) $t.addClass('active');
            $tabs.append($t);
        });
        drawDowHourly(cfg.key);
    }

    function drawDowHourly(key) {
        var st = dowState[key]; if (!st) return;
        var cfg = st.cfg;
        var ctx = document.getElementById(cfg.canvasId); if (!ctx) return;
        var series = (st.active === 0) ? st.all : (st.perDay[st.active] || []);
        var labels = []; for (var h = 0; h < 24; h++) labels.push(h + ':00');
        destroyChart(cfg.chartVar);
        charts[cfg.chartVar] = new Chart(ctx, {
            type: 'bar',
            data: { labels: labels, datasets: [{
                label: cfg.label || 'Count', data: series,
                backgroundColor: chartColors.blueLight, borderColor: chartColors.blue, borderWidth: 1
            }] },
            options: { responsive: true, maintainAspectRatio: false,
                plugins: { legend: { display: false } }, scales: { y: { beginAtZero: true } } }
        });
        if (cfg.summaryId) {
            var peakH = 0, peakV = 0;
            for (var j = 0; j < 24; j++) { if (series[j] > peakV) { peakV = series[j]; peakH = j; } }
            var scope = dowLabel(st.active);
            $('#' + cfg.summaryId).text(peakV > 0
                ? ('Peak: ' + peakH + ':00 (' + scope + ') — ' + formatNumber(peakV) + ' ' + (cfg.noun || 'views') + (cfg.summarySuffix ? (' ' + cfg.summarySuffix) : ''))
                : ('No data (' + scope + ')'));
        }
    }

    // Day-tab clicks (delegated — the strips are rebuilt on every data load)
    $(document).on('click', '.af-dow-tab', function() {
        var key = $(this).closest('.af-dow-tabs').data('key');
        if (!dowState[key]) return;
        dowState[key].active = parseInt($(this).data('dw'), 10) || 0;
        $(this).addClass('active').siblings().removeClass('active');
        drawDowHourly(key);
    });

    // ==================== DATA LOADING ====================

    function loadDashboard() {
        apiCall('af_stats_dashboard', {}, function(d) {
            updateKpi('#kpi-visitors', formatNumber(d.current.visitors), { current: d.current.visitors, previous: d.previous.visitors });
            updateKpi('#kpi-sessions', formatNumber(d.current.sessions), { current: d.current.sessions, previous: d.previous.sessions });
            updateKpi('#kpi-pageviews', formatNumber(d.current.pageviews), { current: d.current.pageviews, previous: d.previous.pageviews });
            updateKpi('#kpi-bounce', d.current.bounce_rate + '%', { current: d.current.bounce_rate, previous: d.previous.bounce_rate });
            $('#kpi-duration').text(formatDuration(d.current.avg_duration));
            $('#kpi-pps').text(d.current.avg_pages_per_session);

            // New vs returning visitors (returning = visitors − new)
            var newCur = d.current.new_visitors || 0, newPrev = d.previous.new_visitors || 0;
            var retCur = Math.max(0, (d.current.visitors || 0) - newCur);
            var retPrev = Math.max(0, (d.previous.visitors || 0) - newPrev);
            updateKpi('#kpi-new-visitors', formatNumber(newCur), { current: newCur, previous: newPrev });
            updateKpi('#kpi-returning-visitors', formatNumber(retCur), { current: retCur, previous: retPrev });

            // Bounce rate: lower is better, so invert the color
            var bounceChange = pctChange(d.current.bounce_rate, d.previous.bounce_rate);
            if (bounceChange.cls === 'up') bounceChange.cls = 'down';
            else if (bounceChange.cls === 'down') bounceChange.cls = 'up';
            $('#kpi-bounce-change').text(bounceChange.text + ' vs prev period').removeClass('up down neutral').addClass(bounceChange.cls);

            buildTrafficChart(d.charts, d.auction_events);
            buildChannelsChart(d.charts);
            buildHourlyChart(d.charts);
            buildDevicesChart(d.charts);
            renderFunnel(d.funnel);

            // Top pages
            var html = '';
            (d.top_pages || []).forEach(function(r) {
                html += '<tr><td title="' + r.url_path + '">' + (r.page_title || r.url_path).substring(0, 50) + '</td><td>' + formatNumber(r.views) + '</td></tr>';
            });
            $('#dash-top-pages tbody').html(html || '<tr><td colspan="2" style="text-align:center;color:#666;">No data</td></tr>');

            // Top referrers
            html = '';
            (d.top_referrers || []).forEach(function(r) {
                html += '<tr><td>' + r.referrer_domain + '</td><td>' + formatNumber(r.count) + '</td></tr>';
            });
            $('#dash-top-referrers tbody').html(html || '<tr><td colspan="2" style="text-align:center;color:#666;">No data</td></tr>');

            // Top countries
            html = '';
            (d.top_countries || []).forEach(function(r) {
                html += '<tr><td>' + countryLabel(r) + '</td><td>' + formatNumber(r.visitors) + '</td></tr>';
            });
            $('#dash-top-countries tbody').html(html || '<tr><td colspan="2" style="text-align:center;color:#666;">No data</td></tr>');
        });
    }

    function loadPages(page) {
        pagesPage = page || 1;
        apiCall('af_stats_top_pages', { page: pagesPage, search: $('#pages-search').val() }, function(d) {
            var html = '';
            (d.results || []).forEach(function(r) {
                html += '<tr><td>' + r.url_path + '</td><td>' + (r.page_title || '').substring(0, 40) + '</td><td>' + formatNumber(r.views) + '</td><td>' + formatNumber(r.visitors) + '</td><td>' + formatDuration(r.avg_time) + '</td></tr>';
            });
            $('#pages-tbody').html(html || '<tr><td colspan="5" style="text-align:center;color:#666;">No data</td></tr>');
            $('#pages-info').text('Page ' + d.page + ' of ' + d.pages);
            $('#pages-prev').prop('disabled', d.page <= 1);
            $('#pages-next').prop('disabled', d.page >= d.pages);
        });
    }

    function loadReferrers(page) {
        referrersPage = page || 1;
        apiCall('af_stats_referrers', { page: referrersPage }, function(d) {
            var html = '';
            (d.results || []).forEach(function(r) {
                html += '<tr><td>' + r.referrer_domain + '</td><td><span class="af-stats-channel-badge channel-' + r.traffic_channel + '">' + r.traffic_channel.replace('_', ' ') + '</span></td><td>' + formatNumber(r.sessions) + '</td><td>' + formatNumber(r.pageviews) + '</td><td>' + formatDuration(r.avg_duration) + '</td><td>' + r.bounce_rate + '%</td></tr>';
            });
            $('#referrers-tbody').html(html || '<tr><td colspan="6" style="text-align:center;color:#666;">No data</td></tr>');
            $('#referrers-info').text('Page ' + d.page + ' of ' + d.pages);
            $('#referrers-prev').prop('disabled', d.page <= 1);
            $('#referrers-next').prop('disabled', d.page >= d.pages);
        });
    }

    function loadCountries() {
        apiCall('af_stats_countries', {}, function(d) {
            var html = '';
            (d.results || []).forEach(function(r) {
                html += '<tr><td>' + countryLabel(r) + '</td><td>' + formatNumber(r.visitors) + '</td><td>' + formatNumber(r.pageviews) + '</td></tr>';
            });
            $('#countries-tbody').html(html || '<tr><td colspan="3" style="text-align:center;color:#666;">No data</td></tr>');
            buildCountriesChart(d.results);
        });
    }

    function loadTechnology() {
        apiCall('af_stats_browsers', {}, function(d) {
            var html = '';
            (d.browsers || []).forEach(function(r) {
                html += '<tr><td>' + r.browser + '</td><td>' + r.os + '</td><td>' + r.device_type + '</td><td>' + formatNumber(r.visitors) + '</td></tr>';
            });
            $('#tech-browsers-tbody').html(html || '<tr><td colspan="4" style="text-align:center;color:#666;">No data</td></tr>');

            html = '';
            (d.screens || []).forEach(function(r) {
                html += '<tr><td>' + r.resolution + '</td><td>' + formatNumber(r.visitors) + '</td></tr>';
            });
            $('#tech-screens-tbody').html(html || '<tr><td colspan="2" style="text-align:center;color:#666;">No data</td></tr>');
        });
    }

    function loadSearches() {
        apiCall('af_stats_searches', {}, function(d) {
            var html = '';
            (d.results || []).forEach(function(r) {
                html += '<tr><td>' + r.search_query + '</td><td>' + r.search_type + '</td><td>' + formatNumber(r.count) + '</td><td>' + r.last_searched + '</td></tr>';
            });
            $('#searches-tbody').html(html || '<tr><td colspan="4" style="text-align:center;color:#666;">No searches recorded</td></tr>');
        });
    }

    function loadErrors() {
        apiCall('af_stats_errors', {}, function(d) {
            var html = '';
            (d.results || []).forEach(function(r) {
                html += '<tr><td>' + r.url_path + '</td><td>' + (r.referrer_url || '—').substring(0, 60) + '</td><td>' + r.hit_count + '</td><td>' + r.first_seen + '</td><td>' + r.last_seen + '</td></tr>';
            });
            $('#errors-tbody').html(html || '<tr><td colspan="5" style="text-align:center;color:#666;">No 404 errors recorded</td></tr>');
        });
    }

    function loadRealtime() {
        $.post(ajaxurl, { action: 'af_stats_realtime', nonce: nonce }, function(resp) {
            if (!resp.success) return;
            var d = resp.data;
            $('#rt-active').text(d.active_visitors);
            var html = '';
            (d.recent_pageviews || []).forEach(function(r) {
                html += '<tr><td>' + (r.page_title || r.url_path || '').substring(0, 60) + '</td><td>' + (r.country_name || r.country || '—') + '</td><td>' + (r.browser || '—') + '</td><td>' + (r.device_type || '—') + '</td><td>' + r.created_at + '</td></tr>';
            });
            $('#rt-tbody').html(html || '<tr><td colspan="5" style="text-align:center;color:#666;">No active visitors</td></tr>');
        });
    }

    // ==================== TAB SWITCHING ====================

    var tabLoaders = {
        dashboard: loadDashboard,
        pages: function() { loadPages(1); },
        referrers: function() { loadReferrers(1); },
        countries: loadCountries,
        technology: loadTechnology,
        searches: loadSearches,
        errors: loadErrors,
        realtime: loadRealtime,
        'lot-analytics': loadLotAnalytics,
        settings: function() {}
    };

    $('.af-stats-tabs .nav-tab').on('click', function(e) {
        e.preventDefault();
        var tab = $(this).data('tab');
        $('.af-stats-tabs .nav-tab').removeClass('nav-tab-active');
        $(this).addClass('nav-tab-active');
        $('.af-stats-tab-content').hide();
        $('#tab-' + tab).show();

        if (rtTimer) { clearInterval(rtTimer); rtTimer = null; }

        if (tabLoaders[tab]) tabLoaders[tab]();

        if (tab === 'realtime') {
            rtTimer = setInterval(loadRealtime, 10000);
        }
    });

    // ==================== DATE RANGE ====================

    function setDateRange(days) {
        var to = new Date();
        var from = new Date();
        from.setDate(from.getDate() - days);
        $('#af-stats-from').val(from.toISOString().split('T')[0]);
        $('#af-stats-to').val(to.toISOString().split('T')[0]);
    }

    $('#af-stats-preset').on('change', function() {
        var val = $(this).val();
        if (val !== 'custom') setDateRange(parseInt(val));
    });

    $('#af-stats-refresh').on('click', function() {
        var activeTab = $('.af-stats-tabs .nav-tab-active').data('tab');
        if (tabLoaders[activeTab]) tabLoaders[activeTab]();
    });

    // Pages
    $('#pages-search-btn').on('click', function() { loadPages(1); });
    $('#pages-search').on('keypress', function(e) { if (e.which === 13) loadPages(1); });
    $('#pages-prev').on('click', function() { loadPages(pagesPage - 1); });
    $('#pages-next').on('click', function() { loadPages(pagesPage + 1); });

    // Referrers
    $('#referrers-prev').on('click', function() { loadReferrers(referrersPage - 1); });
    $('#referrers-next').on('click', function() { loadReferrers(referrersPage + 1); });

    // Export links
    $('#pages-export').on('click', function(e) {
        e.preventDefault();
        var r = getDateRange();
        window.location = exportBase + '&type=pageviews&from=' + r.from + '&to=' + r.to;
    });
    $('#referrers-export').on('click', function(e) {
        e.preventDefault();
        var r = getDateRange();
        window.location = exportBase + '&type=referrers&from=' + r.from + '&to=' + r.to;
    });

    // Settings form
    $('#af-stats-settings-form').on('submit', function(e) {
        e.preventDefault();
        $.post(ajaxurl, {
            action: 'af_stats_save_settings',
            nonce: nonce,
            enabled: $('#set-enabled').is(':checked') ? 'on' : '',
            track_logged_in: $('#set-track-logged-in').is(':checked') ? 'on' : '',
            anonymize_ip: $('#set-anonymize').is(':checked') ? 'on' : '',
            exclude_ips: $('#set-exclude-ips').val(),
            exclude_roles: $('#set-exclude-roles').val(),
            retention_days: $('#set-retention').val(),
            weekly_email: $('#set-weekly-email').is(':checked') ? 'on' : '',
            weekly_email_to: $('#set-weekly-email-to').val(),
            weekly_email_day: $('#set-weekly-email-day').val()
        }, function(resp) {
            $('#settings-status').text(resp.success ? 'Saved!' : 'Error').css('color', resp.success ? '#00a32a' : '#d63638');
            setTimeout(function() { $('#settings-status').text(''); }, 3000);
        });
    });

    // Weekly report — send a test copy now (to whatever is in the Recipient box)
    $('#set-weekly-test').on('click', function() {
        var $s = $('#weekly-test-status').text('Sending…').css('color', '#646970');
        $.post(ajaxurl, { action: 'af_stats_send_test_report', nonce: nonce, to: $('#set-weekly-email-to').val() }, function(resp) {
            if (resp && resp.success) {
                $s.text((resp.data && resp.data.message) ? resp.data.message : 'Sent').css('color', '#00a32a');
            } else {
                $s.text((resp && resp.data) ? resp.data : 'Failed').css('color', '#d63638');
            }
        });
    });

    // ==================== LOT ANALYTICS ====================
    function loadLotAnalytics() {
        var termId = $("#la-auction-filter").val() || "";
        var laRange = getDateRange();
        var laDays = Math.max(1, Math.round((new Date(laRange.to) - new Date(laRange.from)) / 86400000) + 1);
        $("#la-status").text("Loading...");
        $.post(ajaxurl, { action: "af_lot_analytics_data", nonce: nonce, term_id: termId, from: laRange.from, to: laRange.to }, function(resp) {
            $("#la-status").text("");
            if (!resp.success) return;
            var d = resp.data;

            // Auction stats
            var html = "";
            if (d.auctions && d.auctions.length) {
                $.each(d.auctions, function(i, a) {
                    var dateStr = a.auction_date ? a.auction_date.substring(0, 10) : "\u2014";
                    var statusBadge = parseInt(a.is_past)
                        ? '<span style="color:#999;font-size:12px;">Past</span>'
                        : '<span style="color:#00a32a;font-weight:600;font-size:12px;">Upcoming</span>';
                    html += "<tr><td>" + (a.auction_name || "ID: " + a.term_id) + "</td>"
                        + "<td>" + dateStr + "</td>"
                        + "<td>" + statusBadge + "</td>"
                        + "<td>" + formatNumber(a.total_views) + "</td>"
                        + "<td>" + formatNumber(a.total_favorites) + "</td>"
                        + "<td>" + formatNumber(a.lot_count) + "</td>"
                        + "<td>" + parseFloat(a.avg_views_per_lot || 0).toFixed(1) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="7" style="text-align:center;color:#666;">No data yet</td></tr>';
            }
            $("#la-auctions-tbody").html(html);
            populateAuctionFilter(d.auctions);

            // Most viewed
            html = "";
            if (d.most_viewed && d.most_viewed.length) {
                $.each(d.most_viewed, function(i, l) {
                    var name = l.lot_name || l.post_title || "Lot " + l.post_id;
                    html += "<tr><td>" + name + "</td>"
                        + "<td>" + formatNumber(l.view_count) + "</td>"
                        + "<td>" + formatNumber(l.unique_visitors) + "</td>"
                        + "<td>" + formatNumber(l.favorite_count) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="4" style="text-align:center;color:#666;">No data yet</td></tr>';
            }
            $("#la-most-viewed-tbody").html(html);

            // Most favorited
            html = "";
            if (d.most_favorited && d.most_favorited.length) {
                $.each(d.most_favorited, function(i, l) {
                    var name = l.lot_name || l.post_title || "Lot " + l.post_id;
                    html += "<tr><td>" + name + "</td>"
                        + "<td>" + formatNumber(l.favorite_count) + "</td>"
                        + "<td>" + formatNumber(l.view_count) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="3" style="text-align:center;color:#666;">No data yet</td></tr>';
            }
            $("#la-most-fav-tbody").html(html);

            // Trending
            html = "";
            if (d.trending && d.trending.length) {
                $.each(d.trending, function(i, l) {
                    var name = l.lot_name || l.post_title || "Lot " + l.post_id;
                    html += "<tr><td>" + name + "</td>"
                        + "<td>" + (l.auction_name || "") + "</td>"
                        + "<td>" + formatNumber(l.recent_views) + "</td>"
                        + "<td>" + formatNumber(l.recent_unique) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="4" style="text-align:center;color:#666;">No data yet</td></tr>';
            }
            $("#la-trending-tbody").html(html);

            // Conversion tracking
            html = "";
            var totalSold = 0, totalBids = 0, totalNoBids = 0;
            if (d.conversion && d.conversion.length) {
                $.each(d.conversion, function(i, l) {
                    var name = l.lot_name || l.post_title || "Lot " + l.post_id;
                    var statusBadge = l.bid_status === "sold"
                        ? '<span style="color:#00a32a;font-weight:600;">Sold</span>'
                        : l.bid_status === "has_bids"
                        ? '<span style="color:#dba617;">Bids</span>'
                        : '<span style="color:#999;">No Bids</span>';
                    if (l.bid_status === "sold") totalSold++;
                    else if (l.bid_status === "has_bids") totalBids++;
                    else totalNoBids++;
                    var soldPrice = l.soldBid > 0 ? window.bidSpiritCurrency + parseInt(l.soldBid).toLocaleString() : "—";
                    html += "<tr><td>" + name + "</td>"
                        + "<td>" + formatNumber(l.view_count) + "</td>"
                        + "<td>" + formatNumber(l.catalogue_clicks) + "</td>"
                        + "<td>" + formatNumber(l.external_clicks) + "</td>"
                        + "<td>" + formatNumber(l.favorite_count) + "</td>"
                        + "<td>" + formatNumber(l.share_count) + "</td>"
                        + "<td>" + statusBadge + "</td>"
                        + "<td>" + soldPrice + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="8" style="text-align:center;color:#666;">No data yet</td></tr>';
            }
            $("#la-conversion-tbody").html(html);
            var convTotal = totalSold + totalBids + totalNoBids;
            if (convTotal > 0) {
                $("#la-conversion-summary").html(
                    '<div class="af-stats-card" style="flex:1;padding:10px 14px;"><div class="af-card-label">Sold</div><div class="af-card-value" style="font-size:22px;color:#00a32a;">' + totalSold + '</div></div>' +
                    '<div class="af-stats-card" style="flex:1;padding:10px 14px;"><div class="af-card-label">Has Bids</div><div class="af-card-value" style="font-size:22px;color:#dba617;">' + totalBids + '</div></div>' +
                    '<div class="af-stats-card" style="flex:1;padding:10px 14px;"><div class="af-card-label">No Bids</div><div class="af-card-value" style="font-size:22px;color:#999;">' + totalNoBids + '</div></div>' +
                    '<div class="af-stats-card" style="flex:1;padding:10px 14px;"><div class="af-card-label">Sell-through</div><div class="af-card-value" style="font-size:22px;">' + (convTotal > 0 ? Math.round(totalSold/convTotal*100) : 0) + '%</div></div>'
                );
            }

            // Peak viewing times — tabbed by day of week. peak_times already
            // carries day_of_week + hour_of_day + views; consolidate per weekday
            // (last 30 days) with an "All days" view.
            if (typeof Chart !== "undefined") {
                var peakRows = (d.peak_times || []).map(function(pt) {
                    return { dow: pt.day_of_week, hour: pt.hour_of_day, val: pt.views };
                });
                renderDowHourly(peakRows, {
                    key: "la_peak", tabsId: "la-peak-dow-tabs", canvasId: "la-heatmap-chart",
                    chartVar: "heatmap", label: "Lot Views", summaryId: "la-peak-summary",
                    noun: "lot views", summarySuffix: "over " + laDays + " days"
                });
            }

            // Pre-sale vs Live
            html = "";
            if (d.pre_sale_vs_live && d.pre_sale_vs_live.length) {
                $.each(d.pre_sale_vs_live, function(i, a) {
                    var prePct = a.total_views > 0 ? Math.round(a.pre_sale_views / a.total_views * 100) : 0;
                    html += "<tr><td>" + (a.auction_name || "") + "</td>"
                        + "<td>" + formatNumber(a.pre_sale_views) + "</td>"
                        + "<td>" + formatNumber(a.live_views) + "</td>"
                        + "<td>" + formatNumber(a.total_views) + "</td>"
                        + "<td>" + prePct + "%</td></tr>";
                });
            } else {
                html = '<tr><td colspan="5" style="text-align:center;color:#666;">No auction date data available</td></tr>';
            }
            $("#la-presale-tbody").html(html);

            // Category performance
            html = "";
            if (d.categories && d.categories.length) {
                $.each(d.categories, function(i, c) {
                    var catName = c.category_name || ("Cat #" + c.categoryId);
                    html += "<tr><td>" + catName + "</td>"
                        + "<td>" + formatNumber(c.total_views) + "</td>"
                        + "<td>" + formatNumber(c.lot_count) + "</td>"
                        + "<td>" + formatNumber(c.total_favorites) + "</td>"
                        + "<td>" + formatNumber(c.sold_count) + "</td>"
                        + "<td>" + parseFloat(c.avg_views || 0).toFixed(1) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="6" style="text-align:center;color:#666;">No category data</td></tr>';
            }
            $("#la-categories-tbody").html(html);

            // Share analytics
            if (d.shares) {
                var chHtml = "";
                if (d.shares.channels && d.shares.channels.length) {
                    $.each(d.shares.channels, function(i, ch) {
                        var colors = {facebook:"#1877f2",twitter:"#1da1f2",whatsapp:"#25d366",email:"#ea4335",pinterest:"#bd081c",copy_link:"#666",unknown:"#999"};
                        var bg = colors[ch.channel] || "#999";
                        chHtml += '<span style="display:inline-block;padding:4px 10px;border-radius:3px;font-size:12px;font-weight:600;color:#fff;background:' + bg + ';margin:2px 4px 2px 0;">' + ch.channel + ': ' + ch.share_count + '</span>';
                    });
                } else {
                    chHtml = '<span style="color:#666;font-size:13px;">No shares tracked yet</span>';
                }
                $("#la-share-channels").html(chHtml);

                html = "";
                if (d.shares.top_lots && d.shares.top_lots.length) {
                    $.each(d.shares.top_lots, function(i, l) {
                        var name = l.lot_name || l.post_title || "Lot " + l.post_id;
                        html += "<tr><td>" + name + "</td><td>" + l.share_count + "</td><td>" + (l.channels || "") + "</td></tr>";
                    });
                } else {
                    html = '<tr><td colspan="3" style="text-align:center;color:#666;">No shares yet</td></tr>';
                }
                $("#la-shares-tbody").html(html);
            }

            // Search funnel
            html = "";
            if (d.search_funnel && d.search_funnel.length) {
                $.each(d.search_funnel, function(i, s) {
                    html += "<tr><td>" + s.query + "</td>"
                        + "<td>" + formatNumber(s.search_count) + "</td>"
                        + "<td>" + formatNumber(s.lot_views) + "</td>"
                        + "<td>" + formatNumber(s.unique_lots_viewed) + "</td></tr>";
                });
            } else {
                html = '<tr><td colspan="4" style="text-align:center;color:#666;">No search→view data yet</td></tr>';
            }
            $("#la-search-tbody").html(html);
        });
    }

    // Populate catalogue dropdown from auction data, grouped by Upcoming/Past
    function populateAuctionFilter(auctions) {
        var $sel = $("#la-auction-filter");
        var current = $sel.val();
        $sel.find("option:not(:first), optgroup").remove();
        if (auctions && auctions.length) {
            var upcoming = [], past = [];
            $.each(auctions, function(i, a) {
                if (parseInt(a.is_past)) {
                    past.push(a);
                } else {
                    upcoming.push(a);
                }
            });
            function sortByDate(arr) {
                return arr.sort(function(a, b) {
                    var da = a.auction_date || "", db = b.auction_date || "";
                    return db.localeCompare(da);
                });
            }
            upcoming = sortByDate(upcoming);
            past = sortByDate(past);

            function buildOption(a) {
                var label = (a.auction_name || "ID: " + a.term_id);
                var date = a.auction_date ? " \u2014 " + a.auction_date.substring(0, 10) : "";
                return '<option value="' + a.term_id + '">' + label + date + ' (' + formatNumber(a.total_views) + ' views)</option>';
            }

            if (upcoming.length) {
                var $grp = $('<optgroup label="Upcoming / Live"></optgroup>');
                $.each(upcoming, function(i, a) { $grp.append(buildOption(a)); });
                $sel.append($grp);
            }
            if (past.length) {
                var $grp2 = $('<optgroup label="Past Auctions"></optgroup>');
                $.each(past, function(i, a) { $grp2.append(buildOption(a)); });
                $sel.append($grp2);
            }
        }
        if (current) $sel.val(current);
    }

    $("#la-auction-filter").on("change", function() { loadLotAnalytics(); });
    $("#la-refresh").on("click", function() { loadLotAnalytics(); });
    $("#la-backfill").on("click", function() {
        if (!confirm("Backfill lot analytics from existing pageview data? This may take a moment.")) return;
        $("#la-status").text("Backfilling...");
        $.post(ajaxurl, { action: "af_lot_analytics_backfill", nonce: nonce }, function(resp) {
            $("#la-status").text(resp.success ? resp.data.message : "Error");
            if (resp.success) loadLotAnalytics();
        });
    });

    // CSV Export
    $("#la-export-csv").on("click", function() {
        var termId = $("#la-auction-filter").val() || "";
        $("#la-export-status").text("Generating...");
        $.post(ajaxurl, { action: "af_lot_analytics_export", nonce: nonce, term_id: termId }, function(resp) {
            if (!resp.success || !resp.data.rows || !resp.data.rows.length) {
                $("#la-export-status").text("No data to export");
                return;
            }
            var rows = resp.data.rows;
            var headers = Object.keys(rows[0]);
            var csv = headers.join(",") + "\n";
            $.each(rows, function(i, row) {
                var vals = [];
                $.each(headers, function(j, h) {
                    var v = (row[h] === null || row[h] === undefined) ? "" : String(row[h]);
                    vals.push('"' + v.replace(/"/g, '""'). replace(/\n/g, " ") + '"');
                });
                csv += vals.join(",") + "\n";
            });
            var blob = new Blob([csv], { type: "text/csv;charset=utf-8;" });
            var link = document.createElement("a");
            link.href = URL.createObjectURL(blob);
            link.download = "lot-analytics" + (termId ? "-auction-" + termId : "") + ".csv";
            link.click();
            $("#la-export-status").text("Downloaded!");
            setTimeout(function() { $("#la-export-status").text(""); }, 3000);
        });
    });

    // ==================== INIT ====================
    setDateRange(30);
    loadDashboard();

})(jQuery);
</script>
