namespace DigitalData.Core.API;

/// <summary>
/// Middleware to add Content Security Policy (CSP) headers to the HTTP response.
/// </summary>
public class CSPMiddleware
{
    private readonly RequestDelegate _next;
    private readonly string _policy;

    /// <summary>
    /// Initializes a new instance of the <see cref="CSPMiddleware"/> class.
    /// </summary>
    /// <param name="next">The next middleware in the request pipeline.</param>
    /// <param name="policy">The CSP policy string with placeholders for nonces.</param>
    public CSPMiddleware(RequestDelegate next, string policy)
    {
        _next = next;
        _policy = policy;
    }

    /// <summary>
    /// Invokes the middleware to add the CSP header to the response.
    /// </summary>
    /// <param name="context">The HTTP context.</param>
    /// <returns>A task that represents the completion of request processing.</returns>
    public async Task Invoke(HttpContext context)
    {
        // Generate a nonce (number used once) for inline scripts and styles
        var nonce = Convert.ToBase64String(Guid.NewGuid().ToByteArray());

        // Store the nonce in the context items for later use
        context.Items["csp-nonce"] = nonce;

        // Add the CSP header to the response
        context.Response.OnStarting(() =>
        {
            context.Response.Headers.Append("Content-Security-Policy",
                string.Format(_policy, nonce));
            return Task.CompletedTask;
        });

        // Call the next middleware in the pipeline
        await _next(context);
    }
}