<?php
/**
 * Plugin Name: Store Analytics Lite for WooCommerce (KPI Dashboard & Reports)
 * Plugin URI: https://auscomp.com/store-analytics-for-woocommerce
 * Description: Visual WooCommerce analytics with 6 core KPIs. 100% private—processed locally. Upgrade to PRO for 8 additional advanced KPIs.
 * Version: 2.2.3
 * Author: Auscomp
 * Author URI: https://auscomp.com
 * Requires at least: 6.0
 * Requires PHP: 7.4
 * Requires Plugins: woocommerce
 * WC requires at least: 6.0
 * WC tested up to: 9.0
 * Tested up to: 6.8
 * Text Domain: store-analytics-woo-lite
 * Domain Path: /languages
 * License: GPL-2.0-or-later
 */

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

class Store_Analytics_Dashboard_Lite {
    const SLUG  = 'store-analytics-woo-lite';
    const NONCE = 'spd_nonce';

    public function __construct() {
        // Delay until after other plugins (incl. WooCommerce) are loaded
        add_action('plugins_loaded', [$this, 'bootstrap'], 11);
    }

    public function bootstrap() {
        add_action('admin_menu',            [$this,'menu']);
        add_action('admin_enqueue_scripts', [$this,'enqueue']);
        add_action('wp_ajax_spd_get_metrics', [$this,'ajax_metrics']);
    }

    public function woocommerce_missing_notice() {
        echo '<div class="notice notice-error"><p>'
           . esc_html__('Store Analytics Lite for WooCommerce requires WooCommerce to be installed and activated.', 'store-analytics-woo-lite')
           . '</p></div>';
    }

    public function menu() {
        // Prefer WooCommerce cap; fall back so admins still see the menu even if WC caps aren't present
        $cap = current_user_can('manage_woocommerce') ? 'manage_woocommerce' : 'manage_options';

        add_menu_page(
            'Store Analytics Lite',
            'Store Analytics Lite',
            $cap,
            self::SLUG,
            [$this,'route'],                // <- route, not page (see next block)
            'dashicons-chart-pie',
            56
        );
    }



    public function enqueue($hook){
        if ($hook !== 'toplevel_page_'.self::SLUG) return;

        $cssv = @filemtime(plugin_dir_path(__FILE__).'assets/css/admin.css') ?: '2.2.1';
        $jsv  = @filemtime(plugin_dir_path(__FILE__).'assets/js/dashboard.js') ?: '2.2.1';

        // Styles
        wp_enqueue_style(self::SLUG.'-css', plugins_url('assets/css/admin.css', __FILE__), [], $cssv);

        // Chart.js (bundled locally for production)
        wp_enqueue_script('chartjs', plugins_url('assets/vendor/chartjs/chart.umd.js', __FILE__), [], '4.5.0', true);

        // jsVectorMap (MIT) – local copies
        wp_enqueue_style('jsvectormap-css', plugins_url('assets/vendor/jsvectormap/jsvectormap.min.css', __FILE__), [], '1.5.3');
        wp_enqueue_script('jsvectormap', plugins_url('assets/vendor/jsvectormap/jsvectormap.min.js', __FILE__), [], '1.5.3', true);
        wp_enqueue_script('jsvectormap-world', plugins_url('assets/vendor/jsvectormap/maps/world-merc.js', __FILE__), ['jsvectormap'], '1.5.3', true);

        // Our dashboard
        wp_enqueue_script(self::SLUG.'-js', plugins_url('assets/js/dashboard.js', __FILE__), ['jquery','chartjs','jsvectormap','jsvectormap-world'], $jsv, true);

        $currency = function_exists('get_woocommerce_currency') ? get_woocommerce_currency() : 'USD';
        wp_localize_script(self::SLUG.'-js','SPD',[
            'ajax'     => admin_url('admin-ajax.php'),
            'nonce'    => wp_create_nonce(self::NONCE),
            'currency' => $currency ?: 'USD',
            'version'  => '2.2.3',
            'plugin_url' => plugins_url('', __FILE__) . '/',
        ]);
    }

    public function route() {
        if (!class_exists('WooCommerce')) {
            $this->woocommerce_missing_notice();
            return;
        }
        $this->page();
    }

