using Microsoft.AspNetCore.OutputCaching;

namespace CalledIt.Api.OutputCaching;

internal sealed class LeaderboardCachePolicy : IOutputCachePolicy
{
    public static LeaderboardCachePolicy Instance { get; } = new();

    public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var req = context.HttpContext.Request;
        var attempt = HttpMethods.IsGet(req.Method) || HttpMethods.IsHead(req.Method);

        context.EnableOutputCaching = attempt;
        context.AllowCacheLookup = attempt;
        context.AllowCacheStorage = attempt;
        context.AllowLocking = true;

        var compId = context.HttpContext.GetRouteValue("competitionId")?.ToString() ?? string.Empty;
        var userId = context.HttpContext.User.FindFirst("sub")?.Value ?? string.Empty;
        context.CacheVaryByRules.VaryByValues["competitionId"] = compId;
        context.CacheVaryByRules.VaryByValues["uid"] = userId;
        context.ResponseExpirationTimeSpan = TimeSpan.FromSeconds(10);

        return ValueTask.CompletedTask;
    }

    public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        context.HttpContext.Response.Headers["X-Cache"] = "HIT";
        return ValueTask.CompletedTask;
    }

    public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        if (context.HttpContext.Response.StatusCode != StatusCodes.Status200OK)
        {
            context.AllowCacheStorage = false;
        }
        return ValueTask.CompletedTask;
    }
}
