<?php

if ( !defined( 'ABSPATH' ) ) exit; // Exit if accessed directly

class FENSE_BPVT_Cache
{
	
	private static $redis = null;
	private static $available = null;
	private static $prefix = 'fense_bpvt:';
	
	/**
	 * Try to connect to Redis directly via PHP extension
	 */
	public static function connect(): ?bool
	{
		if ( self::$available !== null ) {
			return self::$available;
		}
		
		// Check if Redis PHP extension is loaded
		if ( !extension_loaded( 'redis' ) ) {
			self::$available = false;
			return false;
		}
		
		try {
			self::$redis = new Redis();
			
			// Support custom Redis host/port via wp-config.php constants
			$host = defined( 'FENSE_BPVT_REDIS_HOST' ) ? FENSE_BPVT_REDIS_HOST : '127.0.0.1';
			$port = defined( 'FENSE_BPVT_REDIS_PORT' ) ? FENSE_BPVT_REDIS_PORT : 6379;
			$auth = defined( 'FENSE_BPVT_REDIS_AUTH' ) ? FENSE_BPVT_REDIS_AUTH : null;
			$db = defined( 'FENSE_BPVT_REDIS_DB' ) ? FENSE_BPVT_REDIS_DB : 0;
			
			self::$redis->connect( $host, $port, 2.0 ); // 2 second timeout
			
			if ( $auth ) {
				self::$redis->auth( $auth );
			}
			
			self::$redis->select( $db );
			self::$available = true;
			
		} catch ( Exception $e ) {
			self::$available = false;
			self::$redis = null;
		}
		
		return self::$available;
	}
	
	public static function get( $key )
	{
		if ( !self::connect() ) return false;
		
		try {
			$value = self::$redis->get( self::$prefix . $key );
			return $value ? unserialize( $value ) : false;
		} catch ( Exception $e ) {
			return false;
		}
	}
	
	public static function set( $key, $value, $ttl = 3600 ): bool
	{
		if ( !self::connect() ) return false;
		
		try {
			return self::$redis->setEx(
				self::$prefix . $key,
				(int)$ttl,
				serialize( $value )
			);
		} catch ( Exception $e ) {
			return false;
		}
	}
	
	public static function delete( $key ): bool
	{
		if ( !self::connect() ) return false;
		
		try {
			return self::$redis->del( self::$prefix . $key );
		} catch ( Exception $e ) {
			return false;
		}
	}
	
	public static function is_available(): ?bool
	{
		return self::connect();
	}
	
	// -----------------------------------------------------------------------
	// Transparent wrappers: Redis when available, WordPress transients otherwise
	// -----------------------------------------------------------------------
	
	/**
	 * Get a cached value from Redis or WordPress transients.
	 *
	 * @return mixed  The stored value, or false on miss.
	 */
	public static function wp_get( string $key )
	{
		if ( self::connect() ) {
			$value = self::get( $key );
			if ( $value !== false ) {
				return $value;
			}
			
			// Redis miss — check transient and promote to Redis if found.
			$transient = get_transient( $key );
			if ( $transient !== false ) {
				$timeout = (int)get_option( '_transient_timeout_' . $key );
				$remaining = $timeout > 0 ? max( 1, $timeout - time() ) : 3600;
				self::set( $key, $transient, $remaining );
			}
			return $transient;
		}
		
		return get_transient( $key );
	}
	
	/**
	 * Store a value in Redis or WordPress transients.
	 *
	 * @param mixed $value
	 */
	public static function wp_set( string $key, $value, int $ttl ): bool
	{
		if ( self::connect() ) {
			return (bool)self::set( $key, $value, $ttl );
		}
		return (bool)set_transient( $key, $value, $ttl );
	}
	
	/**
	 * Delete a cached value from Redis or WordPress transients.
	 */
	public static function wp_delete( string $key ): bool
	{
		if ( self::connect() ) {
			(bool)self::delete( $key );
		}
		delete_transient( $key );
		return true;
	}
}
