using System.Collections.Concurrent;

namespace molilian.core
{
    public static class SpecialBusinessRateLimiter
    {
        private static readonly ConcurrentDictionary<string, SlidingWindowState> States = new();

        public static bool TryAcquire(string bucketKey, int limit, TimeSpan window)
        {
            if (string.IsNullOrWhiteSpace(bucketKey)) return true;
            if (limit <= 0 || window <= TimeSpan.Zero) return true;

            var state = States.GetOrAdd(bucketKey, _ => new SlidingWindowState());
            var nowTicks = DateTime.UtcNow.Ticks;
            var minTicks = nowTicks - window.Ticks;

            lock (state.SyncRoot)
            {
                while (state.Timestamps.Count > 0 && state.Timestamps.Peek() < minTicks)
                {
                    state.Timestamps.Dequeue();
                }

                if (state.Timestamps.Count >= limit)
                {
                    return false;
                }

                state.Timestamps.Enqueue(nowTicks);
                return true;
            }
        }

        private sealed class SlidingWindowState
        {
            public object SyncRoot { get; } = new();
            public Queue<long> Timestamps { get; } = new();
        }
    }
}
