#pragma once

#include <string>
#include <unordered_map>
#include <mutex>
#include <chrono>

namespace mosis {

struct RateLimitConfig {
    double tokens_per_second;    // Refill rate
    double max_tokens;           // Bucket capacity
};

class RateLimiter {
public:
    // Default limits for common operations
    RateLimiter();

    // Check if operation is allowed (consumes token if yes)
    bool Check(const std::string& app_id, const std::string& operation);

    // Check without consuming token
    bool CanProceed(const std::string& app_id, const std::string& operation) const;

    // Configure limits for an operation
    void SetLimit(const std::string& operation, const RateLimitConfig& config);

    // Get config for an operation
    const RateLimitConfig* GetLimit(const std::string& operation) const;

    // Get current token count for app+operation
    double GetTokens(const std::string& app_id, const std::string& operation) const;

    // Reset all buckets for an app (e.g., on app restart)
    void ResetApp(const std::string& app_id);

    // Clear all buckets
    void ClearAll();

private:
    struct Bucket {
        double tokens;
        std::chrono::steady_clock::time_point last_refill;
    };

    // Refill bucket based on elapsed time
    void Refill(Bucket& bucket, const RateLimitConfig& config) const;

    // Get or create bucket for app+operation
    Bucket& GetBucket(const std::string& app_id, const std::string& operation);

    // Get bucket key
    static std::string MakeKey(const std::string& app_id, const std::string& operation);

    mutable std::mutex m_mutex;
    std::unordered_map<std::string, RateLimitConfig> m_configs;
    mutable std::unordered_map<std::string, Bucket> m_buckets;
};

// Global rate limiter (singleton)
RateLimiter& GetRateLimiter();

} // namespace mosis

// Convenience alias
using RateLimiter = mosis::RateLimiter;
using RateLimitConfig = mosis::RateLimitConfig;
