using e_suite.Service.Performance.Interfaces;
using eSuite.Core.Clock;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.Caching.Memory;

namespace e_suite.Service.Performance.Extensions.Web;

public class PerformanceMonitorMiddleware
{
    private readonly RequestDelegate _next;
    private readonly IPerformanceReportProcessor _performanceReportProcessor;
    private readonly IMemoryCache _memoryCache;
    private readonly IClock _clock;

    public PerformanceMonitorMiddleware(RequestDelegate next, IPerformanceReportProcessor performanceReportProcessor, IMemoryCache memoryCache, IClock clock)
    {
        _next = next;
        _performanceReportProcessor = performanceReportProcessor;
        _memoryCache = memoryCache;
        _clock = clock;
    }
    public async Task InvokeAsync(HttpContext context)
    {
        var routeData = context.GetRouteData();
        var traceId = context.TraceIdentifier;
        var performanceReportRequest = new PerformanceCapture("Round Trip", _clock)
        {
            Host = context.Request.Host.Value!,
            ControllerName = routeData.Values["controller"]?.ToString() ?? string.Empty,
            ActionName = routeData.Values["action"]?.ToString() ?? string.Empty,
            RequestType = context.Request.Method,
            ActionParameters = (IDictionary<string, object>)_memoryCache.Get("actionParams")!
        };
        performanceReportRequest.Markers.AddMarker(nameof(InvokeAsync));
        _memoryCache.GetOrCreate(traceId, cacheEntry =>
        {
            cacheEntry.SlidingExpiration = TimeSpan.FromSeconds(10);
            cacheEntry.AbsoluteExpirationRelativeToNow = TimeSpan.FromSeconds(50);
            return performanceReportRequest;
        });

        await _next.Invoke(context);

        var performanceReportResponse = _memoryCache.Get<PerformanceCapture>(traceId);
        if (performanceReportResponse != null)
        {
            performanceReportRequest.Markers.AddMarker($"{nameof(InvokeAsync)} Endeed");
            performanceReportResponse.Stopwatch.Stop();
            _memoryCache.Remove(traceId);
            await _performanceReportProcessor.ProcessReportAsync(performanceReportResponse);
        }
    }

}
