<?php
/**
 * Rate Limiter
 *
 * Tracks requests per IP using WordPress transients (no extra DB calls
 * on the hot path). Compatible with Redis/Memcached object cache.
 *
 * @package GuardianShield
 */

namespace GuardianShield;

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

class RateLimiter {

	private Logger $logger;
	private int    $max_requests;
	private int    $window_seconds;

	public function __construct( Logger $logger ) {
		$this->logger         = $logger;
		$this->max_requests   = (int) gs_get_option( 'rate_limit_requests', 200 );
		$this->window_seconds = (int) gs_get_option( 'rate_limit_window', 60 );
	}

	/**
	 * Check current request count for $ip. Increments counter.
	 * Returns true if within limit, false if exceeded.
	 */
	public function check_and_record( string $ip, string $context = 'global' ): bool {
		if ( ! (bool) gs_get_option( 'rate_limit_enabled', true ) ) {
			return true;
		}

		// Normalise the key — colons in IPv6 aren't valid transient keys.
		$safe_ip = str_replace( ':', '_', $ip );
		$key     = "gs_rl_{$context}_{$safe_ip}";
		$count   = (int) get_transient( $key );

		if ( $count === 0 ) {
			set_transient( $key, 1, $this->window_seconds );
			return true;
		}

		$count++;
		set_transient( $key, $count, $this->window_seconds );

		return $count <= $this->max_requests;
	}

	/** Returns remaining requests for $ip in this window. */
	public function remaining( string $ip, string $context = 'global' ): int {
		$safe_ip = str_replace( ':', '_', $ip );
		$count   = (int) get_transient( "gs_rl_{$context}_{$safe_ip}" );
		return max( 0, $this->max_requests - $count );
	}
}
