<?php
/**
 * Simple Rate Limiter for Seazonify using WordPress Transients
 */

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

class Seazonify_Rate_Limiter {

    /**
     * Check if the current request is rate limited.
     *
     * @param string $action    Unique action name (e.g., 'init_connect')
     * @param int    $threshold Max attempts allowed within the window
     * @param int    $window    Time window in seconds
     * @return bool|int         Remaining attempts or false if limited
     */
    public static function check($action, $threshold = 5, $window = 60) {
        $ip = self::get_ip();
        $transient_key = 'seazonify_rl_' . md5($action . $ip);
        
        $attempts = get_transient($transient_key);
        
        if (false === $attempts) {
            $attempts = 0;
        }
        
        if ($attempts >= $threshold) {
            return false;
        }
        
        $attempts++;
        set_transient($transient_key, $attempts, $window);
        
        return $threshold - $attempts;
    }

    /**
     * Get the client's IP address.
     * SECURITY: We deliberately only use REMOTE_ADDR (set by the server/proxy) 
     * and ignore HTTP_CLIENT_IP / HTTP_X_FORWARDED_FOR because those are
     * user-controlled headers and can be trivially spoofed to bypass rate limits.
     */
    private static function get_ip() {
        // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
        $ip = isset($_SERVER['REMOTE_ADDR']) ? sanitize_text_field(wp_unslash($_SERVER['REMOTE_ADDR'])) : '0.0.0.0';
        return $ip;
    }

    /**
     * Helper to return a 429 error response if limited.
     */
    public static function limit_or_continue($action, $threshold = 5, $window = 60) {
        if (self::check($action, $threshold, $window) === false) {
            wp_send_json_error(array(
                'message' => __('Too many requests. Please wait a moment.', 'seazonify'),
                'code'    => 429
            ), 429);
        }
    }
}