    public function page(){ ?>
        <div id="spd-root" class="spd-wrap spd-dark">
            <div class="spd-header">
                <h1 class="spd-title"><?php esc_html_e('Store Analytics Lite - KPI Dashboard', 'store-analytics-woo-lite'); ?></h1>
                <div class="spd-controls">
                    <select id="spd-period" class="spd-select">
                        <option value="today"><?php esc_html_e('Today', 'store-analytics-woo-lite'); ?></option>
                        <option value="yesterday"><?php esc_html_e('Yesterday', 'store-analytics-woo-lite'); ?></option>
                        <option value="this_week"><?php esc_html_e('This week', 'store-analytics-woo-lite'); ?></option>
                        <option value="last_week"><?php esc_html_e('Last week', 'store-analytics-woo-lite'); ?></option>
                        <option value="month_to_date"><?php esc_html_e('Month to date', 'store-analytics-woo-lite'); ?></option>
                        <option value="last_30" selected><?php esc_html_e('Last 30 days', 'store-analytics-woo-lite'); ?></option>
                        <option value="last_month"><?php esc_html_e('Last month', 'store-analytics-woo-lite'); ?></option>
                        <option value="this_quarter"><?php esc_html_e('This quarter', 'store-analytics-woo-lite'); ?></option>
                        <option value="last_quarter"><?php esc_html_e('Last quarter', 'store-analytics-woo-lite'); ?></option>
                        <option value="this_year"><?php esc_html_e('This year', 'store-analytics-woo-lite'); ?></option>
                        <option value="last_year"><?php esc_html_e('Last year', 'store-analytics-woo-lite'); ?></option>
                    </select>
                    <button id="spd-mode-toggle" class="button" title="<?php esc_attr_e('Toggle dark/light', 'store-analytics-woo-lite'); ?>">🌗</button>
                    <button id="spd-about-toggle" class="button" title="<?php esc_attr_e('About', 'store-analytics-woo-lite'); ?>">ℹ️</button>
                    <button id="spd-settings-toggle" class="button" title="<?php esc_attr_e('Dashboard settings', 'store-analytics-woo-lite'); ?>">⚙️</button>
                </div>
            </div>
            <div id="spd-grid" class="spd-grid"></div>
            
            <!-- Settings Panel -->
            <div id="spd-settings-panel" class="spd-settings-panel">
                <div class="spd-settings-header">
                    <h3><?php esc_html_e('Dashboard Settings', 'store-analytics-woo-lite'); ?></h3>
                    <button id="spd-settings-close" class="spd-settings-close">×</button>
                </div>
                <div class="spd-settings-content">
                    <div class="spd-settings-section">
                        <h4><?php esc_html_e('KPI Cards', 'store-analytics-woo-lite'); ?></h4>
                        <div id="spd-card-settings" class="spd-card-settings">
                            <!-- Card settings will be populated by JavaScript -->
                        </div>
                    </div>
                    <div class="spd-settings-actions">
                        <button id="spd-settings-reset" class="button"><?php esc_html_e('Reset to Default', 'store-analytics-woo-lite'); ?></button>
                        <button id="spd-settings-save" class="button button-primary"><?php esc_html_e('Save Settings', 'store-analytics-woo-lite'); ?></button>
                    </div>
                </div>
            </div>
            <div id="spd-settings-overlay" class="spd-settings-overlay"></div>
            
            <!-- About Panel -->
            <div id="spd-about-panel" class="spd-about-panel">
                <div class="spd-about-header">
                    <h3><?php esc_html_e('About', 'store-analytics-woo-lite'); ?></h3>
                    <button id="spd-about-close" class="spd-about-close">×</button>
                </div>
                <div class="spd-about-content">
                    <div class="spd-about-section">
                        <p><?php esc_html_e('A fast, privacy-friendly analytics dashboard for WooCommerce stores. Designed and built by Auscomp.', 'store-analytics-woo-lite'); ?></p>
                    </div>
                    <div class="spd-about-section">
                        <h4><?php esc_html_e('Legal', 'store-analytics-woo-lite'); ?></h4>
                        <p><?php 
                        /* translators: %s: Current year */
                        printf(esc_html__('© %s Auscomp.com. All rights reserved.', 'store-analytics-woo-lite'), esc_html(gmdate('Y'))); 
                        ?></p>
                    </div>
                    <div class="spd-about-section">
                        <h4><?php esc_html_e('Links', 'store-analytics-woo-lite'); ?></h4>
                        <p><a href="https://auscomp.com/product/store-analytics-for-woocommerce" target="_blank"><?php esc_html_e('Product page', 'store-analytics-woo-lite'); ?></a> | <a href="https://auscomp.com/legal" target="_blank"><?php esc_html_e('Legal', 'store-analytics-woo-lite'); ?></a></p>
                    </div>
                    <div class="spd-about-section">
                        <h4><?php esc_html_e('Data & Privacy', 'store-analytics-woo-lite'); ?></h4>
                        <p><?php esc_html_e('All metrics are computed locally from your WooCommerce database. No store data is transmitted to Auscomp or third parties. All assets are now bundled locally for maximum privacy.', 'store-analytics-woo-lite'); ?></p>
                    </div>
                </div>
            </div>
            <div id="spd-about-overlay" class="spd-about-overlay"></div>
        </div>
    <?php }

    private function dt_now() {
        return new DateTime('now', wp_timezone());
    }

