<?php
namespace AIPT\Api\Traits;

use AIPT\Api\Constants\RateLimitConstants;

trait RateLimitTrait {
    /**
     * Check rate limit for a user and scope.
     *
     * Uses WordPress transients for fixed-window rate limiting.
     *
     * Note: The get/set transient cycle is not atomic, so a narrow race condition
     * exists under concurrent requests. This is acceptable for admin-only endpoints
     * with low concurrency. For high-traffic public endpoints, consider a database-level
     * atomic counter (e.g., UPDATE ... SET count = count + 1 WHERE count < max).
     *
     * @param int    $user_id        User ID.
     * @param string $scope           Rate limit scope identifier.
     * @param int|null $max_requests    Maximum requests allowed per window.
     * @param int|null $window_seconds  Window duration in seconds.
     * @return array{allowed: bool, remaining: int, reset_in: int}
     */
    protected function checkRateLimit(int $user_id, string $scope = 'default', ?int $max_requests = null, ?int $window_seconds = null): array {
		$max_requests   = $max_requests ?? RateLimitConstants::defaultMaxRequests();
		$window_seconds = $window_seconds ?? RateLimitConstants::defaultWindowSeconds();

		if ( $max_requests < 1 || $window_seconds < 1 ) {
			return array( 'allowed' => false, 'remaining' => 0, 'reset_in' => 0 );
		}

        $transient_key = 'aipt_rate_limit_' . $scope . '_' . $user_id;

        $rate_data = get_transient($transient_key);

        if (false === $rate_data) {
            $rate_data = array('count' => 1, 'window_start' => time());
            set_transient($transient_key, $rate_data, $window_seconds);
            return array('allowed' => true, 'remaining' => $max_requests - 1, 'reset_in' => $window_seconds);
        }

        $elapsed = time() - $rate_data['window_start'];

        if ($elapsed >= $window_seconds) {
            $rate_data = array('count' => 1, 'window_start' => time());
            set_transient($transient_key, $rate_data, $window_seconds);
            return array('allowed' => true, 'remaining' => $max_requests - 1, 'reset_in' => $window_seconds);
        }

        if ($rate_data['count'] >= $max_requests) {
            return array('allowed' => false, 'remaining' => 0, 'reset_in' => $window_seconds - $elapsed);
        }

        $rate_data['count']++;
        set_transient($transient_key, $rate_data, $window_seconds - $elapsed);

        return array('allowed' => true, 'remaining' => $max_requests - $rate_data['count'], 'reset_in' => $window_seconds - $elapsed);
    }

    protected function rateLimitResponse(array $rate_check): \WP_Error {
        return new \WP_Error(
            'rate_limit_exceeded',
            sprintf(
                /* translators: %d: Number of seconds to wait before retrying */
                __('Rate limit exceeded. Please wait %d seconds before trying again.', 'ai-product-tools'),
                $rate_check['reset_in']
            ),
            array('status' => 429, 'retry_after' => $rate_check['reset_in'])
        );
    }
}
