using Microsoft.Extensions.Primitives;

namespace ErsatzTV.Middleware;

/// <summary>
///     Builds the request path Serilog logs with the <c>access_token</c> query value redacted (#559).
///     The default <c>UseSerilogRequestLogging</c> template logs the full query for every request; the
///     <c>ex != null</c> and <c>StatusCode &gt; 499</c> branches log at Error regardless of path, so a 5xx
///     on an <c>/iptv/...?access_token=&lt;jwt&gt;</c> URL would otherwise write the replayable, globally
///     scoped token to the log. This keeps the rest of the query (e.g. <c>mode=segmenter</c>) for
///     debugging while masking only the credential.
/// </summary>
internal static class RequestLogScrubber
{
    private const string TokenParameter = "access_token";
    private const string Redacted = "***";

    public static string ScrubbedPath(HttpRequest request)
    {
        string path = request.Path.ToString();
        if (!request.QueryString.HasValue)
        {
            return path;
        }

        var pairs = new List<string>();
        foreach (KeyValuePair<string, StringValues> pair in request.Query)
        {
            bool isToken = string.Equals(pair.Key, TokenParameter, StringComparison.OrdinalIgnoreCase);
            pairs.Add($"{pair.Key}={(isToken ? Redacted : pair.Value.ToString())}");
        }

        return pairs.Count == 0 ? path : $"{path}?{string.Join('&', pairs)}";
    }
}