    private function get_range($period) {
        $now = $this->dt_now();
        
        if ($period === 'today') {
            $start = (clone $now)->setTime(0, 0, 0);
            $end = (clone $now);
            $cmp_start = (clone $start)->modify('-7 days');
            $cmp_end = (clone $end)->modify('-7 days');
        } elseif ($period === 'yesterday') {
            $start = (clone $now)->modify('-1 day')->setTime(0, 0, 0);
            $end = (clone $now)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $start)->modify('-7 days');
            $cmp_end = (clone $end)->modify('-7 days');
        } elseif ($period === 'this_week') {
            $start = (clone $now)->modify('monday this week')->setTime(0, 0, 0);
            $end = (clone $now);
            $days = $start->diff($end)->days + 1;
            $cmp_end = (clone $start)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $cmp_end)->modify("-" . ($days - 1) . " days")->setTime(0, 0, 0);
        } elseif ($period === 'last_week') {
            $start = (clone $now)->modify('monday last week')->setTime(0, 0, 0);
            $end = (clone $now)->modify('sunday last week')->setTime(23, 59, 59);
            $cmp_start = (clone $start)->modify('-7 days');
            $cmp_end = (clone $end)->modify('-7 days');
        } elseif ($period === 'last_30') {
            $start = (clone $now)->modify('-29 days')->setTime(0, 0, 0);
            $end = (clone $now);
            $cmp_end = (clone $start)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $cmp_end)->modify('-29 days')->setTime(0, 0, 0);
        } elseif ($period === 'last_month') {
            $start = (clone $now)->modify('first day of last month')->setTime(0, 0, 0);
            $end = (clone $now)->modify('last day of last month')->setTime(23, 59, 59);
            $cmp_start = (clone $start)->modify('first day of -1 month');
            $cmp_end = (clone $start)->modify('last day of -1 month')->setTime(23, 59, 59);
        } elseif ($period === 'this_quarter') {
            $quarter = ceil($now->format('n') / 3);
            $start = (clone $now)->modify("first day of january")->modify("+" . (($quarter - 1) * 3) . " months")->setTime(0, 0, 0);
            $end = (clone $now);
            $days = $start->diff($end)->days + 1;
            $cmp_end = (clone $start)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $cmp_end)->modify("-" . ($days - 1) . " days")->setTime(0, 0, 0);
        } elseif ($period === 'last_quarter') {
            $quarter = ceil($now->format('n') / 3);
            $start = (clone $now)->modify("first day of january")->modify("+" . (($quarter - 2) * 3) . " months")->setTime(0, 0, 0);
            $end = (clone $now)->modify("first day of january")->modify("+" . (($quarter - 1) * 3) . " months")->modify("-1 day")->setTime(23, 59, 59);
            $cmp_start = (clone $start)->modify('first day of -3 months');
            $cmp_end = (clone $start)->modify('last day of -3 months')->setTime(23, 59, 59);
        } elseif ($period === 'this_year') {
            $start = (clone $now)->modify('first day of january')->setTime(0, 0, 0);
            $end = (clone $now);
            $days = $start->diff($end)->days + 1;
            $cmp_end = (clone $start)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $cmp_end)->modify("-" . ($days - 1) . " days")->setTime(0, 0, 0);
        } elseif ($period === 'last_year') {
            $start = (clone $now)->modify('first day of january last year')->setTime(0, 0, 0);
            $end = (clone $now)->modify('last day of december last year')->setTime(23, 59, 59);
            $cmp_start = (clone $start)->modify('first day of january -1 year');
            $cmp_end = (clone $start)->modify('last day of december -1 year')->setTime(23, 59, 59);
        } else {
            $start = (clone $now)->modify('first day of this month')->setTime(0, 0, 0);
            $end = (clone $now);
            $days = $start->diff($end)->days + 1;
            $cmp_end = (clone $start)->modify('-1 day')->setTime(23, 59, 59);
            $cmp_start = (clone $cmp_end)->modify("-" . ($days - 1) . " days")->setTime(0, 0, 0);
        }
        
        return [$start, $end, $cmp_start, $cmp_end];
    }

    private function collect_orders($start, $end) {
        if (!class_exists('WC_Order_Query')) {
            return [];
        }
        $q = new WC_Order_Query([
            'status' => ['wc-processing', 'wc-completed'],
            'limit' => -1,
            'type' => 'shop_order',
            'return' => 'ids',
            'date_created' => $start->format('Y-m-d H:i:s') . '...' . $end->format('Y-m-d H:i:s'),
        ]);
        return array_map('wc_get_order', $q->get_orders());
    }

    private function moneyf($v) {
        return (float) wc_format_decimal($v, 2);
    }

    private function metrics($period='last_30'){
        list($start,$end,$cmp_start,$cmp_end) = $this->get_range($period);
        $orders     = $this->collect_orders($start,$end);
        $orders_cmp = $this->collect_orders($cmp_start,$cmp_end);

        $sum = function($orders, $cb) {
            $t = 0;
            foreach ($orders as $o) {
                $t += $cb($o);
            }
            return $t;
        };
        $rev = $this->moneyf($sum($orders, fn($o) => $o->get_total()));
        $rev_cmp = $this->moneyf($sum($orders_cmp, fn($o) => $o->get_total()));
        $cnt = count($orders);
        $cnt_cmp = count($orders_cmp);

        // daily series
        $labels = [];
        $series = [];
        $profit_series = [];
        $p = clone $start;
        while ($p <= $end) {
            $qs = (clone $p)->setTime(0, 0, 0);
            $qe = (clone $p)->setTime(23, 59, 59);
            $day = $this->collect_orders($qs, $qe);
            $day_revenue = $this->moneyf($sum($day, fn($o) => $o->get_total()));
            $day_shipping = $this->moneyf($sum($day, fn($o) => $o->get_shipping_total()));
            $day_pp = 0.0;
            foreach ($day as $o) {
                if (stripos($o->get_payment_method(), 'paypal') !== false) {
                    $day_pp += $o->get_total() * 0.029 + 0.30;
                }
            }
            $day_profit = $this->moneyf($day_revenue - ($day_shipping + $day_pp));
            $series[] = $day_revenue;
            $profit_series[] = $day_profit;
            $labels[] = $p->format('M j');
            $p->modify('+1 day');
        }
        
        $series_cmp = [];
        $profit_series_cmp = [];
        $p = clone $cmp_start;
        while ($p <= $cmp_end) {
            $qs = (clone $p)->setTime(0, 0, 0);
            $qe = (clone $p)->setTime(23, 59, 59);
            $day = $this->collect_orders($qs, $qe);
            $day_revenue = $this->moneyf($sum($day, fn($o) => $o->get_total()));
            $day_shipping = $this->moneyf($sum($day, fn($o) => $o->get_shipping_total()));
            $day_pp = 0.0;
            foreach ($day as $o) {
                if (stripos($o->get_payment_method(), 'paypal') !== false) {
                    $day_pp += $o->get_total() * 0.029 + 0.30;
                }
            }
            $day_profit = $this->moneyf($day_revenue - ($day_shipping + $day_pp));
            $series_cmp[] = $day_revenue;
            $profit_series_cmp[] = $day_profit;
            $p->modify('+1 day');
        }

        // categories
        $cats = [];
        foreach ($orders as $o) {
            foreach ($o->get_items() as $item) {
                $product = $item->get_product();
                if (!$product) continue;
                
                $terms = wp_get_post_terms($product->get_id(), 'product_cat');
                $qty = (int) $item->get_quantity();
                
                if (empty($terms)) {
                    $cats['Uncategorised'] = ($cats['Uncategorised'] ?? 0) + $qty;
                } else {
                    foreach ($terms as $t) {
                        $cats[$t->name] = ($cats[$t->name] ?? 0) + $qty;
                    }
                }
            }
        }
        arsort($cats);
        $cats = array_slice($cats, 0, 8, true);

        // countries (robust: shipping → billing → geolocated IP)
        $countries = [];
        foreach ($orders as $o) {
            $c = $o->get_shipping_country();
            if (empty($c)) {
                $c = $o->get_billing_country();
            }

            if (empty($c) && class_exists('WC_Geolocation')) {
                $ip = method_exists($o, 'get_customer_ip_address') ? $o->get_customer_ip_address() : (method_exists($o, 'get_customer_ip') ? $o->get_customer_ip() : '');
                if (!$ip) {
                    $ip = (string) $o->get_meta('_customer_ip_address', true);
                }
                if ($ip) {
                    $geo = WC_Geolocation::geolocate_ip($ip);
                    if (!empty($geo['country'])) {
                        $c = $geo['country'];
                    }
                }
            }

            if ($c === 'UK') {
                $c = 'GB'; // normalize
            }
            if (is_string($c) && strlen($c) === 2) {
                $countries[$c] = ($countries[$c] ?? 0) + (float) $o->get_total();
            }
        }
        arsort($countries);
        $countries = array_slice($countries, 0, 60, true);

        // products
        $prod = [];
        foreach ($orders as $o) {
            foreach ($o->get_items() as $item) {
                $pid = $item->get_product_id();
                $name = $item->get_name();
                $lt = (float) $item->get_total();
                if (!isset($prod[$pid])) {
                    $prod[$pid] = ['name' => $name, 'revenue' => 0.0];
                }
                $prod[$pid]['revenue'] += $lt;
            }
        }
        uasort($prod, fn($a, $b) => $b['revenue'] <=> $a['revenue']);
        $top = array_slice($prod, 0, 5, true);

        $aov = $cnt ? round($rev / $cnt, 2) : 0.0;

        // profit (rough)
        $shipping = $this->moneyf($sum($orders, fn($o) => $o->get_shipping_total()));
        $pp = 0.0;
        foreach ($orders as $o) {
            if (stripos($o->get_payment_method(), 'paypal') !== false) {
                $pp += $o->get_total() * 0.029 + 0.30;
            }
        }
        $net = $this->moneyf($rev - ($shipping + $pp));
        
        $shipping_cmp = $this->moneyf($sum($orders_cmp, fn($o) => $o->get_shipping_total()));
        $ppc = 0.0;
        foreach ($orders_cmp as $o) {
            if (stripos($o->get_payment_method(), 'paypal') !== false) {
                $ppc += $o->get_total() * 0.029 + 0.30;
            }
        }
        $net_cmp = $this->moneyf($rev_cmp - ($shipping_cmp + $ppc));
        $margin = $rev > 0 ? round(($net / $rev) * 100, 2) : 0;
        $np_vs = $net_cmp > 0 ? round((($net - $net_cmp) / $net_cmp) * 100, 2) : null;

        // refund rate calculation
        $refund_total = $this->moneyf($sum($orders, fn($o) => $o->get_total_refunded()));
        $refund_orders = 0;
        foreach ($orders as $o) {
            if ($o->get_total_refunded() > 0) {
                $refund_orders++;
            }
        }
        $refund_rate = $rev > 0 ? round(($refund_total / $rev) * 100, 2) : 0;
        
        // comparison period refunds
        $refund_total_cmp = $this->moneyf($sum($orders_cmp, fn($o) => $o->get_total_refunded()));
        $refund_orders_cmp = 0;
        foreach ($orders_cmp as $o) {
            if ($o->get_total_refunded() > 0) {
                $refund_orders_cmp++;
            }
        }
        $refund_rate_cmp = $rev_cmp > 0 ? round(($refund_total_cmp / $rev_cmp) * 100, 2) : 0;
        $refund_rate_vs = $refund_rate_cmp > 0 ? round((($refund_rate - $refund_rate_cmp) / $refund_rate_cmp) * 100, 2) : 0;

        // Day-of-week / hour heatmap calculation
        $heatmap = [];
        $weekdays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
        
        // Initialize heatmap array (7 days x 24 hours)
        foreach ($weekdays as $day) {
            $heatmap[$day] = array_fill(0, 24, 0);
        }
        
        // Group orders by weekday and hour
        foreach ($orders as $order) {
            $date = $order->get_date_created();
            if ($date) {
                $weekday = $date->format('l'); // Full day name
                $hour = (int) $date->format('G'); // 24-hour format without leading zero
                $heatmap[$weekday][$hour]++;
            }
        }
        
        // Convert to array format for JSON
        $heatmap_data = [];
        foreach ($weekdays as $day) {
            $heatmap_data[$day] = array_values($heatmap[$day]);
        }

        // Payment method share calculation
        $payment_methods = [];
        $payment_methods_cmp = [];
        
        // Current period
        foreach ($orders as $order) {
            $method = $order->get_payment_method();
            $method_title = $order->get_payment_method_title();
            $key = !empty($method_title) ? $method_title : $method;
            
            if (!isset($payment_methods[$key])) {
                $payment_methods[$key] = ['revenue' => 0, 'orders' => 0];
            }
            $payment_methods[$key]['revenue'] += (float) $order->get_total();
            $payment_methods[$key]['orders']++;
        }
        
        // Comparison period
        foreach ($orders_cmp as $order) {
            $method = $order->get_payment_method();
            $method_title = $order->get_payment_method_title();
            $key = !empty($method_title) ? $method_title : $method;
            
            if (!isset($payment_methods_cmp[$key])) {
                $payment_methods_cmp[$key] = ['revenue' => 0, 'orders' => 0];
            }
            $payment_methods_cmp[$key]['revenue'] += (float) $order->get_total();
            $payment_methods_cmp[$key]['orders']++;
        }
        
        // Calculate percentages and trends
        $payment_share = [];
        foreach ($payment_methods as $method => $data) {
            $revenue_pct = $rev > 0 ? round(($data['revenue'] / $rev) * 100, 1) : 0;
            $orders_pct = $cnt > 0 ? round(($data['orders'] / $cnt) * 100, 1) : 0;
            
            // Get comparison data
            $cmp_data = $payment_methods_cmp[$method] ?? ['revenue' => 0, 'orders' => 0];
            $revenue_vs = $cmp_data['revenue'] > 0 ? round((($data['revenue'] - $cmp_data['revenue']) / $cmp_data['revenue']) * 100, 1) : 0;
            $orders_vs = $cmp_data['orders'] > 0 ? round((($data['orders'] - $cmp_data['orders']) / $cmp_data['orders']) * 100, 1) : 0;
            
            $payment_share[$method] = [
                'revenue' => $data['revenue'],
                'revenue_pct' => $revenue_pct,
                'revenue_vs' => $revenue_vs,
                'orders' => $data['orders'],
                'orders_pct' => $orders_pct,
                'orders_vs' => $orders_vs
            ];
        }
        
        // Sort by revenue percentage
        uasort($payment_share, function($a, $b) {
            return $b['revenue_pct'] <=> $a['revenue_pct'];
        });

        // New vs Returning customers calculation
        $new_customers = [];
        $returning_customers = [];
        $all_customer_orders = [];
        
        // Collect all customer orders for the period
        foreach ($orders as $order) {
            $customer_id = $order->get_customer_id();
            if ($customer_id > 0) {
                if (!isset($all_customer_orders[$customer_id])) {
                    $all_customer_orders[$customer_id] = [];
                }
                $all_customer_orders[$customer_id][] = $order;
            }
        }
        
        // Determine new vs returning customers
        foreach ($all_customer_orders as $customer_id => $customer_orders) {
            // Check if this customer had any orders before the current period
            $first_order_date = null;
            foreach ($customer_orders as $order) {
                $order_date = $order->get_date_created();
                if (!$first_order_date || $order_date < $first_order_date) {
                    $first_order_date = $order_date;
                }
            }
            
            // Check if customer had orders before the current period
            $had_previous_orders = false;
            if ($first_order_date && $first_order_date > $start) {
                // Check if customer had orders before the current period start
                $previous_orders = $this->collect_orders(
                    (clone $start)->modify('-10 years'), // Look back far enough
                    (clone $start)->modify('-1 second')
                );
                
                foreach ($previous_orders as $prev_order) {
                    if ($prev_order->get_customer_id() == $customer_id) {
                        $had_previous_orders = true;
                        break;
                    }
                }
            }
            
            // Categorize customer orders
            if ($had_previous_orders) {
                foreach ($customer_orders as $order) {
                    $returning_customers[] = $order;
                }
            } else {
                foreach ($customer_orders as $order) {
                    $new_customers[] = $order;
                }
            }
        }
        
        // Calculate metrics for new customers
        $new_customer_revenue = $this->moneyf($sum($new_customers, fn($o) => $o->get_total()));
        $new_customer_orders = count($new_customers);
        $new_customer_revenue_pct = $rev > 0 ? round(($new_customer_revenue / $rev) * 100, 1) : 0;
        $new_customer_orders_pct = $cnt > 0 ? round(($new_customer_orders / $cnt) * 100, 1) : 0;
        
        // Calculate metrics for returning customers
        $returning_customer_revenue = $this->moneyf($sum($returning_customers, fn($o) => $o->get_total()));
        $returning_customer_orders = count($returning_customers);
        $returning_customer_revenue_pct = $rev > 0 ? round(($returning_customer_revenue / $rev) * 100, 1) : 0;
        $returning_customer_orders_pct = $cnt > 0 ? round(($returning_customer_orders / $cnt) * 100, 1) : 0;
        
        // Comparison period calculations
        $new_customers_cmp = [];
        $returning_customers_cmp = [];
        $all_customer_orders_cmp = [];
        
        // Collect all customer orders for comparison period
        foreach ($orders_cmp as $order) {
            $customer_id = $order->get_customer_id();
            if ($customer_id > 0) {
                if (!isset($all_customer_orders_cmp[$customer_id])) {
                    $all_customer_orders_cmp[$customer_id] = [];
                }
                $all_customer_orders_cmp[$customer_id][] = $order;
            }
        }
        
        // Determine new vs returning customers for comparison period
        foreach ($all_customer_orders_cmp as $customer_id => $customer_orders) {
            // Check if this customer had any orders before the comparison period
            $first_order_date = null;
            foreach ($customer_orders as $order) {
                $order_date = $order->get_date_created();
                if (!$first_order_date || $order_date < $first_order_date) {
                    $first_order_date = $order_date;
                }
            }
            
            // Check if customer had orders before the comparison period
            $had_previous_orders = false;
            if ($first_order_date && $first_order_date > $cmp_start) {
                // Check if customer had orders before the comparison period start
                $previous_orders = $this->collect_orders(
                    (clone $cmp_start)->modify('-10 years'), // Look back far enough
                    (clone $cmp_start)->modify('-1 second')
                );
                
                foreach ($previous_orders as $prev_order) {
                    if ($prev_order->get_customer_id() == $customer_id) {
                        $had_previous_orders = true;
                        break;
                    }
                }
            }
            
            // Categorize customer orders
            if ($had_previous_orders) {
                foreach ($customer_orders as $order) {
                    $returning_customers_cmp[] = $order;
                }
            } else {
                foreach ($customer_orders as $order) {
                    $new_customers_cmp[] = $order;
                }
            }
        }
        
        // Calculate comparison metrics
        $new_customer_revenue_cmp = $this->moneyf($sum($new_customers_cmp, fn($o) => $o->get_total()));
        $new_customer_orders_cmp = count($new_customers_cmp);
        $returning_customer_revenue_cmp = $this->moneyf($sum($returning_customers_cmp, fn($o) => $o->get_total()));
        $returning_customer_orders_cmp = count($returning_customers_cmp);
        
        // Calculate trends
        $new_customer_revenue_vs = $new_customer_revenue_cmp > 0 ? round((($new_customer_revenue - $new_customer_revenue_cmp) / $new_customer_revenue_cmp) * 100, 1) : 0;
        $new_customer_orders_vs = $new_customer_orders_cmp > 0 ? round((($new_customer_orders - $new_customer_orders_cmp) / $new_customer_orders_cmp) * 100, 1) : 0;
        $returning_customer_revenue_vs = $returning_customer_revenue_cmp > 0 ? round((($returning_customer_revenue - $returning_customer_revenue_cmp) / $returning_customer_revenue_cmp) * 100, 1) : 0;
        $returning_customer_orders_vs = $returning_customer_orders_cmp > 0 ? round((($returning_customer_orders - $returning_customer_orders_cmp) / $returning_customer_orders_cmp) * 100, 1) : 0;

        // Coupon/discount impact calculation
        $coupons = [];
        $coupons_cmp = [];
        $total_discount = 0.0;
        $total_discount_cmp = 0.0;
        $orders_with_coupons = 0;
        $orders_with_coupons_cmp = 0;
        
        // Current period coupon analysis
        foreach ($orders as $order) {
            $order_discount = 0.0;
            $order_coupons = [];
            
            // Get coupon codes and amounts from order
            $coupon_codes = $order->get_coupon_codes();
            $discount_total = (float) $order->get_discount_total();
            
            if (!empty($coupon_codes) && $discount_total > 0) {
                // Distribute discount among coupons (simple equal distribution)
                $discount_per_coupon = $discount_total / count($coupon_codes);
                
                foreach ($coupon_codes as $coupon_code) {
                    $order_discount += $discount_per_coupon;
                    $order_coupons[] = $coupon_code;
                    
                    if (!isset($coupons[$coupon_code])) {
                        $coupons[$coupon_code] = ['amount' => 0.0, 'orders' => 0, 'revenue' => 0.0];
                    }
                    $coupons[$coupon_code]['amount'] += $discount_per_coupon;
                    $coupons[$coupon_code]['orders']++;
                    $coupons[$coupon_code]['revenue'] += (float) $order->get_total();
                }
                
                $total_discount += $order_discount;
                $orders_with_coupons++;
            }
        }
        
        // Comparison period coupon analysis
        foreach ($orders_cmp as $order) {
            $order_discount = 0.0;
            $order_coupons = [];
            
            // Get coupon codes and amounts from order
            $coupon_codes = $order->get_coupon_codes();
            $discount_total = (float) $order->get_discount_total();
            
            if (!empty($coupon_codes) && $discount_total > 0) {
                // Distribute discount among coupons (simple equal distribution)
                $discount_per_coupon = $discount_total / count($coupon_codes);
                
                foreach ($coupon_codes as $coupon_code) {
                    $order_discount += $discount_per_coupon;
                    $order_coupons[] = $coupon_code;
                    
                    if (!isset($coupons_cmp[$coupon_code])) {
                        $coupons_cmp[$coupon_code] = ['amount' => 0.0, 'orders' => 0, 'revenue' => 0.0];
                    }
                    $coupons_cmp[$coupon_code]['amount'] += $discount_per_coupon;
                    $coupons_cmp[$coupon_code]['orders']++;
                    $coupons_cmp[$coupon_code]['revenue'] += (float) $order->get_total();
                }
                
                $total_discount_cmp += $order_discount;
                $orders_with_coupons_cmp++;
            }
        }
        
        // Calculate coupon metrics
        $avg_discount_pct = $rev > 0 ? round(($total_discount / $rev) * 100, 2) : 0;
        $avg_discount_pct_cmp = $rev_cmp > 0 ? round(($total_discount_cmp / $rev_cmp) * 100, 2) : 0;
        $discount_vs = $avg_discount_pct_cmp > 0 ? round((($avg_discount_pct - $avg_discount_pct_cmp) / $avg_discount_pct_cmp) * 100, 1) : 0;
        
        // Sort coupons by amount
        uasort($coupons, function($a, $b) {
            return $b['amount'] <=> $a['amount'];
        });
        $top_coupons = array_slice($coupons, 0, 5, true);
        
        // Calculate coupon uplift (revenue generated with coupons)
        $coupon_uplift = 0.0;
        foreach ($coupons as $coupon_code => $data) {
            $coupon_uplift += $data['revenue'];
        }
        
        $coupon_uplift_cmp = 0.0;
        foreach ($coupons_cmp as $coupon_code => $data) {
            $coupon_uplift_cmp += $data['revenue'];
        }
        
        $coupon_uplift_vs = $coupon_uplift_cmp > 0 ? round((($coupon_uplift - $coupon_uplift_cmp) / $coupon_uplift_cmp) * 100, 1) : 0;

        // Returns by product calculation
        $product_returns = [];
        $product_sales = [];
        $total_refunded_amount = 0.0;
        $total_refunded_qty = 0;
        
        // Collect sales data for all products
        foreach ($orders as $order) {
            foreach ($order->get_items() as $item) {
                $product_id = $item->get_product_id();
                $product_name = $item->get_name();
                $qty = (int) $item->get_quantity();
                $total = (float) $item->get_total();
                
                if (!isset($product_sales[$product_id])) {
                    $product_sales[$product_id] = [
                        'name' => $product_name,
                        'qty' => 0,
                        'amount' => 0.0
                    ];
                }
                $product_sales[$product_id]['qty'] += $qty;
                $product_sales[$product_id]['amount'] += $total;
            }
        }
        
        // Collect refund data
        foreach ($orders as $order) {
            if ($order->get_total_refunded() > 0) {
                $refunds = $order->get_refunds();
                foreach ($refunds as $refund) {
                    foreach ($refund->get_items() as $refund_item) {
                        $product_id = $refund_item->get_product_id();
                        $product_name = $refund_item->get_name();
                        $refunded_qty = (int) $refund_item->get_quantity();
                        $refunded_amount = (float) $refund_item->get_total();
                        
                        if (!isset($product_returns[$product_id])) {
                            $product_returns[$product_id] = [
                                'name' => $product_name,
                                'qty' => 0,
                                'amount' => 0.0
                            ];
                        }
                        $product_returns[$product_id]['qty'] += $refunded_qty;
                        $product_returns[$product_id]['amount'] += $refunded_amount;
                        
                        $total_refunded_amount += $refunded_amount;
                        $total_refunded_qty += $refunded_qty;
                    }
                }
            }
        }
        
        // Calculate return rates and combine data
        $returns_by_product = [];
        foreach ($product_returns as $product_id => $return_data) {
            $sales_data = $product_sales[$product_id] ?? ['qty' => 0, 'amount' => 0.0];
            
            $qty_rate = $sales_data['qty'] > 0 ? round(($return_data['qty'] / $sales_data['qty']) * 100, 2) : 0;
            $amount_rate = $sales_data['amount'] > 0 ? round(($return_data['amount'] / $sales_data['amount']) * 100, 2) : 0;
            
            $returns_by_product[$product_id] = [
                'name' => $return_data['name'],
                'refunded_qty' => $return_data['qty'],
                'refunded_amount' => $return_data['amount'],
                'sold_qty' => $sales_data['qty'],
                'sold_amount' => $sales_data['amount'],
                'qty_rate' => $qty_rate,
                'amount_rate' => $amount_rate
            ];
        }
        
        // Sort by refunded amount
        uasort($returns_by_product, function($a, $b) {
            return $b['refunded_amount'] <=> $a['refunded_amount'];
        });
        
        $top_returns = array_slice($returns_by_product, 0, 8, true);
        
        // Calculate overall return rate
        $total_sold_amount = array_sum(array_column($product_sales, 'amount'));
        $overall_return_rate = $total_sold_amount > 0 ? round(($total_refunded_amount / $total_sold_amount) * 100, 2) : 0;

        // Repeat purchase rate calculation
        $customer_order_counts = [];
        $customer_order_counts_cmp = [];
        
        // Count orders per customer for current period
        foreach ($orders as $order) {
            $customer_id = $order->get_customer_id();
            if ($customer_id > 0) {
                if (!isset($customer_order_counts[$customer_id])) {
                    $customer_order_counts[$customer_id] = 0;
                }
                $customer_order_counts[$customer_id]++;
            }
        }
        
        // Count orders per customer for comparison period
        foreach ($orders_cmp as $order) {
            $customer_id = $order->get_customer_id();
            if ($customer_id > 0) {
                if (!isset($customer_order_counts_cmp[$customer_id])) {
                    $customer_order_counts_cmp[$customer_id] = 0;
                }
                $customer_order_counts_cmp[$customer_id]++;
            }
        }
        
        // Calculate repeat purchase rate for current period
        $total_customers = count($customer_order_counts);
        $repeat_customers = 0;
        foreach ($customer_order_counts as $customer_id => $order_count) {
            if ($order_count >= 2) {
                $repeat_customers++;
            }
        }
        $repeat_purchase_rate = $total_customers > 0 ? round(($repeat_customers / $total_customers) * 100, 1) : 0;
        
        // Calculate repeat purchase rate for comparison period
        $total_customers_cmp = count($customer_order_counts_cmp);
        $repeat_customers_cmp = 0;
        foreach ($customer_order_counts_cmp as $customer_id => $order_count) {
            if ($order_count >= 2) {
                $repeat_customers_cmp++;
            }
        }
        $repeat_purchase_rate_cmp = $total_customers_cmp > 0 ? round(($repeat_customers_cmp / $total_customers_cmp) * 100, 1) : 0;
        
        // Calculate trend
        $repeat_purchase_rate_vs = $repeat_purchase_rate_cmp > 0 ? round((($repeat_purchase_rate - $repeat_purchase_rate_cmp) / $repeat_purchase_rate_cmp) * 100, 1) : 0;

        return [
            'period' => $period,
            'series' => [
                'labels' => $labels,
                'this' => $series,
                'compare' => $series_cmp
            ],
            'profit_series' => [
                'labels' => $labels,
                'this' => $profit_series,
                'compare' => $profit_series_cmp
            ],
            'headline' => [
                'sales' => $rev,
                'sales_vs' => ($rev_cmp > 0 ? round((($rev - $rev_cmp) / $rev_cmp) * 100, 2) : 0),
                'orders' => $cnt,
                'orders_vs' => ($cnt_cmp > 0 ? round((($cnt - $cnt_cmp) / $cnt_cmp) * 100, 2) : 0)
            ],
            'breakdown' => [
                'orders_by_category' => $cats,
                'sales_by_country' => $countries,
                'top_products' => $top
            ],
            'aov' => $aov,
            'profit' => [
                'net' => $net,
                'margin' => $margin,
                'vs_pct' => $np_vs
            ],
            'refunds' => [
                'rate' => $refund_rate,
                'rate_vs' => $refund_rate_vs,
                'total' => $refund_total,
                'orders' => $refund_orders,
                'orders_cmp' => $refund_orders_cmp
            ],
            'heatmap' => $heatmap_data,
            'payment_methods' => $payment_share,
            'coupons' => [
                'total_discount' => $total_discount,
                'avg_discount_pct' => $avg_discount_pct,
                'discount_vs' => $discount_vs,
                'orders_with_coupons' => $orders_with_coupons,
                'orders_with_coupons_cmp' => $orders_with_coupons_cmp,
                'coupon_uplift' => $coupon_uplift,
                'coupon_uplift_vs' => $coupon_uplift_vs,
                'top_coupons' => $top_coupons
            ],
            'returns_by_product' => [
                'overall_rate' => $overall_return_rate,
                'total_refunded_amount' => $total_refunded_amount,
                'total_refunded_qty' => $total_refunded_qty,
                'top_returns' => $top_returns
            ],
            'customers' => [
                'new' => [
                    'revenue' => $new_customer_revenue,
                    'revenue_pct' => $new_customer_revenue_pct,
                    'revenue_vs' => $new_customer_revenue_vs,
                    'orders' => $new_customer_orders,
                    'orders_pct' => $new_customer_orders_pct,
                    'orders_vs' => $new_customer_orders_vs
                ],
                'returning' => [
                    'revenue' => $returning_customer_revenue,
                    'revenue_pct' => $returning_customer_revenue_pct,
                    'revenue_vs' => $returning_customer_revenue_vs,
                    'orders' => $returning_customer_orders,
                    'orders_pct' => $returning_customer_orders_pct,
                    'orders_vs' => $returning_customer_orders_vs
                ]
            ],
            'repeat_purchase_rate' => [
                'rate' => $repeat_purchase_rate,
                'rate_vs' => $repeat_purchase_rate_vs,
                'total_customers' => $total_customers,
                'repeat_customers' => $repeat_customers,
                'total_customers_cmp' => $total_customers_cmp,
                'repeat_customers_cmp' => $repeat_customers_cmp
            ],
        ];
    }

    public function ajax_metrics() {
        check_ajax_referer(self::NONCE, 'nonce');
        $period = isset($_POST['period']) ? sanitize_text_field(wp_unslash($_POST['period'])) : 'last_30';
        wp_send_json_success($this->metrics($period));
    }
}
new Store_Analytics_Dashboard_Lite();
