<?php
/**
 * Dashboard Cache Helper
 *
 * Provides cache-invalidation + TTL helpers for the Analytics Dashboard
 * transient caches (summary stats, top engaged users).
 *
 * Before 1.2.9 the dashboard used a 15-minute TTL with no invalidation path,
 * so stat cards stayed stale for up to 15 minutes after new visitor activity.
 * These helpers reduce TTL to 30 s (filterable) and flush transients whenever
 * a session row is inserted / updated.
 *
 * @package opti-behavior
 * @since 1.2.9
 */

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

if ( ! function_exists( 'opti_behavior_dashboard_cache_ttl' ) ) {
	/**
	 * Short-lived dashboard cache TTL in seconds.
	 *
	 * Defaults to 30 s so stat cards catch up with new visitor activity quickly.
	 * Operators can raise it via the `opti_behavior_dashboard_cache_ttl` filter
	 * if their traffic warrants a longer cache.
	 *
	 * @since 1.2.9
	 * @return int Cache lifetime in seconds.
	 */
	function opti_behavior_dashboard_cache_ttl() {
		$ttl = (int) apply_filters( 'opti_behavior_dashboard_cache_ttl', 30 );
		return $ttl > 0 ? $ttl : 30;
	}
}

if ( ! function_exists( 'opti_behavior_invalidate_dashboard_caches' ) ) {
	/**
	 * Flush the short-lived Analytics Dashboard transient caches.
	 *
	 * Safe to call frequently — only deletes transient rows; next dashboard hit
	 * re-aggregates. Matches both `opti_behavior_*` and `optibehavior_*`
	 * prefix families because both are used in the codebase.
	 *
	 * @since 1.2.9
	 * @return int Number of option rows deleted.
	 */
	function opti_behavior_invalidate_dashboard_caches() {
		global $wpdb;

		// phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching,WordPress.DB.PreparedSQL.InterpolatedNotPrepared -- Transient cleanup requires direct LIKE query; option_name values are hashed keys, not user input.
		$rows = (int) $wpdb->query(
			"DELETE FROM {$wpdb->options}
			 WHERE option_name LIKE '_transient_opti_behavior_summary_stats_%'
				OR option_name LIKE '_transient_timeout_opti_behavior_summary_stats_%'
				OR option_name LIKE '_transient_opti_behavior_top_users_%'
				OR option_name LIKE '_transient_timeout_opti_behavior_top_users_%'
				OR option_name LIKE '_transient_optibehavior_top_users_%'
				OR option_name LIKE '_transient_timeout_optibehavior_top_users_%'"
		);

		// Bust the cached alloptions blob so the next request doesn't serve the
		// deleted transient keys from memory.
		wp_cache_delete( 'alloptions', 'options' );

		/**
		 * Fires after dashboard caches are flushed.
		 *
		 * @since 1.2.9
		 * @param int $rows Number of option rows removed.
		 */
		do_action( 'opti_behavior_dashboard_caches_invalidated', $rows );

		return $rows;
	}
}

if ( ! function_exists( 'opti_behavior_is_force_refresh_requested' ) ) {
	/**
	 * Whether the current request asks for a dashboard force-refresh.
	 *
	 * Accepts either `force_refresh=1` in GET or POST. Used by the dashboard
	 * query paths to bypass the transient cache on explicit user action.
	 *
	 * @since 1.2.9
	 * @return bool True when caller requested a cache bypass.
	 */
	function opti_behavior_is_force_refresh_requested() {
		// phpcs:ignore WordPress.Security.NonceVerification.Recommended -- Read-only flag; no state change performed by reading it.
		if ( isset( $_REQUEST['force_refresh'] ) ) {
			// phpcs:ignore WordPress.Security.NonceVerification.Recommended
			return '1' === sanitize_text_field( wp_unslash( $_REQUEST['force_refresh'] ) );
		}
		return false;
	}
}
