using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http.Filters;

namespace DeviceRepair.Api.CustomAttribute
{
    public class GzipCompressionAttribute : ActionFilterAttribute
    {
        public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
        {
            if (actionExecutedContext.Response != null && actionExecutedContext.Response.Content != null)
            {
                var response = actionExecutedContext.Response;

                // 检查客户端是否接受 GZIP 压缩  
                var acceptsEncoding = actionExecutedContext.Request.Headers.AcceptEncoding;
                var gzipSupported = acceptsEncoding.Any(x => x.Value.Contains("gzip"));

                if (gzipSupported)
                {
                    // 读取原始响应内容  
                    var originalContent = await response.Content.ReadAsStringAsync();

                    // 压缩内容  
                    byte[] compressedContent = CompressString(originalContent);

                    // 创建一个新的内存流来保存压缩后的内容  
                    var compressedStream = new MemoryStream(compressedContent);

                    // 创建一个新的响应内容，并设置内容类型、编码和头部信息  
                    var compressedResponseContent = new StreamContent(compressedStream);
                    compressedResponseContent.Headers.ContentType = response.Content.Headers.ContentType;
                    compressedResponseContent.Headers.ContentEncoding.Add("gzip");

                    // 创建一个新的响应消息，并设置新的内容  
                    var newResponse = new HttpResponseMessage(response.StatusCode)
                    {
                        Content = compressedResponseContent,
                        ReasonPhrase = response.ReasonPhrase
                    };

                    // 将新的响应设置为 actionExecutedContext 的结果  
                    actionExecutedContext.Response = newResponse;
                }
            }

            // 调用基类的方法以继续管道中的后续操作  
            await base.OnActionExecutedAsync(actionExecutedContext, cancellationToken);
        }

        private byte[] CompressString(string str)
        {
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            var memoryStream = new MemoryStream();
            using (var gZipStream = new GZipStream(memoryStream, CompressionMode.Compress, true))
            {
                gZipStream.Write(buffer, 0, buffer.Length);
            }

            memoryStream.Position = 0;
            return memoryStream.ToArray();
        }
    }
}