<?php
/**
 * Simple transient-based rate limiting for wishlist AJAX.
 *
 * @package SKYNSMFA_Smart_Favorites
 */

declare( strict_types=1 );

namespace SKYNSMFA\Wishlist;

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


final class Rate_Limit {
	/**
	 * Singleton instance.
	 *
	 * @var Rate_Limit|null
	 */
	private static $instance = null;

	/**
	 * Get singleton instance.
	 *
	 * @return Rate_Limit
	 */
	public static function instance(): Rate_Limit {
		if ( null === self::$instance ) {
			self::$instance = new self();
		}

		return self::$instance;
	}

	/**
	 * Constructor.
	 */
	private function __construct() {
	}

	/**
	 * Whether the current request is allowed for an action.
	 *
	 * @param string $action_slug Short action identifier.
	 * @param int    $max_per_window Max hits per window.
	 * @param int    $window_seconds Window length in seconds.
	 * @return bool True if allowed; false if rate limited.
	 */
	public function allow( string $action_slug, int $max_per_window, int $window_seconds ): bool {
		$ip = $this->get_request_ip();
		if ( '' === $ip ) {
			return true;
		}

		$key   = 'skynsmfa_rl_' . md5( $action_slug . '|' . $ip );
		$count = (int) get_transient( $key );

		if ( $count >= $max_per_window ) {
			return false;
		}

		$count++;
		set_transient( $key, $count, $window_seconds );

		return true;
	}

	/**
	 * Best-effort client IP for rate limiting.
	 *
	 * @return string
	 */
	private function get_request_ip(): string {
		if ( ! empty( $_SERVER['REMOTE_ADDR'] ) ) {
			return sanitize_text_field( wp_unslash( (string) $_SERVER['REMOTE_ADDR'] ) );
		}

		return '';
	}
}
