using Microsoft.AspNetCore.OutputCaching;
using Microsoft.Extensions.Primitives;
using Tiku.Application.Security;

namespace Tiku.Api.Caching;

internal sealed class TenantPublicOutputCachePolicy : IOutputCachePolicy
{
    public ValueTask CacheRequestAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var request = context.HttpContext.Request;
        var tenantId = context.HttpContext.RequestServices.GetRequiredService<ITenantContext>().TenantId;
        var enabled = HttpMethods.IsGet(request.Method) &&
                      tenantId.HasValue &&
                      StringValues.IsNullOrEmpty(request.Headers.Authorization) &&
                      context.HttpContext.User.Identity?.IsAuthenticated != true;
        context.EnableOutputCaching = enabled;
        context.AllowCacheLookup = enabled;
        context.AllowCacheStorage = enabled;
        context.AllowLocking = true;
        if (enabled)
        {
            var resolvedTenantId = tenantId.GetValueOrDefault();
            context.CacheVaryByRules.QueryKeys = "*";
            context.CacheVaryByRules.HeaderNames = new StringValues("Accept-Encoding");
            context.CacheVaryByRules.VaryByValues["tenant"] = resolvedTenantId.ToString("N");
            context.Tags.Add($"tenant:{resolvedTenantId:N}");
        }

        return ValueTask.CompletedTask;
    }

    public ValueTask ServeFromCacheAsync(OutputCacheContext context, CancellationToken cancellationToken) =>
        ValueTask.CompletedTask;

    public ValueTask ServeResponseAsync(OutputCacheContext context, CancellationToken cancellationToken)
    {
        var response = context.HttpContext.Response;
        if (response.StatusCode != StatusCodes.Status200OK ||
            !StringValues.IsNullOrEmpty(response.Headers.SetCookie) ||
            context.HttpContext.User.Identity?.IsAuthenticated == true)
        {
            context.AllowCacheStorage = false;
        }

        return ValueTask.CompletedTask;
    }
}
