<?php
/**
 * Cart Monitor — Hourly scan of WooCommerce sessions for abandoned carts.
 *
 * Scans the wp_woocommerce_sessions table only (R7 Fix#1 removed usermeta source).
 * Stores lightweight summary in capiflow_abandoned_summary option (no custom table).
 * WP.org compliant: awareness only — no recovery actions in Core (Pro feature).
 * Extracts: cart count, total value, up to 3 sample product names.
 *
 * @package CapiFlow
 */

namespace CapiFlow\Core;

defined( 'ABSPATH' ) || exit;

class Cart_Monitor {

	/**
	 * Minimum inactivity time before a cart is considered abandoned.
	 * Default: 1 hour. Filterable.
	 *
	 * @var int Seconds.
	 */
	private const ABANDONMENT_THRESHOLD = HOUR_IN_SECONDS;

	/**
	 * Register hooks (called from Plugin_Loader::init).
	 */
	public function register_hooks(): void {
		// Hourly scan is handled by AS cron in Plugin_Loader::schedule_tasks().
		// No additional hooks needed here — scan() is called directly.
	}

	/**
	 * Static scan entry point for Action Scheduler.
	 *
	 * Called by: add_action('capiflow_scan_abandoned_carts', [Cart_Monitor::class, 'scan'])
	 * R12-C2 Fix: This method must be static for ::class callback to work correctly.
	 */
	public static function scan(): void {
		global $wpdb;

		$threshold = (int) apply_filters( 'capiflow_cart_abandonment_threshold', self::ABANDONMENT_THRESHOLD );
		$cutoff    = gmdate( 'Y-m-d H:i:s', time() - $threshold );

		// Scan wp_woocommerce_sessions table.
		// Conditions:
		//   - session_expiry > time() (session still alive)
		//   - session_expiry < time() + 48h - threshold (session inactive for > $threshold)
		//     WC default session lifetime = 48 hours (172800s). session_expiry = last_activity + 48h.
		//     So session_expiry < now + 48h - threshold ≈ last_activity < now - threshold.
		//   - session_value contains cart data
		$wc_session_lifetime = (int) apply_filters( 'wc_session_expiration', 172800 ); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound -- WooCommerce core filter.
		$rows = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
			$wpdb->prepare(
				"SELECT session_key, session_value
				FROM {$wpdb->prefix}woocommerce_sessions
				WHERE session_expiry > %d
				AND session_expiry < %d
				AND session_value LIKE %s
				LIMIT 200",
				time(),
				time() + $wc_session_lifetime - $threshold,
				'%cart%'
			)
		);

		if ( empty( $rows ) ) {
			self::save_summary( array( 'count' => 0, 'value' => 0.0, 'products' => array() ) );
			return;
		}

		$count        = 0;
		$total_value  = 0.0;
		$sample_names = array();

		foreach ( $rows as $row ) {
			$session_data = maybe_unserialize( $row->session_value );

			if ( ! is_array( $session_data ) || empty( $session_data['cart'] ) ) {
				continue;
			}

			$cart = maybe_unserialize( $session_data['cart'] );
			if ( empty( $cart ) || ! is_array( $cart ) ) {
				continue;
			}

			// Calculate cart value.
			$cart_value = 0.0;
			foreach ( $cart as $item ) {
				if ( ! isset( $item['line_total'] ) || ! isset( $item['product_id'] ) ) {
					continue;
				}
				$cart_value += (float) $item['line_total'];

				// Collect up to 3 sample product names.
				if ( count( $sample_names ) < 3 ) {
					$product = wc_get_product( (int) $item['product_id'] );
					if ( $product ) {
						$sample_names[] = $product->get_name();
					}
				}
			}

			if ( $cart_value > 0 ) {
				$count++;
				$total_value += $cart_value;
			}
		}

		self::save_summary(
			array(
				'count'    => $count,
				'value'    => round( $total_value, 2 ),
				'products' => array_unique( $sample_names ),
			)
		);
	}

	/**
	 * Get the current abandoned cart summary.
	 *
	 * @return array{count:int, value:float, products:array}
	 */
	public static function get_summary(): array {
		return get_option(
			'capiflow_abandoned_summary',
			array( 'count' => 0, 'value' => 0.0, 'products' => array() )
		);
	}

	/**
	 * Save the abandoned cart summary to wp_options.
	 *
	 * @param array $summary Summary data.
	 */
	private static function save_summary( array $summary ): void {
		update_option( 'capiflow_abandoned_summary', $summary, false );
	}
}
