<?php
// phpcs:disable WordPress.NamingConventions.PrefixAllGlobals
// phpcs:disable WordPress.Security.NonceVerification
// phpcs:disable WordPress.DB.PreparedSQL
// phpcs:disable WordPress.DB.DirectDatabaseQuery
// phpcs:disable WordPress.DB.SlowDBQuery
// phpcs:disable PluginCheck.Security.DirectDB
// phpcs:disable PluginCheck.CodeAnalysis
// phpcs:disable WordPressVIPMinimum
/**
 * GT BOGO Engine — Journey Intelligence Dashboard (Enterprise Edition)
 *
 * Customer lifecycle stage funnel, stage velocity, transition matrix,
 * cohort analysis, Conversion Guard deep metrics, win-back effectiveness,
 * stage projection, journey health score, and engagement distribution.
 *
 * Data layer: all queries cached with staggered transients (5-min TTL).
 * Visualizations: Chart.js donut + velocity bar chart.
 * Security: capability check, nonce-protected flush, escaped output throughout.
 *
 * @package GT_BOGO_Engine
 * @since   3.28.0
 */

if ( ! function_exists( 'gt_bogo_has_pro' ) || ! gt_bogo_has_pro() ) {
	gtbogo_upgrade_card(
		'Journey Intelligence',
		'Deep analytics on customer lifecycle progression — stage funnels, velocity analysis, transition matrices, cohort curves, Conversion Guard metrics, and win-back effectiveness. Identifies exactly which customers need intervention and which deals move them fastest.'
	);
	return;
}
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}
if ( ! current_user_can( 'manage_woocommerce' ) ) {
	wp_die( esc_html__( 'Insufficient permissions.', 'gt-bogo-engine' ) );
}

global $wpdb;

// ════════════════════════════════════════════════════════════════════════════════
// CONSTANTS & CONFIG
// ════════════════════════════════════════════════════════════════════════════════

$accent       = '#E10000';
$cache_ttl    = 5 * MINUTE_IN_SECONDS;
$profiles_tbl = $wpdb->prefix . 'gtbogo_customer_profiles';
$events_tbl   = $wpdb->prefix . 'gtbogo_lifecycle_events';
$rules_tbl    = $wpdb->prefix . 'gtbogo_rules';

$has_prof = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $profiles_tbl ) );
$has_evts = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $events_tbl ) );

$days = isset( $_GET['days'] ) ? absint( wp_unslash( $_GET['days'] ) ) : 30;
$days = in_array( $days, array( 7, 30, 60, 90 ), true ) ? $days : 30;

$stage_meta = array(
	'new'       => array(
		'label' => 'New',
		'color' => '#3b82f6',
		'icon'  => '✨',
		'desc'  => '1 order',
		'order' => 1,
	),
	'returning' => array(
		'label' => 'Returning',
		'color' => '#8b5cf6',
		'icon'  => '🔄',
		'desc'  => '2-3 orders',
		'order' => 2,
	),
	'loyal'     => array(
		'label' => 'Loyal',
		'color' => '#10b981',
		'icon'  => '💚',
		'desc'  => '4+ orders',
		'order' => 3,
	),
	'vip'       => array(
		'label' => 'VIP',
		'color' => '#f59e0b',
		'icon'  => '👑',
		'desc'  => 'High LTV',
		'order' => 4,
	),
	'at_risk'   => array(
		'label' => 'At Risk',
		'color' => '#f97316',
		'icon'  => '⚠️',
		'desc'  => '60+ days idle',
		'order' => 5,
	),
	'lapsed'    => array(
		'label' => 'Lapsed',
		'color' => '#ef4444',
		'icon'  => '😴',
		'desc'  => '90+ days idle',
		'order' => 6,
	),
	'unknown'   => array(
		'label' => 'Untracked',
		'color' => '#475569',
		'icon'  => '❓',
		'desc'  => 'Unclassified',
		'order' => 7,
	),
);

// ════════════════════════════════════════════════════════════════════════════════
// DATA LAYER — all queries with transient caching
// ════════════════════════════════════════════════════════════════════════════════

// ── 1. Stage distribution with LTV and order averages ────────────────────────
$stage_data = get_transient( 'gtbogo_ji_stages_v2' );
if ( false === $stage_data && $has_prof ) {
	$rows       = $wpdb->get_results(
		"SELECT lifecycle_state,
                COUNT(*) AS cnt,
                COALESCE(AVG(total_spent),0) AS avg_ltv,
                COALESCE(AVG(total_orders),0) AS avg_orders,
                COALESCE(SUM(total_spent),0) AS total_revenue
         FROM {$profiles_tbl}
         GROUP BY lifecycle_state"
	) ?: array();
	$stage_data = array();
	foreach ( $rows as $r ) {
		$stage_data[ $r->lifecycle_state ] = array(
			'count'         => (int) $r->cnt,
			'avg_ltv'       => (float) $r->avg_ltv,
			'avg_orders'    => (float) $r->avg_orders,
			'total_revenue' => (float) $r->total_revenue,
		);
	}
	set_transient( 'gtbogo_ji_stages_v2', $stage_data, $cache_ttl );
}
$stage_data        = is_array( $stage_data ) ? $stage_data : array();
$total_customers   = array_sum( array_column( $stage_data, 'count' ) );
$total_healthy     = ( $stage_data['loyal']['count'] ?? 0 ) + ( $stage_data['vip']['count'] ?? 0 );
$total_at_risk_all = ( $stage_data['at_risk']['count'] ?? 0 ) + ( $stage_data['lapsed']['count'] ?? 0 );
$total_revenue_all = array_sum( array_column( $stage_data, 'total_revenue' ) );

// ── 2. Stage velocity — avg days between transitions ─────────────────────────
$velocity_data = get_transient( 'gtbogo_ji_velocity_v2' );
if ( false === $velocity_data && $has_evts ) {
	$rows          = $wpdb->get_results(
		"SELECT from_state, to_state,
                COUNT(*) AS transitions,
                COALESCE(AVG(TIMESTAMPDIFF(DAY, from_created_at, created_at)),0) AS avg_days,
                MIN(created_at) AS first_seen,
                MAX(created_at) AS last_seen
         FROM {$events_tbl}
         WHERE from_state IS NOT NULL
           AND to_state IS NOT NULL
           AND from_state != to_state
         GROUP BY from_state, to_state
         ORDER BY transitions DESC
         LIMIT 50"
	) ?: array();
	$velocity_data = array();
	foreach ( $rows as $r ) {
		$key                   = $r->from_state . '__' . $r->to_state;
		$velocity_data[ $key ] = array(
			'from'        => $r->from_state,
			'to'          => $r->to_state,
			'transitions' => (int) $r->transitions,
			'avg_days'    => (float) $r->avg_days,
			'last_seen'   => $r->last_seen,
		);
	}
	set_transient( 'gtbogo_ji_velocity_v2', $velocity_data, $cache_ttl );
}
$velocity_data = is_array( $velocity_data ) ? $velocity_data : array();

// ── 3. Stage transition matrix (90d) ─────────────────────────────────────────
$transition_matrix = get_transient( 'gtbogo_ji_matrix_v2' );
if ( false === $transition_matrix && $has_evts ) {
	$rows              = $wpdb->get_results(
		"SELECT from_state, to_state, COUNT(*) AS cnt
         FROM {$events_tbl}
         WHERE from_state IS NOT NULL
           AND to_state IS NOT NULL
           AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 90 DAY)
         GROUP BY from_state, to_state"
	) ?: array();
	$transition_matrix = array();
	foreach ( $rows as $r ) {
		if ( ! isset( $transition_matrix[ $r->from_state ] ) ) {
			$transition_matrix[ $r->from_state ] = array();
		}
		$transition_matrix[ $r->from_state ][ $r->to_state ] = (int) $r->cnt;
	}
	set_transient( 'gtbogo_ji_matrix_v2', $transition_matrix, $cache_ttl );
}
$transition_matrix = is_array( $transition_matrix ) ? $transition_matrix : array();

// ── 4. Monthly cohort progression (last 6 months) ────────────────────────────
$cohort_data = get_transient( 'gtbogo_ji_cohorts_v2' );
if ( false === $cohort_data && $has_prof ) {
	$rows        = $wpdb->get_results(
		"SELECT DATE_FORMAT(first_order_date, '%Y-%m') AS cohort_month,
                lifecycle_state,
                COUNT(*) AS cnt,
                COALESCE(AVG(total_spent),0) AS avg_ltv
         FROM {$profiles_tbl}
         WHERE first_order_date >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL 6 MONTH)
           AND first_order_date IS NOT NULL
         GROUP BY cohort_month, lifecycle_state
         ORDER BY cohort_month DESC"
	) ?: array();
	$cohort_data = array();
	foreach ( $rows as $r ) {
		if ( ! isset( $cohort_data[ $r->cohort_month ] ) ) {
			$cohort_data[ $r->cohort_month ] = array();
		}
		$cohort_data[ $r->cohort_month ][ $r->lifecycle_state ] = array(
			'count'   => (int) $r->cnt,
			'avg_ltv' => (float) $r->avg_ltv,
		);
	}
	set_transient( 'gtbogo_ji_cohorts_v2', $cohort_data, $cache_ttl );
}
$cohort_data   = is_array( $cohort_data ) ? $cohort_data : array();
$cohort_months = array_keys( $cohort_data );
rsort( $cohort_months );
$cohort_months = array_slice( $cohort_months, 0, 6 );

