Can you optimize the following C# Code:

#define Http2
//#define SEND_LUMINATI_HEADER

using System;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Security.Authentication;
using System.Threading.Tasks;
using System.Threading;
using System.Collections.Generic;
using System.Net.Http.Headers;
using System.IO;
using System.Text;
using System.Diagnostics;

#pragma warning disable CA1416

namespace Test.Helpers;

public static class HttpClientHelper
{
    public const string UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36";
    private static WebProxy? _localProxy;

    // public static readonly string? ProxySessionId;
    private const string TimeoutPropertyKey = "RequestTimeout";
    private static readonly HttpRequestOptionsKey<TimeSpan?> TimeoutOptionsKey;
    
    static HttpClientHelper()
    {
        // ProxySessionId = Strings.GetRandomUsername(5, 10);
        KeepUpdatingLocalProxy();
        TimeoutOptionsKey = new HttpRequestOptionsKey<TimeSpan?>(TimeoutPropertyKey);
    }

    public static async Task<string> GetValidContent(HttpMethod httpMethod, string url, string wordsToSearch, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, Proxy? proxy = null, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        string content;
        bool valid;
        var triesCounter = 0;
        do
        {
            if (proxy != null)
            {
                while (proxy != null && !proxy.Increment())
                {
                    proxy = ProxyHelper.GetAvailableProxy();
                }
                //writeLineDEBUG($"NEW Proxy: { proxy.ProxyString } | NOF: { proxy.NumOfFail } | UC: { proxy.UseCounter }");
            }
            else if (ProxyHelper.UseProxies)
            {
                proxy = ProxyHelper.GetAvailableProxy();
            }

            content = await Request(httpMethod, url, post, timeout, cookies, proxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (autoRedirect == false && content.StartsWith("$Redirected to$|:"))
            {
                valid = true;
                break;
            }

            valid = wordsToSearch == null || wordsToSearch.Split('|').Any(w => content.ToLower().Contains(w.ToLower()));
            if (!valid)
            {
                if (proxy != null)
                {
                    proxy.Enough = true;
                    proxy.NumOfFailIncrement();
                    Debug.WriteLine($"OLD Proxy: {proxy.ProxyString} | NOF: {proxy.FailCounter} | UC: {proxy.UsageCounter}");
                }

                await Task.Delay(700).ConfigureAwait(false);
            }
        }
        while (!valid && (maxTries == -1 || ++triesCounter < maxTries));

        if (valid)
            proxy?.ResetFailCounter();
        return content;
    }
    public static async Task<string> GetContentDoesNotContain(HttpMethod httpMethod, string url, string wordsToSearch, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, Proxy? proxy = null, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool alsoNotEmpty = true, int notLessThan = 700, bool noProxy = false)
    {
        string content;
        bool valid;
        var triesCounter = 0;
        do
        {
            if (proxy != null)
            {
                while (proxy != null && !proxy.Increment())
                {
                    proxy = ProxyHelper.GetAvailableProxy();
                }
                //writeLineDEBUG($"NEW Proxy: { proxy.ProxyString } | NOF: { proxy.NumOfFail } | UC: { proxy.UseCounter }");
            }
            else if (ProxyHelper.UseProxies)
            {
                proxy = ProxyHelper.GetAvailableProxy();
            }

            content = await Request(httpMethod, url, post, timeout, cookies, proxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (autoRedirect == false && content.StartsWith("$Redirected to$|:"))
            {
                valid = true;
                break;
            }

            valid = !alsoNotEmpty || content.Length > notLessThan;

            if (valid && !string.IsNullOrEmpty(wordsToSearch))
            {
                var words = wordsToSearch.Split('|');
                var contentLowered = content.ToLower();
                foreach (var word in words)
                {
                    if (contentLowered.Contains(word.ToLower()))
                    {
                        valid = false;
                        break;
                    }
                }
            }

            if (valid || proxy == null) continue;

            proxy.Enough = true;
            proxy.NumOfFailIncrement();
            Debug.WriteLine($"OLD Proxy: {proxy.ProxyString} | NOF: {proxy.FailCounter} | UC: {proxy.UsageCounter}");
            //Thread.Sleep(300);
        }
        while (!valid && (maxTries == -1 || ++triesCounter < maxTries));

        if (valid)
            proxy?.ResetFailCounter();
        //writeLineDEBUG($"Valid Content Proxy: { proxy.ProxyString } | UC: { proxy.useCounter }");
        return content;
    }
    public static async Task<HttpStatusCode> MakeSureFileDownloaded(HttpMethod httpMethod, string url, string path, bool overrideExist = true, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, Proxy? proxy = null, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        HttpStatusCode statusCode;
        bool downloaded;
        var triesCounter = 0;
        do
        {
            if (proxy != null)
            {
                while (proxy != null && !proxy.Increment())
                {
                    proxy = ProxyHelper.GetAvailableProxy();
                }
                //writeLineDEBUG($"NEW Proxy: { proxy.ProxyString } | NOF: { proxy.numOfFail } | UC: { proxy.useCounter }");

            }
            else if (ProxyHelper.UseProxies)
            {
                proxy = ProxyHelper.GetAvailableProxy();
            }

            statusCode = await DownloadFile(httpMethod, url, path, overrideExist, post, timeout, cookies, proxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (autoRedirect == false && statusCode == HttpStatusCode.Redirect)
            {
                downloaded = true;
                break;
            }

            downloaded = statusCode is HttpStatusCode.OK or HttpStatusCode.Found;
            if (!downloaded)
            {
                if (proxy != null)
                {
                    proxy.Enough = true;
                    proxy.NumOfFailIncrement();
                    Debug.WriteLine($"OLD Proxy: {proxy.ProxyString} | NOF: {proxy.FailCounter} | UC: {proxy.UsageCounter} | Download:{statusCode}");
                }
                //Thread.Sleep(300);
            }
        } while (!downloaded && (maxTries == -1 || ++triesCounter < maxTries));

        if (downloaded)
            proxy?.ResetFailCounter();

        return statusCode;
    }
    public static async Task<byte[]?> MakeSureFileDownloadedToMemory(HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, Proxy? proxy = null, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        byte[]? result;
        bool downloaded;
        var triesCounter = 0;
        do
        {
            if (proxy != null)
            {
                while (proxy != null && !proxy.Increment())
                {
                    proxy = ProxyHelper.GetAvailableProxy();
                }
                //writeLineDEBUG($"NEW Proxy: { proxy.ProxyString } | NOF: { proxy.numOfFail } | UC: { proxy.useCounter }");

            }
            else if (ProxyHelper.UseProxies)
            {
                proxy = ProxyHelper.GetAvailableProxy();
            }
            result = await DownloadFileToMemory(httpMethod, url, post, timeout, cookies, proxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            //BadGateway > 502 | Forbidden > 403 | Unauthorized	> 401 etc....
            downloaded = result != null && result.Length != 3;

            if (downloaded || (autoRedirect == false && result == Encoding.UTF8.GetBytes(HttpStatusCode.Redirect.ToString())))
                break;
            
            if (!downloaded)
            {
                if (proxy != null)
                {
                    proxy.Enough = true;
                    proxy.NumOfFailIncrement();
                    Debug.WriteLine($"OLD Proxy: {proxy.ProxyString} | NOF: {proxy.FailCounter} | UC: {proxy.UsageCounter}");
                }
                //Thread.Sleep(300);
            }
        } while (!downloaded && (maxTries == -1 || ++triesCounter < maxTries));

        if (downloaded)
            proxy?.ResetFailCounter();

        return result;
    }
    public static async Task<string> Request(HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, Proxy? proxy = null, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        string output;
        try
        {
            var response = await SendAsync(httpMethod, url, post, timeout, cookies, proxy?.WebProxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (!autoRedirect && response.StatusCode == HttpStatusCode.Redirect)
                return $"$Redirected to$|:{response.Headers.Location}";

            output = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
        catch (Exception e)
        {
            var err = e.InnerException == null ? e.Message : e.InnerException.Message;
            //writeLineDEBUG(err);
            output = err;
        }
        return output;
    }
    public static async Task<HttpStatusCode> DownloadFile(HttpMethod httpMethod, string url, string path, bool overrideExist = true, byte[]? post = null, int timeout = 120_000, CookieContainer? cookies = null, Proxy? proxy = null, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        url = TryGetValidUrl(url)!;
        if (string.IsNullOrWhiteSpace(url)) return HttpStatusCode.RequestUriTooLong;

        if (!overrideExist && File.Exists(path)) return HttpStatusCode.Found;

        try
        {
            var response = await SendAsync(httpMethod, url, post, timeout, cookies, proxy?.WebProxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (response.StatusCode is not (HttpStatusCode.OK or HttpStatusCode.Found)) return response.StatusCode;

            await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
            await using var fs = File.Create(path);
            await responseStream.CopyToAsync(fs).ConfigureAwait(false);
        }
        catch
        {
            return HttpStatusCode.BadRequest;
        }

        return HttpStatusCode.OK;
    }
    public static async Task<byte[]?> DownloadFileToMemory(HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 120_000, CookieContainer? cookies = null, Proxy? proxy = null, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        url = TryGetValidUrl(url)!;
        if (string.IsNullOrWhiteSpace(url)) return default;

        try
        {
            var response = await SendAsync(httpMethod, url, post, timeout, cookies, proxy?.WebProxy, autoRedirect, aHeaders, noProxy).ConfigureAwait(false);

            if (response.StatusCode is not HttpStatusCode.OK)
                return Encoding.UTF8.GetBytes(((int)response.StatusCode).ToString());

            return await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
        }
        catch
        {
            return default;
        }
    }
    private static Task<HttpResponseMessage> SendAsync(HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, CookieContainer? cookies = null, WebProxy? proxy = null, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool noProxy = false)
    {
        var uri = new Uri(url);
        var finalProxy = noProxy ? null : proxy ?? _localProxy;
#if Http2
        var handler = (Http2CustomHandler)CreateWinHttpHandler(timeout, cookies, finalProxy, autoRedirect);
#else
        var handler = CreateHttpHandler(cookies, proxy, autoRedirect);
#endif

        using var client = new HttpClient(handler);

        client.DefaultRequestHeaders.Host = uri.Host;
        client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent);

        var request = new HttpRequestMessage
        {
            RequestUri = uri,
            Method = httpMethod
        };

        request.SetTimeout(TimeSpan.FromMilliseconds(timeout));
        request.Headers.ExpectContinue = false;

        if (aHeaders == null || aHeaders.Keys.All(k => k.ToLower() != "accept"))
            request.Headers.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        if (aHeaders == null || aHeaders.Keys.All(k => k.ToLower() != "accept-encoding"))
            request.Headers.AcceptEncoding.ParseAdd("gzip, deflate, br");
        if (aHeaders == null || aHeaders.Keys.All(k => k.ToLower() != "accept-language"))
            request.Headers.AcceptLanguage.ParseAdd("en-US,en;q=0.9,ar;q=0.8");
        //if (aHeaders == null || aHeaders.Keys.All(k => k.ToLower() != "referer"))
        //    request.Headers.Referrer = uri;

        if (aHeaders != null)
            foreach (var header in aHeaders)
                request.Headers.TryAddWithoutValidation(header.Key, header.Value);

#if SEND_LUMINATI_HEADER
        if (Bot.OnlyPaidProxies)
            request.Headers.TryAddWithoutValidation("x-lpm-session", ProxySessionId);
#endif

        if (post != null)
        {
            request.Content = new ByteArrayContent(post);

            var contentType = aHeaders?.FirstOrDefault(h => h.Key.Equals("content-type", StringComparison.InvariantCultureIgnoreCase)).Value;
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType ?? "application/x-www-form-urlencoded");
        }
        
        return client.SendAsync(request);
    }

    public static async Task<string> GetValidContent<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, string wordsToSearch, byte[]? post = null, int timeout = 60_000, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        var triesCounter = 0;
        while (maxTries == -1 || triesCounter < maxTries)
        {
            var content = await Request(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (autoRedirect == false && content.StartsWith("$Redirected to$|:"))
                break;
            if (string.IsNullOrEmpty(wordsToSearch) || wordsToSearch.Split('|').Any(w => content.Contains(w, StringComparison.OrdinalIgnoreCase)))
                return content;

            await Task.Delay(700).ConfigureAwait(false);
            triesCounter++;
        }

        return string.Empty;
    }
    public static async Task<string> GetContentDoesNotContain<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, string wordsToSearch, byte[]? post = null, int timeout = 60_000, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null, bool alsoNotEmpty = true, int notLessThan = 700) where T : HttpMessageHandler
    {
        var triesCounter = 0;
        while (maxTries == -1 || triesCounter < maxTries)
        {
            var content = await Request(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (autoRedirect == false && content.StartsWith("$Redirected to$|:"))
                break;

            if ((!alsoNotEmpty || content.Length > notLessThan) && (string.IsNullOrEmpty(wordsToSearch) || !wordsToSearch.Split('|').Any(word => content.Contains(word, StringComparison.OrdinalIgnoreCase))))
                return content;

            await Task.Delay(700).ConfigureAwait(false);
            triesCounter++;
        }

        return string.Empty;
    }
    public static async Task<HttpStatusCode> MakeSureFileDownloaded<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, string path, bool overrideExist = true, byte[]? post = null, int timeout = 60_000, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        HttpStatusCode statusCode;
        bool downloaded;
        var triesCounter = 0;
        do
        {
            statusCode = await DownloadFile(client, httpMethod, url, path, overrideExist, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (autoRedirect == false && statusCode == HttpStatusCode.Redirect)
                break;

            downloaded = statusCode is HttpStatusCode.OK or HttpStatusCode.Found;
            if (!downloaded)
                await Task.Delay(700).ConfigureAwait(false);
        }
        while (!downloaded && (maxTries == -1 || ++triesCounter < maxTries));

        return statusCode;
    }
    public static async Task<byte[]?> MakeSureFileDownloadedToMemory<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, int maxTries = -1, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        byte[]? result;
        bool downloaded;
        var triesCounter = 0;
        do
        {
            result = await DownloadFileToMemory(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            //BadGateway > 502 | Forbidden > 403 | Unauthorized	> 401 etc....
            downloaded = result != null && result.Length != 3;

            if (downloaded || (autoRedirect == false && result == Encoding.UTF8.GetBytes(HttpStatusCode.Redirect.ToString())))
                break;

            await Task.Delay(700).ConfigureAwait(false);
        }
        while (!downloaded && (maxTries == -1 || ++triesCounter < maxTries));

        return result;
    }
    public static async Task<string> Request<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        string output;
        try
        {
            var response = await SendAsync(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (!autoRedirect && response.StatusCode == HttpStatusCode.Redirect)
                return $"$Redirected to$|:{response.Headers.Location}";

            output = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
        }
        catch (Exception e)
        {
            var err = e.InnerException == null ? e.Message : e.InnerException.Message;
            //writeLineDEBUG(err);
            output = err;
        }
        return output;
    }
    public static async Task<HttpStatusCode> DownloadFile<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, string path, bool overrideExist = true, byte[]? post = null, int timeout = 120_000, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        url = TryGetValidUrl(url)!;
        if (string.IsNullOrWhiteSpace(url)) return HttpStatusCode.RequestUriTooLong;

        if (!overrideExist && File.Exists(path)) return HttpStatusCode.Found;

        try
        {
            var response = await SendAsync(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (response.StatusCode is not (HttpStatusCode.OK or HttpStatusCode.Found)) return response.StatusCode;

            await using var responseStream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false);
            await using var fs = File.Create(path);
            await responseStream.CopyToAsync(fs).ConfigureAwait(false);
        }
        catch
        {
            return HttpStatusCode.BadRequest;
        }

        return HttpStatusCode.OK;
    }
    public static async Task<byte[]?> DownloadFileToMemory<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 120_000, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        url = TryGetValidUrl(url)!;
        if (string.IsNullOrWhiteSpace(url)) return default;

        try
        {
            var response = await SendAsync(client, httpMethod, url, post, timeout, autoRedirect, aHeaders).ConfigureAwait(false);

            if (response.StatusCode is not HttpStatusCode.OK)
                return Encoding.UTF8.GetBytes(((int)response.StatusCode).ToString());

            return await response.Content.ReadAsByteArrayAsync().ConfigureAwait(false);
        }
        catch
        {
            return default;
        }
    }
    private static Task<HttpResponseMessage> SendAsync<T>(CustomHttpClient<T> client, HttpMethod httpMethod, string url, byte[]? post = null, int timeout = 60_000, bool autoRedirect = true, Dictionary<string, string?>? aHeaders = null) where T : HttpMessageHandler
    {
        var uri = new Uri(url);
        var request = new HttpRequestMessage
        {
            RequestUri = uri,
            Method = httpMethod
        };

        request.SetTimeout(TimeSpan.FromMilliseconds(timeout));
        request.Headers.ExpectContinue = false;

        //if (aHeaders == null || aHeaders.Keys.All(k => k.ToLower() != "referer"))
        //    request.Headers.Referrer = uri;
        if (aHeaders != null)
            foreach (var header in aHeaders)
                request.Headers.TryAddWithoutValidation(header.Key, header.Value);

#if SEND_LUMINATI_HEADER
            if (Bot.OnlyPaidProxies)
                request.Headers.TryAddWithoutValidation("x-lpm-session", ProxySessionId);
#endif

        if (post != null)
        {
            request.Content = new ByteArrayContent(post);

            var contentType = aHeaders?.FirstOrDefault(h => h.Key.Equals("content-type", StringComparison.InvariantCultureIgnoreCase)).Value;
            request.Content.Headers.ContentType = MediaTypeHeaderValue.Parse(contentType ?? "application/x-www-form-urlencoded");
        }

        TryToSetHandlerRedirect(client.Handler, autoRedirect);
        return client.SendAsync(request);
    }


    /// <summary>
    /// Returns a valid URL if it's valid or missing just http: |
    /// Returns null if it's not valid
    /// </summary>
    public static string? TryGetValidUrl(string? url)
    {
        if (url == null) return null;

        if (url.StartsWith("//")) url = $"http:{url}";
        return CheckUrlValid(url) ? url : null;
    }
    public static bool CheckUrlValid(string source)
    {
        return Uri.TryCreate(source, UriKind.Absolute, out var uriResult)
               && (uriResult.Scheme == Uri.UriSchemeHttp || uriResult.Scheme == Uri.UriSchemeHttps);
    }

    private static async void KeepUpdatingLocalProxy()
    {
#if DEBUG
        while (true)
        {
            try
            {
                using var client = new System.Net.Sockets.TcpClient();
                var result = client.BeginConnect("127.0.0.1", 17073, null, null);
                result.AsyncWaitHandle.WaitOne(2000);
                client.EndConnect(result);

                _localProxy = _localProxy ?? new WebProxy("127.0.0.1", 17073);
            }
            catch
            {
                _localProxy = null;
            }

            await Task.Delay(3000).ConfigureAwait(false);
        }
#else
        _localProxy = null;
#endif
        // ReSharper disable once FunctionNeverReturns
    }

    #region Http Client & Handler
    public static CustomHttpClient<T> CreateHttpClient<T>(T handler, bool disposeHandler = true) where T : HttpMessageHandler
    {
        var client = new CustomHttpClient<T>(handler, disposeHandler);
        client.DefaultRequestHeaders.UserAgent.ParseAdd(UserAgent);
        client.DefaultRequestHeaders.Accept.ParseAdd("text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
        client.DefaultRequestHeaders.AcceptEncoding.ParseAdd("gzip, deflate, br");
        client.DefaultRequestHeaders.AcceptLanguage.ParseAdd("en-US,en;q=0.9,ar;q=0.8");
        //client.DefaultRequestHeaders.ExpectContinue = false;

        return client;
    }
    public static HttpClientHandler CreateHttpHandler(CookieContainer? cookies = null, WebProxy? proxy = null, bool autoRedirect = true)
    {
        return new HttpClientHandler
        {
            ServerCertificateCustomValidationCallback = delegate { return true; },
            SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12,
            UseProxy = proxy != null,
            Proxy = proxy,
            UseCookies = /*cookies != null*/ true,
            CookieContainer = cookies ?? new CookieContainer(),
            AllowAutoRedirect = autoRedirect,
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli
        };
    }

#if Http2
    public static WinHttpHandler CreateWinHttpHandler(int timeout = 60_000, CookieContainer? cookies = null, WebProxy? proxy = null, bool autoRedirect = true, bool keepAlive = true)
    {
        var sTimeout = TimeSpan.FromMilliseconds(timeout);
        return new WinHttpHandler
        {
            ServerCertificateValidationCallback = delegate { return true; },
            SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12,
            WindowsProxyUsePolicy = proxy == null ? WindowsProxyUsePolicy.DoNotUseProxy : WindowsProxyUsePolicy.UseCustomProxy,
            Proxy = proxy,
            CookieUsePolicy = /*cookies == null ? CookieUsePolicy.IgnoreCookies : */CookieUsePolicy.UseSpecifiedCookieContainer,
            CookieContainer = cookies ?? new CookieContainer(),
            AutomaticRedirection = autoRedirect,
            TcpKeepAliveEnabled = keepAlive,
            ReceiveDataTimeout = sTimeout,
            ReceiveHeadersTimeout = sTimeout,
            SendTimeout = sTimeout,
            AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate | DecompressionMethods.Brotli
        };
    }
#endif

    private static void TryToSetHandlerRedirect<T>(T handler, bool autoRedirect = true) where T : HttpMessageHandler
    {
        switch (handler)
        {
            case WinHttpHandler whh:
                whh.AutomaticRedirection = autoRedirect;
                break;
            case HttpClientHandler hch:
                hch.AllowAutoRedirect = autoRedirect;
                break;
        }
    }
    public static void SetTimeout(this HttpRequestMessage request, TimeSpan? timeout)
    {
        if (request == null)
            throw new ArgumentNullException(nameof(request));

        request.Options.Set(TimeoutOptionsKey, timeout);
    }

    public static TimeSpan? GetTimeout(this HttpRequestMessage request)
    {
        if (request == null)
            throw new ArgumentNullException(nameof(request));

        return request.Options.TryGetValue(TimeoutOptionsKey, out var value) ? value : null;
    }

    public class CustomHttpClient<T> : HttpClient where T : HttpMessageHandler
    {
        //public TimeSpan DefaultTimeout { get; set; } = TimeSpan.FromSeconds(100);
        public T Handler { get; }

        public CustomHttpClient(T handler, bool disposeHandler = true) : base(handler, disposeHandler)
        {
            Timeout = System.Threading.Timeout.InfiniteTimeSpan;
            Handler = handler;
        }

        public override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
#if Http2
            if (Handler is WinHttpHandler)
                request.Version = new Version("2.0");
#endif

            using var cts = GetCancellationTokenSource(request, cancellationToken);
            try
            {
                var response = await base.SendAsync(request, cts?.Token ?? cancellationToken).ConfigureAwait(false);

                if (!response.Content.Headers.TryGetValues("Content-Encoding", out var ce) || ce.First() != "br")
                    return response;

                //var buffer = await response.Content.ReadAsByteArrayAsync(cancellationToken).ConfigureAwait(false);
                //response.Content = new ByteArrayContent(Brotli.DecompressBuffer(buffer, 0, buffer.Length));
                var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
                response.Content = new StreamContent(new BrotliStream(stream, CompressionMode.Decompress));
                return response;
            }
            catch (OperationCanceledException ex) when (!cancellationToken.IsCancellationRequested)
            {
                throw new TimeoutException(ex.Message, ex);
            }
        }

        private CancellationTokenSource? GetCancellationTokenSource(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            var timeout = request.GetTimeout() ?? Timeout;
            if (timeout == System.Threading.Timeout.InfiniteTimeSpan)
            {
                // No need to create a CTS if there's no timeout
                return null;
            }

            var cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
            cts.CancelAfter(timeout);
            return cts;
        }
    }

#if Http2
    public class Http2CustomHandler : WinHttpHandler
    {
        protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            request.Version = new Version("2.0");
            var response = await base.SendAsync(request, cancellationToken).ConfigureAwait(false);
            if (!response.Content.Headers.TryGetValues("Content-Encoding", out var ce) || ce.First() != "br")
                return response;
            //var buffer = await response.Content.ReadAsByteArrayAsync(cancellationToken).ConfigureAwait(false);
            //response.Content = new ByteArrayContent(Brotli.DecompressBuffer(buffer, 0, buffer.Length));
            var stream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
            response.Content = new StreamContent(new BrotliStream(stream, CompressionMode.Decompress));
            return response;
        }
    }
#endif
    #endregion
}