<?php
/**
 * Rate Limiting Service
 */
class RateLimiter {
    private static $storageFile;
    private static $maxRequests;
    private static $timeWindow;
    
    public static function init() {
        self::$storageFile = __DIR__ . '/logs/rate_limits.json';
        self::$maxRequests = env_int('RATE_LIMIT_MAX_REQUESTS', 5);
        self::$timeWindow = env_int('RATE_LIMIT_TIME_WINDOW', 300); // 5 minutes
        
        // Create logs directory if it doesn't exist
        $logDir = dirname(self::$storageFile);
        if (!is_dir($logDir)) {
            mkdir($logDir, 0755, true);
        }
    }
    
    /**
     * Check if the request is allowed
     */
    public static function isAllowed($identifier = null) {
        if (self::$storageFile === null) {
            self::init();
        }
        
        $identifier = $identifier ?: self::getIdentifier();
        $currentTime = time();
        
        // Load existing rate limit data
        $rateLimits = self::loadRateLimits();
        
        // Clean up old entries
        $rateLimits = self::cleanupOldEntries($rateLimits, $currentTime);
        
        // Check current identifier
        if (!isset($rateLimits[$identifier])) {
            $rateLimits[$identifier] = [];
        }
        
        // Remove old requests for this identifier
        $rateLimits[$identifier] = array_filter(
            $rateLimits[$identifier],
            function($timestamp) use ($currentTime) {
                return $timestamp > ($currentTime - self::$timeWindow);
            }
        );
        
        // Check if limit exceeded
        if (count($rateLimits[$identifier]) >= self::$maxRequests) {
            Logger::warning('Rate limit exceeded', [
                'identifier' => $identifier,
                'requests' => count($rateLimits[$identifier]),
                'max_requests' => self::$maxRequests
            ]);
            return false;
        }
        
        // Add current request
        $rateLimits[$identifier][] = $currentTime;
        
        // Save updated rate limits
        self::saveRateLimits($rateLimits);
        
        return true;
    }
    
    /**
     * Get remaining requests
     */
    public static function getRemainingRequests($identifier = null) {
        if (self::$storageFile === null) {
            self::init();
        }
        
        $identifier = $identifier ?: self::getIdentifier();
        $currentTime = time();
        
        $rateLimits = self::loadRateLimits();
        $rateLimits = self::cleanupOldEntries($rateLimits, $currentTime);
        
        if (!isset($rateLimits[$identifier])) {
            return self::$maxRequests;
        }
        
        $recentRequests = array_filter(
            $rateLimits[$identifier],
            function($timestamp) use ($currentTime) {
                return $timestamp > ($currentTime - self::$timeWindow);
            }
        );
        
        return max(0, self::$maxRequests - count($recentRequests));
    }
    
    /**
     * Get time until reset
     */
    public static function getTimeUntilReset($identifier = null) {
        if (self::$storageFile === null) {
            self::init();
        }
        
        $identifier = $identifier ?: self::getIdentifier();
        $currentTime = time();
        
        $rateLimits = self::loadRateLimits();
        
        if (!isset($rateLimits[$identifier]) || empty($rateLimits[$identifier])) {
            return 0;
        }
        
        $oldestRequest = min($rateLimits[$identifier]);
        $resetTime = $oldestRequest + self::$timeWindow;
        
        return max(0, $resetTime - $currentTime);
    }
    
    private static function getIdentifier() {
        // Use IP address as identifier
        return $_SERVER['REMOTE_ADDR'] ?? 'unknown';
    }
    
    private static function loadRateLimits() {
        if (!file_exists(self::$storageFile)) {
            return [];
        }
        
        $content = file_get_contents(self::$storageFile);
        $data = json_decode($content, true);
        
        return is_array($data) ? $data : [];
    }
    
    private static function saveRateLimits($rateLimits) {
        file_put_contents(
            self::$storageFile,
            json_encode($rateLimits),
            LOCK_EX
        );
    }
    
    private static function cleanupOldEntries($rateLimits, $currentTime) {
        foreach ($rateLimits as $identifier => $timestamps) {
            $rateLimits[$identifier] = array_filter(
                $timestamps,
                function($timestamp) use ($currentTime) {
                    return $timestamp > ($currentTime - self::$timeWindow);
                }
            );
            
            // Remove empty entries
            if (empty($rateLimits[$identifier])) {
                unset($rateLimits[$identifier]);
            }
        }
        
        return $rateLimits;
    }
}