// ── 5. Recent lifecycle events (paginated, 25/page) ───────────────────────────
$event_page    = max( 1, absint( wp_unslash( $_GET['epage'] ?? 1 ) ) );
$events_limit  = 25;
$events_offset = ( $event_page - 1 ) * $events_limit;

$recent_events = array();
$total_events  = 0;
if ( $has_evts ) {
	$total_events  = (int) $wpdb->get_var( "SELECT COUNT(*) FROM {$events_tbl}" );
	$recent_events = $wpdb->get_results(
		$wpdb->prepare(
			"SELECT e.event_type, e.from_state, e.to_state, e.created_at,
                e.customer_id,
                p.customer_email, p.lifecycle_state AS current_state,
                p.total_spent, p.total_orders
         FROM {$events_tbl} e
         LEFT JOIN {$profiles_tbl} p ON p.customer_id = e.customer_id
         ORDER BY e.created_at DESC
         LIMIT %d OFFSET %d",
			$events_limit,
			$events_offset
		)
	) ?: array();
}
$event_pages = $events_limit > 0 ? (int) ceil( $total_events / $events_limit ) : 1;

// ── 6. Conversion Guard metrics ───────────────────────────────────────────────
$guard_report     = array();
$guard_suppressed = 0;
if ( class_exists( 'GT_BOGO_Conversion_Guard' ) && method_exists( 'GT_BOGO_Conversion_Guard', 'get_guard_report' ) ) {
	$guard_report     = GT_BOGO_Conversion_Guard::get_guard_report() ?: array();
	$guard_suppressed = (int) ( $guard_report['suppressed_30d'] ?? 0 );
}

// ── 7. LTV benchmarks per stage ───────────────────────────────────────────────
$ltv_benchmarks = get_transient( 'gtbogo_ji_ltv_bench_v2' );
if ( false === $ltv_benchmarks && $has_prof ) {
	$rows           = $wpdb->get_results(
		"SELECT lifecycle_state,
                COALESCE(MIN(total_spent),0)    AS min_ltv,
                COALESCE(MAX(total_spent),0)    AS max_ltv,
                COALESCE(AVG(total_spent),0)    AS avg_ltv,
                COALESCE(STDDEV(total_spent),0) AS stddev_ltv,
                COUNT(*) AS cnt
         FROM {$profiles_tbl}
         WHERE total_spent > 0
         GROUP BY lifecycle_state"
	) ?: array();
	$ltv_benchmarks = array();
	foreach ( $rows as $r ) {
		$ltv_benchmarks[ $r->lifecycle_state ] = array(
			'min'    => (float) $r->min_ltv,
			'max'    => (float) $r->max_ltv,
			'avg'    => (float) $r->avg_ltv,
			'stddev' => (float) $r->stddev_ltv,
			'cnt'    => (int) $r->cnt,
		);
	}
	set_transient( 'gtbogo_ji_ltv_bench_v2', $ltv_benchmarks, $cache_ttl );
}
$ltv_benchmarks = is_array( $ltv_benchmarks ) ? $ltv_benchmarks : array();

// ── 8. Event window metrics (upgrades, downgrades, win-backs) ─────────────────
$events_window = get_transient( "gtbogo_ji_events_win_{$days}" );
if ( false === $events_window && $has_evts ) {
	$upgrades      = (int) $wpdb->get_var(
		$wpdb->prepare(
			"SELECT COUNT(*) FROM {$events_tbl}
         WHERE event_type IN ('stage_upgrade','tier_upgrade')
           AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d DAY)",
			$days
		)
	);
	$downgrades    = (int) $wpdb->get_var(
		$wpdb->prepare(
			"SELECT COUNT(*) FROM {$events_tbl}
         WHERE event_type IN ('stage_downgrade','at_risk','lapsed')
           AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d DAY)",
			$days
		)
	);
	$winbacks      = (int) $wpdb->get_var(
		$wpdb->prepare(
			"SELECT COUNT(*) FROM {$events_tbl}
         WHERE from_state IN ('at_risk','lapsed')
           AND to_state IN ('returning','loyal','vip')
           AND created_at >= DATE_SUB(UTC_TIMESTAMP(), INTERVAL %d DAY)",
			$days
		)
	);
	$events_window = compact( 'upgrades', 'downgrades', 'winbacks' );
	set_transient( "gtbogo_ji_events_win_{$days}", $events_window, $cache_ttl );
}
$events_window = is_array( $events_window ) ? $events_window : array(
	'upgrades'   => 0,
	'downgrades' => 0,
	'winbacks'   => 0,
);

// ── 9. Journey Health Score (0–100) composite ────────────────────────────────
$health_score = 0;
if ( $total_customers > 0 ) {
	$loyal_vip_rate  = ( $total_healthy / $total_customers ) * 40;
	$at_risk_penalty = ( $total_at_risk_all / $total_customers ) * 30;
	$winback_bonus   = min( 15.0, (float) $events_window['winbacks'] );
	$upgrade_bonus   = min( 15.0, (float) $events_window['upgrades'] / 10 );
	$health_score    = (int) min(
		100,
		max(
			0,
			$loyal_vip_rate - $at_risk_penalty + $winback_bonus + $upgrade_bonus
		)
	);
}
$health_color = $health_score >= 70 ? '#10b981' : ( $health_score >= 40 ? '#f59e0b' : '#ef4444' );
$health_label = $health_score >= 70 ? 'Healthy' : ( $health_score >= 40 ? 'Needs Attention' : 'Critical' );

// ── 10. Stage projection (30d forward based on net velocity flow) ─────────────
$projection = array();
foreach ( $stage_meta as $slug => $meta ) {
	$current = $stage_data[ $slug ]['count'] ?? 0;
	$in      = 0;
	$out     = 0;
	foreach ( $velocity_data as $v ) {
		if ( $v['to'] === $slug ) {
			$in += $v['transitions'];
		}
		if ( $v['from'] === $slug ) {
			$out += $v['transitions'];
		}
	}
	$net_monthly         = $in - $out;
	$projection[ $slug ] = max( 0, $current + (int) round( $net_monthly * 30 / 90 ) );
}

// ── 11. Chart.js data arrays ─────────────────────────────────────────────────
$chart_labels = array();
$chart_counts = array();
$chart_colors = array();
$chart_ltv    = array();
foreach ( $stage_meta as $slug => $meta ) {
	$chart_labels[] = $meta['label'];
	$chart_counts[] = $stage_data[ $slug ]['count'] ?? 0;
	$chart_colors[] = $meta['color'];
	$chart_ltv[]    = round( $ltv_benchmarks[ $slug ]['avg'] ?? 0, 2 );
}

// Velocity chart — top 8 transitions
$vel_labels = array();
$vel_days   = array();
$vel_counts = array();
$vel_colors = array();
$sorted_vel = array_values( $velocity_data );
usort( $sorted_vel, fn( $a, $b ) => $b['transitions'] - $a['transitions'] );
foreach ( array_slice( $sorted_vel, 0, 8 ) as $v ) {
	$fl           = $stage_meta[ $v['from'] ]['label'] ?? $v['from'];
	$tl           = $stage_meta[ $v['to'] ]['label'] ?? $v['to'];
	$vel_labels[] = $fl . ' → ' . $tl;
	$vel_days[]   = round( $v['avg_days'], 1 );
	$vel_counts[] = $v['transitions'];
	$is_positive  = in_array( $v['to'], array( 'returning', 'loyal', 'vip' ), true )
					&& ! in_array( $v['from'], array( 'at_risk', 'lapsed' ), true );
	$vel_colors[] = $is_positive ? '#10b981cc' : '#f97316cc';
}

$base_url = admin_url( 'admin.php?page=gt-bogo-engine&tab=journey-intelligence' );

// ── 12. Cache flush handler ───────────────────────────────────────────────────
$flush_message = '';
if ( isset( $_GET['gtbogo_flush_ji'] )
	&& wp_verify_nonce( sanitize_text_field( wp_unslash( $_GET['_nonce'] ?? '' ) ), 'gtbogo_ji_flush' )
) {
	$flush_keys = array(
		'gtbogo_ji_stages_v2',
		'gtbogo_ji_velocity_v2',
		'gtbogo_ji_matrix_v2',
		'gtbogo_ji_cohorts_v2',
		'gtbogo_ji_ltv_bench_v2',
		"gtbogo_ji_events_win_{$days}",
	);
	foreach ( $flush_keys as $tk ) {
		delete_transient( $tk );
	}
	$flush_message = 'Cache flushed — data refreshed from database.';
}

