using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using XYY.Core.Standard.Mvc;
using System.Threading.Tasks;
using System.IO;
using Microsoft.AspNetCore.Http;

namespace XYY.Core.Standard.Data.Infrastructure
{
    public class ApiActionFilterAttribute : Attribute, IActionFilter
    {
        public void OnActionExecuted(ActionExecutedContext context)
        {
            var uw = context.HttpContext.RequestServices.GetService<IUnitOfWork>();
            if (context.Exception == null)
                uw.Commit();
            else
            {
                uw.Rollback();
            }
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {

        }
    }

    public class ApiLogMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<ApiLogMiddleware> _logger;

        public ApiLogMiddleware(RequestDelegate next, ILogger<ApiLogMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }
        public async Task Invoke(HttpContext context)
        {

            string requestMessage = "";
            try
            {
                context.Request.EnableBuffering();
                if (context.Request.QueryString.HasValue)
                {
                    requestMessage += context.Request.QueryString;
                }
                using (StreamReader reader = new StreamReader(context.Request.Body, Encoding.UTF8, true, 1024, true))
                {
                    requestMessage += await reader.ReadToEndAsync();
                }
            }
            finally
            {
                context.Request.Body.Position = 0;
            }

            Stream originalBody = context.Response.Body;
            string responseBody = string.Empty;
            try
            {
                using (var memStream = new MemoryStream())
                {
                    context.Response.Body = memStream;

                    await _next(context);

                    memStream.Position = 0;
                    responseBody = await new StreamReader(memStream).ReadToEndAsync(); 
                    memStream.Position = 0;
                    await memStream.CopyToAsync(originalBody);
                }
            }
            finally
            {
                context.Response.Body = originalBody;
            }
            try
            {
                var data = Newtonsoft.Json.JsonConvert.DeserializeObject<ApiJsonModel>(responseBody);
                if (!data.success)
                {
                    this._logger.LogError("Url:{action},Request:{request},Response:{response}",
                        context.Request.Host, requestMessage, data.error ?? data.message);
                }
            }
            catch (Exception ex)
            {
                this._logger.LogError("Url:{action},Request:{request},Response:{response}",
                    context.Request.Host, requestMessage, responseBody);
            }
        }
    }



}