using e_suite.Service.Performance.Interfaces;

namespace e_suite.Service.Performance.Implementations;

public class PerformanceCache : IPerformanceCache
{
    public PerformanceCache()
    {

    }

    private class RequestCache
    {
        private DateTimeOffset _expires;
        private long cacheEntry;

        public RequestCache(long timeOutMs)
        {
            UpdateTimeoutCache(timeOutMs);
        }

        public long? GetCacheValue()
        {
            if (_expires > DateTimeOffset.UtcNow)
                return cacheEntry;

            return null;
        }

        public void UpdateTimeoutCache(long timeOutMs)
        {
            _expires = DateTimeOffset.UtcNow.AddMinutes(5);
            cacheEntry = timeOutMs;
        }
    }

    private class ActionCache
    {
        private Dictionary<string, RequestCache> _cache = new Dictionary<string, RequestCache>();

        public long? CheckRequestType(PerformanceCapture performanceCapture)
        {
            var requestType = performanceCapture.RequestType;
            return _cache.ContainsKey(requestType) ? _cache[requestType].GetCacheValue() : null;
        }

        public void UpdateTimeoutCache(PerformanceCapture performanceCapture, long timeOutMs)
        {
            var requestType = performanceCapture.RequestType;
            RequestCache requestCache;
            if (_cache.ContainsKey(requestType))
            {
                requestCache = _cache[requestType];
                requestCache.UpdateTimeoutCache(timeOutMs);
            }
            else
            {

                requestCache = new RequestCache(timeOutMs);
                _cache.Add(requestType, requestCache);
            }
        }
    }
    private class ControllerCache
    {
        private readonly Dictionary<string, ActionCache> _cache = new Dictionary<string, ActionCache>();

        public long? GetTimeoutFromCache(PerformanceCapture performanceCapture)
        {
            var actionName = performanceCapture.ActionName.ToString();
            return _cache.ContainsKey(actionName) ? _cache[actionName].CheckRequestType(performanceCapture) : null;
        }

        public void UpdateTimeoutCache(PerformanceCapture performanceCapture, long timeOutMs)
        {
            var actionName = performanceCapture.ActionName.ToString();
            ActionCache actionCache;
            if (_cache.ContainsKey(actionName))
            {
                actionCache = _cache[actionName];
            }
            else
            {

                actionCache = new ActionCache();
                _cache.Add(actionName, actionCache);
            }

            actionCache.UpdateTimeoutCache(performanceCapture, timeOutMs);
        }
    }

    private readonly Dictionary<string, ControllerCache> _cache = new Dictionary<string, ControllerCache>();

    public long? GetTimeoutFromCache(PerformanceCapture performanceCapture)
    {
        var controllerName = performanceCapture.ControllerName.ToString();
        return _cache.ContainsKey(controllerName) ? _cache[controllerName].GetTimeoutFromCache(performanceCapture) : null;
    }

    public void UpdateTimeoutCache(PerformanceCapture performanceCapture, long timeOutMs)
    {
        var controllerName = performanceCapture.ControllerName.ToString();
        ControllerCache controllerCache;
        if (_cache.ContainsKey(controllerName))
        {
            controllerCache = _cache[controllerName];
        }
        else
        {

            controllerCache = new ControllerCache();
            _cache.Add(controllerName, controllerCache);
        }

        controllerCache.UpdateTimeoutCache(performanceCapture, timeOutMs);
    }
}
