using Microsoft.AspNetCore.Http;
using Serilog.Context;
using System;
using System.IO;
using System.Threading.Tasks;

namespace IRaCIS.Core.API._PipelineExtensions.Serilog
{
    public class RequestResponseLoggingMiddleware
    {
        private readonly RequestDelegate _next;

        public RequestResponseLoggingMiddleware(RequestDelegate next)
        {
            _next = next;
        }

        public async Task Invoke(HttpContext context)
        {
            var ContentType = context.Request.ContentType;

            var isUploadRelation = false;

            if (ContentType != null)
            {
                isUploadRelation = context.Request.ContentType.Contains("multipart/form-data") || context.Request.ContentType.Contains("boundary") || context.Request.ContentType.Contains("octet-stream");
            }


            if (isUploadRelation)
            {
                using (LogContext.PushProperty("RequestBody", string.Empty))
                {
                    await _next.Invoke(context);
                }
            }
            else
            {

                var requestBodyPayload = await ReadRequestBody(context.Request);

                context.Items["RequestBody"] = requestBodyPayload;

                using (LogContext.PushProperty("RequestBody", requestBodyPayload))
                {
                    //await _next.Invoke()
                    await _next.Invoke(context);
                }
            }

            //var request = context.Request;


            // Read and log request body data

            //SerilogHelper.RequestPayload = requestBodyPayload;

            #region ResponseBody

            //// Read and log response body data
            //// Copy a pointer to the original response body stream
            //var originalResponseBodyStream = context.Response.Body;

            //// Create a new memory stream...
            //using (var responseBody = new MemoryStream())
            //{
            //	// ...and use that for the temporary response body
            //	context.Response.Body = responseBody;

            //	// Continue down the Middleware pipeline, eventually returning to this class
            //await _next(context);

            //	// Copy the contents of the new memory stream (which contains the response) to the original stream, which is then returned to the client.
            //	await responseBody.CopyToAsync(originalResponseBodyStream);
            //}
            //string responseBodyPayload = await ReadResponseBody(context.Response);
            //_diagnosticContext.Set("ResponseBody", responseBodyPayload);

            #endregion


        }

        private async Task<string> ReadRequestBody(HttpRequest request)
        {
            // Ensure the request's body can be read multiple times (for the next middlewares in the pipeline).
            request.EnableBuffering();

            using var streamReader = new StreamReader(request.Body, leaveOpen: true);
            var requestBody = await streamReader.ReadToEndAsync();

            // Reset the request's body stream position for next middleware in the pipeline.
            request.Body.Position = 0;
            return requestBody == null ? String.Empty : requestBody.Trim();
        }

        private static async Task<string> ReadResponseBody(HttpResponse response)
        {
            response.Body.Seek(0, SeekOrigin.Begin);
            string responseBody = await new StreamReader(response.Body).ReadToEndAsync();
            response.Body.Seek(0, SeekOrigin.Begin);

            return $"{responseBody}";
        }

    }
}