// ════════════════════════════════════════════════════════════════════════════════
// CSS
// ════════════════════════════════════════════════════════════════════════════════
?>
<style>
/* ── Design tokens ── */
:root{
	--ji-bg:#020617;--ji-card:#0a1628;--ji-card2:#0d1f3c;
	--ji-border:rgba(255,255,255,0.07);--ji-border-strong:rgba(255,255,255,0.13);
	--ji-text:#e2e8f0;--ji-muted:#64748b;--ji-subtle:#94a3b8;
	--ji-accent:<?php echo esc_attr( $accent ); ?>;
	--ji-radius:8px;--ji-radius-sm:5px;
	--ji-font:'Outfit',system-ui,-apple-system,sans-serif;
	--ji-transition:0.2s ease;
}
/* ── Layout ── */
.ji-wrap{padding:28px;font-family:var(--ji-font);color:var(--ji-text);background:var(--ji-bg);min-height:100vh;box-sizing:border-box}
.ji-header{display:flex;justify-content:space-between;align-items:flex-start;margin-bottom:28px;gap:16px;flex-wrap:wrap}
.ji-header-left h1{margin:0 0 4px;font-size:1.65em;font-weight:700;color:#fff;line-height:1.2}
.ji-header-left p{margin:0;color:var(--ji-muted);font-size:0.87em;line-height:1.5;max-width:520px}
.ji-header-right{display:flex;align-items:center;gap:10px;flex-wrap:wrap}
/* ── KPI grids ── */
.ji-kpi-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:16px;margin-bottom:20px}
.ji-kpi{background:var(--ji-card);border:1px solid var(--ji-border);border-radius:var(--ji-radius);padding:20px;position:relative;overflow:hidden;transition:border-color var(--ji-transition)}
.ji-kpi:hover{border-color:var(--ji-border-strong)}
.ji-kpi-val{font-size:2.1em;font-weight:700;line-height:1;margin-bottom:4px}
.ji-kpi-label{font-size:0.77em;color:var(--ji-muted);text-transform:uppercase;letter-spacing:0.05em;font-weight:600}
.ji-kpi-sub{font-size:0.78em;color:var(--ji-subtle);margin-top:6px;line-height:1.4}
.ji-kpi-trend{position:absolute;top:14px;right:14px;font-size:0.74em;font-weight:700;padding:3px 8px;border-radius:20px}
.ji-kpi-trend.up{background:rgba(16,185,129,0.15);color:#10b981}
.ji-kpi-trend.down{background:rgba(239,68,68,0.15);color:#ef4444}
.ji-kpi-trend.neutral{background:rgba(100,116,139,0.15);color:var(--ji-muted)}
/* ── Cards ── */
.ji-card{background:var(--ji-card);border:1px solid var(--ji-border);border-radius:var(--ji-radius);padding:22px;margin-bottom:20px}
.ji-card.alert{border-color:rgba(249,115,22,0.3)}
.ji-card.critical{border-color:rgba(239,68,68,0.3)}
.ji-card-title{font-size:0.95em;font-weight:700;color:#fff;margin:0 0 18px;display:flex;align-items:center;gap:8px;font-family:var(--ji-font);flex-wrap:wrap}
.ji-card-title .ji-dot{width:7px;height:7px;border-radius:50%;background:var(--ji-accent);flex-shrink:0}
.ji-card-title .ji-badge{font-size:0.72em;font-weight:700;padding:2px 9px;border-radius:20px;background:rgba(225,0,0,0.12);color:var(--ji-accent);margin-left:auto}
/* ── Two/three col ── */
.ji-two-col{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-bottom:20px}
.ji-three-col{display:grid;grid-template-columns:1fr 1fr 1fr;gap:16px;margin-bottom:20px}
.ji-four-col{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
/* ── Stage funnel ── */
.ji-stage-row{display:flex;align-items:center;gap:10px;padding:11px 0;border-bottom:1px solid rgba(255,255,255,0.04)}
.ji-stage-row:last-child{border-bottom:none}
.ji-stage-icon{font-size:1.1em;width:22px;flex-shrink:0;text-align:center}
.ji-stage-name{width:80px;flex-shrink:0;font-size:0.87em;font-weight:700}
.ji-stage-desc{width:70px;flex-shrink:0;font-size:0.72em;color:var(--ji-muted)}
.ji-bar-bg{flex:1;background:rgba(255,255,255,0.05);border-radius:3px;height:7px;overflow:hidden;min-width:40px}
.ji-bar-fill{height:7px;border-radius:3px;transition:width 0.5s ease}
.ji-stage-count{width:52px;text-align:right;flex-shrink:0;font-size:0.87em;font-weight:700}
.ji-stage-pct{width:40px;text-align:right;flex-shrink:0;font-size:0.76em;color:var(--ji-muted)}
.ji-stage-ltv{width:64px;text-align:right;flex-shrink:0;font-size:0.76em;color:var(--ji-subtle)}
/* ── Transition matrix ── */
.ji-matrix{width:100%;border-collapse:collapse;font-size:0.8em}
.ji-matrix th{padding:7px 9px;text-align:center;color:var(--ji-muted);font-size:0.74em;text-transform:uppercase;letter-spacing:0.04em;border-bottom:1px solid var(--ji-border)}
.ji-matrix th.row-header{text-align:left;padding-left:0}
.ji-matrix td{padding:7px 9px;text-align:center;border-bottom:1px solid rgba(255,255,255,0.03)}
.ji-matrix td.row-label{text-align:left;font-weight:600;color:var(--ji-subtle);padding-left:0}
.ji-matrix td.cell-zero{color:rgba(255,255,255,0.14);font-size:0.85em}
.ji-matrix td.cell-low{background:rgba(16,185,129,0.08);color:#10b981;border-radius:3px}
.ji-matrix td.cell-mid{background:rgba(16,185,129,0.2);color:#10b981;font-weight:600;border-radius:3px}
.ji-matrix td.cell-high{background:rgba(16,185,129,0.36);color:#34d399;font-weight:700;border-radius:3px}
/* ── Velocity ── */
.ji-vel-row{display:flex;justify-content:space-between;align-items:center;padding:10px 0;border-bottom:1px solid rgba(255,255,255,0.04)}
.ji-vel-row:last-child{border-bottom:none}
.ji-vel-flow{display:flex;align-items:center;gap:7px;font-size:0.87em}
.ji-vel-arrow{color:var(--ji-muted);font-size:0.85em}
.ji-vel-days{font-size:1.05em;font-weight:700}
.ji-vel-meta{font-size:0.74em;color:var(--ji-muted);text-align:right;margin-top:2px}
/* ── Cohort ── */
.ji-cohort{width:100%;border-collapse:collapse;font-size:0.8em}
.ji-cohort th{padding:8px 11px;text-align:center;color:var(--ji-muted);font-size:0.74em;text-transform:uppercase;letter-spacing:0.04em;border-bottom:1px solid var(--ji-border)}
.ji-cohort th:first-child{text-align:left}
.ji-cohort td{padding:8px 11px;text-align:center;border-bottom:1px solid rgba(255,255,255,0.03);color:var(--ji-subtle)}
.ji-cohort td:first-child{text-align:left;font-weight:600;color:var(--ji-text)}
/* ── Events table ── */
.ji-events{width:100%;border-collapse:collapse;font-size:0.83em}
.ji-events th{padding:9px 11px;text-align:left;border-bottom:1px solid var(--ji-border);color:var(--ji-muted);font-size:0.74em;text-transform:uppercase;letter-spacing:0.05em;font-weight:600}
.ji-events td{padding:9px 11px;border-bottom:1px solid rgba(255,255,255,0.033);color:var(--ji-text)}
.ji-events tr:hover td{background:rgba(255,255,255,0.018)}
.ji-events tr:last-child td{border-bottom:none}
/* ── LTV benchmark table ── */
.ji-ltv-table{width:100%;border-collapse:collapse;font-size:0.82em}
.ji-ltv-table th{padding:8px 11px;text-align:left;border-bottom:1px solid var(--ji-border);color:var(--ji-muted);font-size:0.74em;text-transform:uppercase;letter-spacing:0.04em;font-weight:600}
.ji-ltv-table td{padding:8px 11px;border-bottom:1px solid rgba(255,255,255,0.033);vertical-align:middle}
.ji-ltv-table tr:last-child td{border-bottom:none}
/* ── Stage pill badge ── */
.ji-pill{display:inline-block;padding:2px 9px;border-radius:20px;font-size:0.75em;font-weight:700;text-transform:uppercase;letter-spacing:0.03em;white-space:nowrap}
/* ── Guard grid ── */
.ji-guard-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:12px}
.ji-guard-item{background:var(--ji-card2);border-radius:var(--ji-radius-sm);padding:15px}
.ji-guard-val{font-size:1.55em;font-weight:700;line-height:1}
.ji-guard-label{font-size:0.8em;font-weight:600;color:var(--ji-text);margin-top:4px}
.ji-guard-desc{font-size:0.73em;color:var(--ji-muted);margin-top:3px;line-height:1.4}
/* ── Projection ── */
.ji-proj-row{display:flex;align-items:center;gap:8px;padding:9px 0;border-bottom:1px solid rgba(255,255,255,0.04)}
.ji-proj-row:last-child{border-bottom:none}
.ji-proj-name{width:82px;flex-shrink:0;font-size:0.85em;font-weight:600}
.ji-proj-now{width:52px;flex-shrink:0;font-size:0.85em;text-align:right;color:var(--ji-subtle)}
.ji-proj-arrow{color:var(--ji-muted);font-size:0.8em;flex-shrink:0}
.ji-proj-future{width:58px;flex-shrink:0;font-size:0.85em;font-weight:700;text-align:right}
.ji-proj-delta{font-size:0.75em;flex-shrink:0;min-width:40px;text-align:right}
/* ── Controls ── */
.ji-filter-bar{display:flex;align-items:center;gap:7px}
.ji-range-btn{padding:6px 13px;border-radius:20px;font-size:0.8em;font-weight:600;border:1px solid var(--ji-border);background:transparent;color:var(--ji-muted);cursor:pointer;text-decoration:none;transition:all var(--ji-transition)}
.ji-range-btn.active,.ji-range-btn:hover{background:var(--ji-accent);border-color:var(--ji-accent);color:#fff}
.ji-btn{display:inline-flex;align-items:center;gap:5px;padding:8px 17px;border-radius:20px;font-size:0.82em;font-weight:700;text-decoration:none;cursor:pointer;border:none;transition:all var(--ji-transition);font-family:var(--ji-font)}
.ji-btn-primary{background:var(--ji-accent);color:#fff}
.ji-btn-primary:hover{opacity:0.88;color:#fff}
.ji-btn-ghost{background:transparent;color:var(--ji-muted);border:1px solid var(--ji-border)}
.ji-btn-ghost:hover{border-color:var(--ji-border-strong);color:var(--ji-text)}
/* ── Pagination ── */
.ji-pagination{display:flex;align-items:center;gap:5px;margin-top:16px;flex-wrap:wrap}
.ji-page-btn{padding:5px 11px;border-radius:5px;font-size:0.8em;font-weight:600;border:1px solid var(--ji-border);background:transparent;color:var(--ji-muted);text-decoration:none;transition:all var(--ji-transition)}
.ji-page-btn.active,.ji-page-btn:hover{border-color:var(--ji-accent);color:var(--ji-accent)}
/* ── Chart ── */
.ji-chart-wrap{position:relative;height:240px}
/* ── Empty states ── */
.ji-empty{text-align:center;padding:32px 20px;color:var(--ji-muted);font-size:0.88em;line-height:1.6}
.ji-empty-icon{font-size:2.4em;margin-bottom:10px;display:block}
/* ── System status items ── */
.ji-sys-item{background:var(--ji-card2);border-radius:var(--ji-radius-sm);padding:13px}
.ji-sys-name{font-size:0.82em;font-weight:700;margin-bottom:3px}
.ji-sys-detail{font-size:0.75em;color:var(--ji-muted)}
/* ── Responsive ── */
@media(max-width:1100px){.ji-kpi-grid{grid-template-columns:repeat(2,1fr)}.ji-two-col,.ji-three-col{grid-template-columns:1fr}.ji-four-col{grid-template-columns:repeat(2,1fr)}}
@media(max-width:680px){.ji-kpi-grid{grid-template-columns:1fr 1fr}.ji-guard-grid{grid-template-columns:1fr}.ji-four-col{grid-template-columns:1fr}}
@media(prefers-reduced-motion:reduce){.ji-bar-fill,.ji-btn,.ji-range-btn,.ji-kpi{transition:none!important}}
</style>

<?php /* ════════════════════ HTML OUTPUT ════════════════════ */ ?>

<div class="ji-wrap">

	<!-- ── HEADER ─────────────────────────────────────────────────────────── -->
	<div class="ji-header">
	<div class="ji-header-left">
		<h1>&#128202; Journey Intelligence</h1>
		<p>Lifecycle stage funnels, velocity analysis, transition matrices, cohort progression, Conversion Guard metrics, and win-back effectiveness.</p>
	</div>
	<div class="ji-header-right">
		<?php
		$status_cls = $health_score >= 70 ? 'active' : ( $health_score >= 40 ? 'warning' : 'danger' );
		$status_dot = $health_score >= 70 ? '●' : '▲';
		$status_bg  = $health_score >= 70
			? 'background:rgba(16,185,129,0.12);color:#10b981'
			: ( $health_score >= 40
				? 'background:rgba(245,158,11,0.12);color:#f59e0b'
				: 'background:rgba(239,68,68,0.12);color:#ef4444' );
		?>
		<span style="<?php echo esc_attr( $status_bg ); ?>;padding:5px 14px;border-radius:20px;font-size:0.8em;font-weight:700">
		<?php echo esc_html( $status_dot . ' ' . $health_label ); ?>
		</span>
		<div class="ji-filter-bar">
		<?php
		foreach ( array(
			7  => '7d',
			30 => '30d',
			60 => '60d',
			90 => '90d',
		) as $d => $lbl ) :
			?>
		<a href="<?php echo esc_url( add_query_arg( 'days', $d, $base_url ) ); ?>"
			class="ji-range-btn <?php echo $days === $d ? 'active' : ''; ?>">
			<?php echo esc_html( $lbl ); ?>
		</a>
		<?php endforeach; ?>
		</div>
		<a href="
		<?php
		echo esc_url(
			add_query_arg(
				array(
					'gtbogo_flush_ji' => 1,
					'_nonce'          => wp_create_nonce( 'gtbogo_ji_flush' ),
				),
				$base_url
			)
		);
		?>
		"
		class="ji-btn ji-btn-ghost">&#8635; Refresh</a>
	</div>
	</div>

	<?php if ( $flush_message ) : ?>
	<div style="background:rgba(16,185,129,0.1);border:1px solid rgba(16,185,129,0.28);border-radius:6px;padding:10px 16px;margin-bottom:20px;color:#10b981;font-size:0.85em;font-weight:600">
	&#10003; <?php echo esc_html( $flush_message ); ?>
	</div>
	<?php endif; ?>

	<!-- ── KPI ROW 1 — primary metrics ────────────────────────────────────── -->
	<div class="ji-kpi-grid">
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:<?php echo esc_attr( $accent ); ?>"><?php echo esc_html( number_format( $total_customers ) ); ?></div>
		<div class="ji-kpi-label">Total Profiled</div>
		<div class="ji-kpi-sub">Customers tracked by intelligence engine</div>
	</div>
	<div class="ji-kpi">
		<span class="ji-kpi-trend up">+<?php echo esc_html( $events_window['upgrades'] ); ?> upgrades</span>
		<div class="ji-kpi-val" style="color:#10b981"><?php echo esc_html( number_format( $total_healthy ) ); ?></div>
		<div class="ji-kpi-label">Loyal + VIP</div>
		<div class="ji-kpi-sub"><?php echo esc_html( $total_customers > 0 ? round( $total_healthy / $total_customers * 100, 1 ) : 0 ); ?>% of base — your most valuable segment</div>
	</div>
	<div class="ji-kpi">
		<span class="ji-kpi-trend down"><?php echo esc_html( $total_at_risk_all ); ?> need action</span>
		<div class="ji-kpi-val" style="color:#f97316"><?php echo esc_html( number_format( $total_at_risk_all ) ); ?></div>
		<div class="ji-kpi-label">At Risk + Lapsed</div>
		<div class="ji-kpi-sub"><?php echo esc_html( $total_customers > 0 ? round( $total_at_risk_all / $total_customers * 100, 1 ) : 0 ); ?>% churn risk — intervention required</div>
	</div>
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:<?php echo esc_attr( $health_color ); ?>"><?php echo esc_html( $health_score ); ?></div>
		<div class="ji-kpi-label">Journey Health Score</div>
		<div class="ji-kpi-sub" style="color:<?php echo esc_attr( $health_color ); ?>;font-weight:600"><?php echo esc_html( $health_label ); ?> — composite funnel score (0–100)</div>
	</div>
	</div>

	<!-- ── KPI ROW 2 — window metrics ─────────────────────────────────────── -->
	<div class="ji-kpi-grid">
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:#f59e0b"><?php echo esc_html( number_format( $guard_suppressed ) ); ?></div>
		<div class="ji-kpi-label">Guard Suppressed (30d)</div>
		<div class="ji-kpi-sub">Self-converters shielded from unnecessary discounts</div>
	</div>
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:#8b5cf6"><?php echo esc_html( number_format( $events_window['winbacks'] ) ); ?></div>
		<div class="ji-kpi-label">Win-Backs (<?php echo esc_html( $days ); ?>d)</div>
		<div class="ji-kpi-sub">At-risk or lapsed customers successfully re-engaged</div>
	</div>
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:#3b82f6"><?php echo esc_html( number_format( $events_window['upgrades'] ) ); ?></div>
		<div class="ji-kpi-label">Stage Upgrades (<?php echo esc_html( $days ); ?>d)</div>
		<div class="ji-kpi-sub">Customers who advanced to a higher lifecycle tier</div>
	</div>
	<div class="ji-kpi">
		<div class="ji-kpi-val" style="color:$'#64748b'"><?php echo esc_html( number_format( $events_window['downgrades'] ) ); ?></div>
		<div class="ji-kpi-label">Stage Downgrades (<?php echo esc_html( $days ); ?>d)</div>
		<div class="ji-kpi-sub">Customers who moved to a lower tier this window</div>
	</div>
	</div>

	<!-- ── STAGE FUNNEL + DONUT ────────────────────────────────────────────── -->
	<div class="ji-two-col">

	<div class="ji-card">
		<h2 class="ji-card-title">
		<span class="ji-dot"></span>
		Lifecycle Stage Distribution
		<span class="ji-badge"><?php echo esc_html( number_format( $total_customers ) ); ?> total</span>
		</h2>
		<?php
		if ( ! empty( $stage_data ) ) :
			$max_count = max( array_column( $stage_data, 'count' ) ?: array( 1 ) );
			foreach ( $stage_meta as $slug => $meta ) :
				$cnt    = $stage_data[ $slug ]['count'] ?? 0;
				$avgltv = $stage_data[ $slug ]['avg_ltv'] ?? 0;
				$pct    = $total_customers > 0 ? round( $cnt / $total_customers * 100, 1 ) : 0;
				$bar    = $max_count > 0 ? round( $cnt / $max_count * 100 ) : 0;
				?>
		<div class="ji-stage-row">
		<span class="ji-stage-icon"><?php echo esc_html( $meta['icon'] ); ?></span>
		<span class="ji-stage-name" style="color:<?php echo esc_attr( $meta['color'] ); ?>"><?php echo esc_html( $meta['label'] ); ?></span>
		<span class="ji-stage-desc"><?php echo esc_html( $meta['desc'] ); ?></span>
		<div class="ji-bar-bg"><div class="ji-bar-fill" style="width:<?php echo esc_attr( $bar ); ?>%;background:<?php echo esc_attr( $meta['color'] ); ?>"></div></div>
		<span class="ji-stage-count" style="color:<?php echo esc_attr( $meta['color'] ); ?>"><?php echo esc_html( number_format( $cnt ) ); ?></span>
		<span class="ji-stage-pct"><?php echo esc_html( $pct ); ?>%</span>
		<span class="ji-stage-ltv">$<?php echo esc_html( number_format( $avgltv, 0 ) ); ?></span>
		</div>
			<?php endforeach; ?>
		<?php else : ?>
		<div class="ji-empty"><span class="ji-empty-icon">&#128202;</span>No customer profiles yet. Profiles build automatically as customers place orders through your store.</div>
		<?php endif; ?>
	</div>

	<div class="ji-card">
		<h2 class="ji-card-title"><span class="ji-dot"></span>Stage Breakdown</h2>
		<div class="ji-chart-wrap"><canvas id="jiDonutChart"></canvas></div>
	</div>

	</div>

	<!-- ── LTV BENCHMARKS TABLE ────────────────────────────────────────────── -->
	<div class="ji-card">
	<h2 class="ji-card-title"><span class="ji-dot"></span>LTV Benchmarks by Stage</h2>
	<?php if ( ! empty( $ltv_benchmarks ) ) : ?>
	<div style="overflow-x:auto">
	<table class="ji-ltv-table">
		<thead><tr>
		<th>Stage</th><th>Customers</th><th>Min LTV</th><th>Avg LTV</th>
		<th>Max LTV</th><th>Std Dev</th><th>Avg Orders</th><th>Stage Revenue</th>
		</tr></thead>
		<tbody>
		<?php
		foreach ( $stage_meta as $slug => $meta ) :
			if ( ! isset( $stage_data[ $slug ] ) && ! isset( $ltv_benchmarks[ $slug ] ) ) {
				continue;
			}
			$b         = $ltv_benchmarks[ $slug ] ?? array(
				'min'    => 0,
				'avg'    => 0,
				'max'    => 0,
				'stddev' => 0,
			);
			$cnt       = $stage_data[ $slug ]['count'] ?? 0;
			$avg_ord   = $stage_data[ $slug ]['avg_orders'] ?? 0;
			$stage_rev = $stage_data[ $slug ]['total_revenue'] ?? 0;
			?>
		<tr>
		<td>
			<span class="ji-pill" style="background:<?php echo esc_attr( $meta['color'] ); ?>1a;color:<?php echo esc_attr( $meta['color'] ); ?>">
			<?php echo esc_html( $meta['icon'] . ' ' . $meta['label'] ); ?>
			</span>
		</td>
		<td style="font-weight:600"><?php echo esc_html( number_format( $cnt ) ); ?></td>
		<td style="color:var(--ji-muted)">$<?php echo esc_html( number_format( $b['min'], 2 ) ); ?></td>
		<td style="font-weight:700;color:<?php echo esc_attr( $meta['color'] ); ?>">$<?php echo esc_html( number_format( $b['avg'], 2 ) ); ?></td>
		<td>$<?php echo esc_html( number_format( $b['max'], 2 ) ); ?></td>
		<td style="color:var(--ji-subtle)">±$<?php echo esc_html( number_format( $b['stddev'], 2 ) ); ?></td>
		<td style="color:var(--ji-subtle)"><?php echo esc_html( number_format( $avg_ord, 1 ) ); ?></td>
		<td style="color:#f59e0b;font-weight:600">$<?php echo esc_html( number_format( $stage_rev, 0 ) ); ?></td>
		</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
	</div>
	<?php else : ?>
	<div class="ji-empty"><span class="ji-empty-icon">&#128181;</span>LTV benchmark data not yet available. Builds automatically as customers make purchases.</div>
	<?php endif; ?>
	</div>

	<!-- ── VELOCITY CHART + TRANSITION MATRIX ─────────────────────────────── -->
	<div class="ji-two-col">

	<div class="ji-card">
		<h2 class="ji-card-title"><span class="ji-dot"></span>Stage Transition Velocity</h2>
		<p style="margin:0 0 14px;font-size:0.82em;color:var(--ji-muted)">Average days for customers to move between stages. Green = healthy progression. Lower is faster.</p>
		<?php
		if ( ! empty( $velocity_data ) ) :
			$sorted_vel = array_values( $velocity_data );
			usort( $sorted_vel, fn( $a, $b ) => $b['transitions'] - $a['transitions'] );
			$shown = 0;
			foreach ( $sorted_vel as $v ) :
				if ( $shown >= 10 ) {
					break;
				}
				$fm = $stage_meta[ $v['from'] ] ?? null;
				$tm = $stage_meta[ $v['to'] ] ?? null;
				if ( ! $fm || ! $tm ) {
					continue;
				}
				$is_pos    = in_array( $v['to'], array( 'returning', 'loyal', 'vip' ), true )
					&& ! in_array( $v['from'], array( 'at_risk', 'lapsed' ), true );
				$is_win    = in_array( $v['from'], array( 'at_risk', 'lapsed' ), true )
					&& in_array( $v['to'], array( 'returning', 'loyal', 'vip' ), true );
				$day_color = $is_win ? '#8b5cf6' : ( $is_pos ? '#10b981' : '#f97316' );
				++$shown;
				?>
		<div class="ji-vel-row">
		<div class="ji-vel-flow">
			<span style="color:<?php echo esc_attr( $fm['color'] ); ?>;font-weight:600"><?php echo esc_html( $fm['icon'] . ' ' . $fm['label'] ); ?></span>
			<span class="ji-vel-arrow">&#8594;</span>
			<span style="color:<?php echo esc_attr( $tm['color'] ); ?>;font-weight:600"><?php echo esc_html( $tm['icon'] . ' ' . $tm['label'] ); ?></span>
				<?php
				if ( $is_win ) :
					?>
					<span style="font-size:0.75em;color:#8b5cf6;margin-left:4px">WIN-BACK</span><?php endif; ?>
		</div>
		<div style="text-align:right">
			<div class="ji-vel-days" style="color:<?php echo esc_attr( $day_color ); ?>"><?php echo esc_html( round( $v['avg_days'], 0 ) ); ?>d avg</div>
			<div class="ji-vel-meta"><?php echo esc_html( number_format( $v['transitions'] ) ); ?> transitions</div>
		</div>
		</div>
			<?php endforeach; ?>
		<?php else : ?>
		<div class="ji-empty">
		<span class="ji-empty-icon">&#9201;</span>
			<?php
			echo $has_evts
			? 'No transition data yet — velocity builds as customers progress between stages.'
			: 'Lifecycle events table not found. Run the database migration from System Status.';
			?>
		</div>
		<?php endif; ?>
	</div>

	<div class="ji-card">
		<h2 class="ji-card-title"><span class="ji-dot"></span>Transition Matrix <span class="ji-badge">90d</span></h2>
		<p style="margin:0 0 14px;font-size:0.82em;color:var(--ji-muted)">Stage-to-stage customer flows. Rows = origin stage, columns = destination stage.</p>
		<?php
		$matrix_stages = array( 'new', 'returning', 'loyal', 'vip', 'at_risk', 'lapsed' );
		if ( ! empty( $transition_matrix ) ) :
			$matrix_max = 1;
			foreach ( $transition_matrix as $tos ) {
				foreach ( $tos as $cnt ) {
					$matrix_max = max( $matrix_max, (int) $cnt );
				}
			}
			?>
		<div style="overflow-x:auto">
		<table class="ji-matrix">
		<thead><tr>
			<th class="row-header" style="font-size:0.72em;color:var(--ji-muted)">From ↓ To →</th>
			<?php
			foreach ( $matrix_stages as $slug ) :
				$m = $stage_meta[ $slug ] ?? array(
					'icon'  => '?',
					'color' => '#64748b',
				);
				?>
			<th style="color:<?php echo esc_attr( $m['color'] ); ?>"><?php echo esc_html( $m['icon'] ); ?></th>
			<?php endforeach; ?>
		</tr></thead>
		<tbody>
			<?php
			foreach ( $matrix_stages as $from ) :
				$fm = $stage_meta[ $from ] ?? array(
					'label' => $from,
					'color' => '#64748b',
					'icon'  => '?',
				);
				?>
		<tr>
			<td class="row-label" style="color:<?php echo esc_attr( $fm['color'] ); ?>"><?php echo esc_html( $fm['icon'] . ' ' . $fm['label'] ); ?></td>
				<?php
				foreach ( $matrix_stages as $to ) :
					$cnt   = $transition_matrix[ $from ][ $to ] ?? 0;
					$ratio = $cnt / $matrix_max;
					if ( $cnt === 0 ) {
						$cls  = 'cell-zero';
						$disp = '—';
					} elseif ( $ratio > 0.6 ) {
						$cls  = 'cell-high';
						$disp = number_format( $cnt );
					} elseif ( $ratio > 0.2 ) {
						$cls  = 'cell-mid';
						$disp = number_format( $cnt );
					} else {
						$cls  = 'cell-low';
						$disp = number_format( $cnt );
					}
					?>
			<td class="<?php echo esc_attr( $cls ); ?>"><?php echo esc_html( $disp ); ?></td>
				<?php endforeach; ?>
		</tr>
			<?php endforeach; ?>
		</tbody>
		</table>
		</div>
		<?php else : ?>
		<div class="ji-empty"><span class="ji-empty-icon">&#128257;</span><?php echo $has_evts ? 'No transition data yet.' : 'Lifecycle events table not found.'; ?></div>
		<?php endif; ?>
	</div>

	</div>

	<!-- ── VELOCITY TREND CHART ────────────────────────────────────────────── -->
	<?php if ( ! empty( $vel_labels ) ) : ?>
	<div class="ji-card">
	<h2 class="ji-card-title"><span class="ji-dot"></span>Transition Velocity Chart</h2>
	<div class="ji-chart-wrap"><canvas id="jiVelocityChart"></canvas></div>
	</div>
	<?php endif; ?>

	<!-- ── MONTHLY COHORT ANALYSIS ─────────────────────────────────────────── -->
	<div class="ji-card">
	<h2 class="ji-card-title"><span class="ji-dot"></span>Monthly Cohort Progression</h2>
	<p style="margin:0 0 16px;font-size:0.82em;color:var(--ji-muted)">How customer cohorts (grouped by first order month) have progressed through lifecycle stages. Reveals retention curves and upgrade acceleration over time.</p>
	<?php if ( ! empty( $cohort_data ) && ! empty( $cohort_months ) ) : ?>
	<div style="overflow-x:auto">
	<table class="ji-cohort">
		<thead><tr>
		<th>Cohort</th>
		<?php foreach ( $stage_meta as $slug => $meta ) : ?>
		<th style="color:<?php echo esc_attr( $meta['color'] ); ?>"><?php echo esc_html( $meta['icon'] . ' ' . $meta['label'] ); ?></th>
		<?php endforeach; ?>
		<th style="color:var(--ji-subtle)">Total</th>
		<th style="color:#f59e0b">Avg LTV</th>
		</tr></thead>
		<tbody>
		<?php
		foreach ( $cohort_months as $month ) :
			$cohort         = $cohort_data[ $month ] ?? array();
			$cohort_total   = 0;
			$cohort_ltv_sum = 0;
			$cohort_ltv_cnt = 0;
			foreach ( $cohort as $sdata ) {
				$cohort_total   += $sdata['count'] ?? 0;
				$cohort_ltv_sum += ( $sdata['count'] ?? 0 ) * ( $sdata['avg_ltv'] ?? 0 );
				if ( ( $sdata['count'] ?? 0 ) > 0 ) {
					$cohort_ltv_cnt += $sdata['count'];
				}
			}
			if ( $cohort_total === 0 ) {
				continue;
			}
			$cohort_avg_ltv = $cohort_ltv_cnt > 0 ? $cohort_ltv_sum / $cohort_ltv_cnt : 0;
			?>
		<tr>
		<td style="font-family:monospace;font-size:0.88em"><?php echo esc_html( $month ); ?></td>
			<?php
			foreach ( $stage_meta as $slug => $meta ) :
				$n = $cohort[ $slug ]['count'] ?? 0;
				$p = $cohort_total > 0 ? round( $n / $cohort_total * 100 ) : 0;
				?>
		<td style="color:<?php echo esc_attr( $meta['color'] ); ?>">
				<?php
				echo $n > 0
				? esc_html( $n . ' (' . $p . '%)' )
				: '<span style="color:rgba(255,255,255,0.1)">—</span>';
				?>
		</td>
			<?php endforeach; ?>
		<td style="font-weight:700;color:var(--ji-text)"><?php echo esc_html( number_format( $cohort_total ) ); ?></td>
		<td style="color:#f59e0b;font-weight:600">$<?php echo esc_html( number_format( $cohort_avg_ltv, 2 ) ); ?></td>
		</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
	</div>
	<?php else : ?>
	<div class="ji-empty"><span class="ji-empty-icon">&#128200;</span>Cohort data builds as customers place orders over multiple months. Check back after your store has been running for at least 30 days.</div>
	<?php endif; ?>
	</div>

	<!-- ── 30-DAY STAGE PROJECTION + CONVERSION GUARD ─────────────────────── -->
	<div class="ji-two-col">

	<div class="ji-card">
		<h2 class="ji-card-title"><span class="ji-dot"></span>30-Day Stage Projection</h2>
		<p style="margin:0 0 16px;font-size:0.82em;color:var(--ji-muted)">Estimated stage distribution in 30 days based on current transition velocity. Model only — actual results depend on deal activity and market conditions.</p>
		<?php
		foreach ( $stage_meta as $slug => $meta ) :
			$now     = $stage_data[ $slug ]['count'] ?? 0;
			$proj    = $projection[ $slug ] ?? $now;
			$delta   = $proj - $now;
			$d_color = $delta > 0 ? '#10b981' : ( $delta < 0 ? '#ef4444' : '#64748b' );
			$d_pre   = $delta > 0 ? '+' : '';
			?>
		<div class="ji-proj-row">
		<span class="ji-proj-name" style="color:<?php echo esc_attr( $meta['color'] ); ?>"><?php echo esc_html( $meta['icon'] . ' ' . $meta['label'] ); ?></span>
		<span class="ji-proj-now"><?php echo esc_html( number_format( $now ) ); ?></span>
		<span class="ji-proj-arrow">&#8594;</span>
		<span class="ji-proj-future" style="color:<?php echo esc_attr( $meta['color'] ); ?>"><?php echo esc_html( number_format( $proj ) ); ?></span>
		<span class="ji-proj-delta" style="color:<?php echo esc_attr( $d_color ); ?>"><?php echo esc_html( $delta !== 0 ? $d_pre . number_format( $delta ) : '=' ); ?></span>
		</div>
		<?php endforeach; ?>
	</div>

	<div class="ji-card">
		<h2 class="ji-card-title"><span class="ji-dot"></span>Conversion Guard</h2>
		<?php if ( ! empty( $guard_report ) ) : ?>
		<div class="ji-guard-grid">
			<?php
			$guard_items = array(
				array(
					'label' => 'Suppressed (30d)',
					'val'   => $guard_report['suppressed_30d'] ?? 0,
					'color' => '#64748b',
					'desc'  => 'Deals blocked — customer was already converting',
				),
				array(
					'label' => 'Self-Converters',
					'val'   => $guard_report['self_converters'] ?? 0,
					'color' => '#10b981',
					'desc'  => 'Customers who buy without needing a discount',
				),
				array(
					'label' => 'Margin Saved',
					'val'   => '$' . number_format( (float) ( $guard_report['estimated_margin_saved'] ?? 0 ), 2 ),
					'color' => '#f59e0b',
					'desc'  => 'Estimated margin preserved by suppression',
				),
				array(
					'label' => 'Suppression Rate',
					'val'   => ( $guard_report['suppression_rate'] ?? 0 ) . '%',
					'color' => '#8b5cf6',
					'desc'  => '% of deals suppressed vs total triggered',
				),
				array(
					'label' => 'Guard Efficiency',
					'val'   => ( $guard_report['efficiency_score'] ?? '—' ),
					'color' => '#3b82f6',
					'desc'  => 'How accurately guard identifies self-converters',
				),
				array(
					'label' => 'Control Group Size',
					'val'   => $guard_report['control_group_size'] ?? 0,
					'color' => '#475569',
					'desc'  => '5% baseline group never suppressed for A/B validity',
				),
			);
			foreach ( $guard_items as $item ) :
				$dv = is_numeric( $item['val'] ) ? number_format( (float) $item['val'] ) : $item['val'];
				?>
		<div class="ji-guard-item">
			<div class="ji-guard-val" style="color:<?php echo esc_attr( $item['color'] ); ?>"><?php echo esc_html( $dv ); ?></div>
			<div class="ji-guard-label"><?php echo esc_html( $item['label'] ); ?></div>
			<div class="ji-guard-desc"><?php echo esc_html( $item['desc'] ); ?></div>
		</div>
		<?php endforeach; ?>
		</div>
		<?php else : ?>
		<div class="ji-empty" style="padding:16px 0">
		<span class="ji-empty-icon">&#128737;</span>
			<?php if ( class_exists( 'GT_BOGO_Conversion_Guard' ) ) : ?>
		Conversion Guard is active. No report data yet — data accumulates after the first order events are processed.
		<?php else : ?>
		Conversion Guard class not found. Ensure PRO license is active and validated.
		<?php endif; ?>
		</div>
		<?php endif; ?>
	</div>

	</div>

	<!-- ── AT-RISK ACTION PANEL ────────────────────────────────────────────── -->
	<?php
	$at_risk_count = $stage_data['at_risk']['count'] ?? 0;
	$lapsed_count  = $stage_data['lapsed']['count'] ?? 0;
	if ( $at_risk_count > 0 || $lapsed_count > 0 ) :
		?>
	<div class="ji-card alert">
	<h2 class="ji-card-title">
		<span style="width:7px;height:7px;border-radius:50%;background:#f97316;display:inline-block;flex-shrink:0"></span>
		Intervention Required
	</h2>
	<div class="ji-three-col" style="margin-bottom:18px">
		<div style="background:#0d1f3c;border-radius:6px;padding:16px">
		<div style="font-size:1.8em;font-weight:700;color:#f97316;line-height:1"><?php echo esc_html( number_format( $at_risk_count ) ); ?></div>
		<div style="font-size:0.82em;font-weight:600;color:var(--ji-text);margin-top:5px">At Risk</div>
		<div style="font-size:0.75em;color:var(--ji-muted);margin-top:3px;line-height:1.4">60+ days since last order. Likely to lapse without a targeted deal.</div>
		<?php if ( isset( $ltv_benchmarks['at_risk'] ) ) : ?>
		<div style="font-size:0.78em;color:#f97316;margin-top:6px;font-weight:600">Avg LTV: $<?php echo esc_html( number_format( $ltv_benchmarks['at_risk']['avg'], 0 ) ); ?></div>
		<?php endif; ?>
		</div>
		<div style="background:#0d1f3c;border-radius:6px;padding:16px">
		<div style="font-size:1.8em;font-weight:700;color:#ef4444;line-height:1"><?php echo esc_html( number_format( $lapsed_count ) ); ?></div>
		<div style="font-size:0.82em;font-weight:600;color:var(--ji-text);margin-top:5px">Lapsed</div>
		<div style="font-size:0.75em;color:var(--ji-muted);margin-top:3px;line-height:1.4">90+ days inactive. Win-back campaign required immediately to recover LTV.</div>
		<?php if ( isset( $ltv_benchmarks['lapsed'] ) ) : ?>
		<div style="font-size:0.78em;color:#ef4444;margin-top:6px;font-weight:600">Avg LTV: $<?php echo esc_html( number_format( $ltv_benchmarks['lapsed']['avg'], 0 ) ); ?></div>
		<?php endif; ?>
		</div>
		<div style="background:#0d1f3c;border-radius:6px;padding:16px">
		<div style="font-size:1.8em;font-weight:700;color:#8b5cf6;line-height:1"><?php echo esc_html( number_format( $events_window['winbacks'] ) ); ?></div>
		<div style="font-size:0.82em;font-weight:600;color:var(--ji-text);margin-top:5px">Recovered (<?php echo esc_html( $days ); ?>d)</div>
		<div style="font-size:0.75em;color:var(--ji-muted);margin-top:3px;line-height:1.4">At-risk and lapsed customers successfully re-engaged in this window.</div>
		<?php if ( $at_risk_count + $lapsed_count > 0 ) : ?>
		<div style="font-size:0.78em;color:#8b5cf6;margin-top:6px;font-weight:600">Recovery rate: <?php echo esc_html( round( $events_window['winbacks'] / ( $at_risk_count + $lapsed_count ) * 100, 1 ) ); ?>%</div>
		<?php endif; ?>
		</div>
	</div>
	<div style="display:flex;gap:10px;flex-wrap:wrap">
		<a href="<?php echo esc_url( admin_url( 'admin.php?page=gt-bogo-engine&tab=pro-rules' ) ); ?>"
		class="ji-btn ji-btn-primary">&#9998; Create Win-Back Rule</a>
		<a href="<?php echo esc_url( admin_url( 'admin.php?page=gt-bogo-engine&tab=emails' ) ); ?>"
		class="ji-btn ji-btn-ghost">&#9993; Configure Win-Back Email</a>
		<a href="<?php echo esc_url( admin_url( 'admin.php?page=gt-bogo-engine&tab=segments' ) ); ?>"
		class="ji-btn ji-btn-ghost">&#127978; Create At-Risk Segment</a>
		<a href="<?php echo esc_url( admin_url( 'admin.php?page=gt-bogo-engine&tab=customer-intelligence' ) ); ?>"
		class="ji-btn ji-btn-ghost">&#128203; View Individual Profiles</a>
	</div>
	</div>
	<?php endif; ?>

	<!-- ── RECENT LIFECYCLE EVENTS ─────────────────────────────────────────── -->
	<div class="ji-card">
	<h2 class="ji-card-title">
		<span class="ji-dot"></span>
		Recent Lifecycle Events
		<span class="ji-badge"><?php echo esc_html( number_format( $total_events ) ); ?> total</span>
	</h2>
	<?php if ( ! empty( $recent_events ) ) : ?>
	<div style="overflow-x:auto">
	<table class="ji-events">
		<thead><tr>
		<th>#</th><th>Customer</th><th>Event</th><th>From</th><th>To</th>
		<th>LTV</th><th>Orders</th><th>Current Stage</th><th>Time</th>
		</tr></thead>
		<tbody>
		<?php
		$row_n = $events_offset + 1;
		foreach ( $recent_events as $ev ) :
			$from_m    = $stage_meta[ $ev->from_state ?? '' ] ?? null;
			$to_m      = $stage_meta[ $ev->to_state ?? '' ] ?? null;
			$current_m = $stage_meta[ $ev->current_state ?? '' ] ?? null;
			$email     = $ev->customer_email ?? '';
			$at_pos    = strpos( $email, '@' );
			$masked    = $at_pos !== false
			? substr( $email, 0, min( 3, $at_pos ) ) . '***' . substr( $email, $at_pos )
			: 'Guest';
			$is_up     = in_array( $ev->to_state, array( 'returning', 'loyal', 'vip' ), true )
					&& ! in_array( $ev->from_state, array( 'at_risk', 'lapsed' ), true );
			$is_win    = in_array( $ev->from_state, array( 'at_risk', 'lapsed' ), true )
					&& in_array( $ev->to_state, array( 'returning', 'loyal', 'vip' ), true );
			$ev_label  = str_replace( '_', ' ', ucwords( str_replace( '_', ' ', $ev->event_type ?? '' ) ) );
			$ev_color  = $is_win ? '#8b5cf6' : ( $is_up ? '#10b981' : 'inherit' );
			?>
		<tr>
		<td style="color:var(--ji-muted);font-size:0.77em"><?php echo esc_html( $row_n++ ); ?></td>
		<td>
			<span style="color:var(--ji-text);font-family:monospace;font-size:0.83em"><?php echo esc_html( $masked ); ?></span>
			<?php if ( $ev->customer_id ) : ?>
			<a href="<?php echo esc_url( admin_url( 'user-edit.php?user_id=' . (int) $ev->customer_id ) ); ?>"
			style="color:var(--ji-muted);font-size:0.75em;margin-left:4px" title="View profile">&#8599;</a>
			<?php endif; ?>
		</td>
		<td style="color:<?php echo esc_attr( $ev_color ); ?>;font-weight:600">
			<?php echo $is_win ? '🔥 ' : ( $is_up ? '↑ ' : '' ); ?>
			<?php echo esc_html( $ev_label ); ?>
		</td>
		<td>
			<?php if ( $from_m ) : ?>
			<span class="ji-pill" style="background:<?php echo esc_attr( $from_m['color'] ); ?>1a;color:<?php echo esc_attr( $from_m['color'] ); ?>"><?php echo esc_html( $from_m['icon'] . ' ' . $from_m['label'] ); ?></span>
				<?php
			else :
				?>
				<span style="color:var(--ji-muted)">—</span><?php endif; ?>
		</td>
		<td>
			<?php if ( $to_m ) : ?>
			<span class="ji-pill" style="background:<?php echo esc_attr( $to_m['color'] ); ?>1a;color:<?php echo esc_attr( $to_m['color'] ); ?>"><?php echo esc_html( $to_m['icon'] . ' ' . $to_m['label'] ); ?></span>
				<?php
			else :
				?>
				<span style="color:var(--ji-muted)">—</span><?php endif; ?>
		</td>
		<td style="color:#f59e0b;font-weight:600">$<?php echo esc_html( number_format( (float) ( $ev->total_spent ?? 0 ), 2 ) ); ?></td>
		<td style="color:var(--ji-subtle)"><?php echo esc_html( (int) ( $ev->total_orders ?? 0 ) ); ?></td>
		<td>
			<?php if ( $current_m ) : ?>
			<span class="ji-pill" style="background:<?php echo esc_attr( $current_m['color'] ); ?>1a;color:<?php echo esc_attr( $current_m['color'] ); ?>"><?php echo esc_html( $current_m['icon'] . ' ' . $current_m['label'] ); ?></span>
				<?php
			else :
				?>
				<span style="color:var(--ji-muted)">—</span><?php endif; ?>
		</td>
		<td style="color:var(--ji-muted);font-size:0.8em;white-space:nowrap">
			<?php
			echo esc_html(
				$ev->created_at
				? human_time_diff( (int) strtotime( $ev->created_at ), time() ) . ' ago'
				: '—'
			);
			?>
		</td>
		</tr>
		<?php endforeach; ?>
		</tbody>
	</table>
	</div>
		<?php if ( $event_pages > 1 ) : ?>
	<div class="ji-pagination">
		<span style="font-size:0.8em;color:var(--ji-muted);margin-right:6px">Page <?php echo esc_html( $event_page ); ?> of <?php echo esc_html( $event_pages ); ?></span>
			<?php
			$range_start = max( 1, $event_page - 3 );
			$range_end   = min( $event_pages, $event_page + 3 );
			if ( $range_start > 1 ) {
				echo '<a href="' . esc_url(
					add_query_arg(
						array(
							'epage' => 1,
							'days'  => $days,
						),
						$base_url
					)
				) . '" class="ji-page-btn">1</a>';
				if ( $range_start > 2 ) {
					echo '<span style="color:var(--ji-muted)">…</span>';
				}
			}
			for ( $p = $range_start; $p <= $range_end; $p++ ) :
				?>
		<a href="
				<?php
				echo esc_url(
					add_query_arg(
						array(
							'epage' => $p,
							'days'  => $days,
						),
						$base_url
					)
				);
				?>
					"
		class="ji-page-btn <?php echo $p === $event_page ? 'active' : ''; ?>">
				<?php echo esc_html( $p ); ?>
		</a>
				<?php
		endfor;
			if ( $range_end < $event_pages ) {
				if ( $range_end < $event_pages - 1 ) {
					echo '<span style="color:var(--ji-muted)">…</span>';
				}
				echo '<a href="' . esc_url(
					add_query_arg(
						array(
							'epage' => $event_pages,
							'days'  => $days,
						),
						$base_url
					)
				) . '" class="ji-page-btn">' . esc_html( $event_pages ) . '</a>';
			}
			?>
	</div>
	<?php endif; ?>
	<?php elseif ( ! $has_evts ) : ?>
	<div class="ji-empty"><span class="ji-empty-icon">&#128202;</span>Lifecycle events table not found. Run the database migration from <a href="<?php echo esc_url( admin_url( 'admin.php?page=gt-bogo-engine&tab=system-status' ) ); ?>" style="color:var(--ji-accent)">System Status</a>.</div>
	<?php else : ?>
	<div class="ji-empty"><span class="ji-empty-icon">&#128200;</span>No lifecycle events recorded yet. Events populate automatically as customers transition between stages.</div>
	<?php endif; ?>
	</div>

	<!-- ── INTELLIGENCE SYSTEM STATUS ─────────────────────────────────────── -->
	<div class="ji-card" style="margin-bottom:0">
	<h2 class="ji-card-title"><span class="ji-dot"></span>Intelligence System Status</h2>
	<div class="ji-four-col">
		<?php
		$systems = array(
			array(
				'name'   => 'Customer Profiles',
				'active' => $has_prof,
				'detail' => number_format( $total_customers ) . ' profiles tracked',
			),
			array(
				'name'   => 'Lifecycle Events',
				'active' => $has_evts,
				'detail' => number_format( $total_events ) . ' events logged',
			),
			array(
				'name'   => 'Conversion Guard',
				'active' => class_exists( 'GT_BOGO_Conversion_Guard' ),
				'detail' => number_format( $guard_suppressed ) . ' suppressed (30d)',
			),
			array(
				'name'   => 'Journey State',
				'active' => class_exists( 'GT_BOGO_Journey_State' ),
				'detail' => 'Stage monitoring active',
			),
			array(
				'name'   => 'LTV Scoring',
				'active' => class_exists( 'GT_BOGO_LTV_Scoring' ),
				'detail' => count( $ltv_benchmarks ) . ' stage benchmarks built',
			),
			array(
				'name'   => 'Cohort Intelligence',
				'active' => class_exists( 'GT_BOGO_Cohort_Intelligence' ),
				'detail' => count( $cohort_data ) . ' cohorts tracked',
			),
			array(
				'name'   => 'Outcome Capture',
				'active' => class_exists( 'GT_BOGO_Outcome_Capture' ),
				'detail' => 'Decision outcomes tracked',
			),
			array(
				'name'   => 'Customer Segmentation',
				'active' => class_exists( 'GT_BOGO_Customer_Segmentation' ),
				'detail' => 'Active — rules targeting segments',
			),
		);
		foreach ( $systems as $sys ) :
			$sys_color = $sys['active'] ? '#10b981' : '#64748b';
			$sys_icon  = $sys['active'] ? '●' : '○';
			?>
		<div class="ji-sys-item">
		<div class="ji-sys-name" style="color:<?php echo esc_attr( $sys_color ); ?>"><?php echo esc_html( $sys_icon . ' ' . $sys['name'] ); ?></div>
		<div class="ji-sys-detail"><?php echo esc_html( $sys['active'] ? $sys['detail'] : 'Not active' ); ?></div>
		</div>
		<?php endforeach; ?>
	</div>
	<div style="margin-top:14px;padding-top:14px;border-top:1px solid var(--ji-border);font-size:0.78em;color:var(--ji-muted);display:flex;align-items:center;gap:16px;flex-wrap:wrap">
		<span>Cache TTL: 5 min</span>
		<span>Data window: <?php echo esc_html( $days ); ?> days</span>
		<span>Last refreshed: <?php echo esc_html( gmdate( 'H:i:s \U\T\C' ) ); ?></span>
		<a href="
		<?php
		echo esc_url(
			add_query_arg(
				array(
					'gtbogo_flush_ji' => 1,
					'_nonce'          => wp_create_nonce( 'gtbogo_ji_flush' ),
				),
				$base_url
			)
		);
		?>
		"
		style="color:var(--ji-accent);text-decoration:none;font-weight:600">&#8635; Flush Cache</a>
	</div>
	</div>

</div><!-- .ji-wrap -->

<!-- ── CHART.JS INITIALIZATION ─────────────────────────────────────────────── -->
<script>
(function() {
	if ( typeof Chart === 'undefined' ) return;

	Chart.defaults.color        = '#64748b';
	Chart.defaults.font.family  = "'Outfit', system-ui, sans-serif";
	Chart.defaults.font.size    = 11;

	// ── Donut chart — stage distribution ─────────────────────────────────
	var donutEl = document.getElementById('jiDonutChart');
	if ( donutEl ) {
	var donutLabels  = <?php echo wp_json_encode( $chart_labels ); ?>;
	var donutCounts  = <?php echo wp_json_encode( $chart_counts ); ?>;
	var donutColors  = <?php echo wp_json_encode( $chart_colors ); ?>;
	var donutBg      = donutColors.map(function(c){ return c + 'cc'; });

	new Chart( donutEl, {
		type: 'doughnut',
		data: {
		labels:   donutLabels,
		datasets: [{
			data:            donutCounts,
			backgroundColor: donutBg,
			borderColor:     donutColors,
			borderWidth: 1.5,
			hoverOffset: 8
		}]
		},
		options: {
		responsive:          true,
		maintainAspectRatio: false,
		cutout:              '66%',
		plugins: {
			legend: {
			position: 'right',
			labels: {
				color:    '#94a3b8',
				boxWidth: 10,
				padding:  10,
				font: { size: 11, family: "'Outfit',system-ui" }
			}
			},
			tooltip: {
			callbacks: {
				label: function(ctx) {
				var total = ctx.dataset.data.reduce(function(a,b){return a+b;},0);
				var pct   = total > 0 ? Math.round(ctx.parsed/total*100) : 0;
				return ' ' + ctx.label + ': ' + ctx.parsed.toLocaleString() + ' (' + pct + '%)';
				}
			}
			}
		}
		}
	});
	}

	// ── Velocity horizontal bar chart ─────────────────────────────────────
	var velEl = document.getElementById('jiVelocityChart');
	if ( velEl ) {
	var velLabels = <?php echo wp_json_encode( $vel_labels ); ?>;
	var velDays   = <?php echo wp_json_encode( $vel_days ); ?>;
	var velColors = <?php echo wp_json_encode( $vel_colors ); ?>;
	var velCounts = <?php echo wp_json_encode( $vel_counts ); ?>;

	new Chart( velEl, {
		type: 'bar',
		data: {
		labels:   velLabels,
		datasets: [{
			label:           'Avg Days',
			data:            velDays,
			backgroundColor: velColors,
			borderColor:     velColors,
			borderWidth: 0,
			borderRadius: 3
		}]
		},
		options: {
		indexAxis:           'y',
		responsive:          true,
		maintainAspectRatio: false,
		plugins: {
			legend: { display: false },
			tooltip: {
			callbacks: {
				label: function(ctx) {
				var idx = ctx.dataIndex;
				return ' ' + ctx.parsed.x + ' days avg (' + (velCounts[idx]||0).toLocaleString() + ' transitions)';
				}
			}
			}
		},
		scales: {
			x: {
			grid:  { color: 'rgba(255,255,255,0.05)' },
			ticks: { color: '#64748b' },
			title: { display: true, text: 'Average Days', color: '#64748b', font: { size: 11 } }
			},
			y: {
			grid:  { display: false },
			ticks: { color: '#94a3b8', font: { size: 10 } }
			}
		}
		}
	});
	}

})();
</script>
