using Ashermed.ApiLogCoreFramework.ContractModel;
using Ashermed.ApiLogCoreFramework.Service;
using ASHermed.SinoInterface.Code;
using ASHermed.SinoInterface.Exception;
using ASHermed.SinoInterface.Tools;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using PoJun.Util;
using System;
using System.Threading.Tasks;

namespace ASHermed.SinoInterface.WebApi.Filters
{
	/// <summary>
	/// 全局异常处理过滤器
	/// </summary>
	public class ExceptionLogAttribute : IAsyncExceptionFilter
	{
		#region 初始化

		/// <summary>
		/// 接口日志服务
		/// </summary>
		private readonly IAPILogService apiLogService;

		/// <summary>
		/// 文本日志
		/// </summary>
		private readonly ILogger<ExceptionLogAttribute> logger;

		/// <summary>
		/// 初始化
		/// </summary>
		/// <param name="_apiLogService"></param>
		/// <param name="_logger"></param>
		public ExceptionLogAttribute(IAPILogService _apiLogService, ILogger<ExceptionLogAttribute> _logger)
		{
			apiLogService = _apiLogService;
			logger = _logger;
		}

		#endregion

		/// <summary>
		///
		/// </summary>
		/// <param name="context"></param>
		/// <returns></returns>
		public async Task OnExceptionAsync(ExceptionContext context)
		{
			var dto = new ContractModel.BaseResponse();
			bool isError = false;
			
			switch (context.Exception)
			{
				case BaseException baseException:
					dto.Code = (int)baseException.DetailedStatus;
					//dto.GatewayStatus = baseException.GatewayStatus;
					dto.Msg = $"{context.Exception.Message}";
					logger.LogError("报错抓取:" + context.Exception.Message);
					//dto.GatewayMessage = dto.GatewayStatus.Description();
					break;
				default:
					dto.Code = 0;
					dto.Msg = $"{context.Exception.Message}";
					logger.LogError("报错抓取:" + context.Exception.Message);
					//dto.GatewayStatus = GatewayStatusCode.Fail;
					//dto.GatewayMessage = dto.GatewayStatus.Description();
					isError = true;
					break;
			}

			var serializerSettings = new JsonSerializerSettings
			{
				//设置为不是驼峰命名
				ContractResolver = new DefaultContractResolver()
			};

			if (APIConfig.GetInstance().IsLittleCamelFormat)
				//设置为驼峰命名
				serializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();

			var result = JsonConvert.SerializeObject(dto, serializerSettings).Replace("Code", "code").Replace("Msg", "msg");
			context.Result = new ContentResult() { Content = result };


			#region 新增接口返回日志

			context.HttpContext.Items.TryGetValue(nameof(APILogConfig.PoJun_LogTraceID), out object logTraceID);
			if (logTraceID != null)
			{
				context.HttpContext.Items.TryGetValue(nameof(APILogConfig.RequestTime), out object _requestTime);
				var logParam = new AddResponseLogParam
				{
					ResponseBody = result,
					ErrorBody = $"StackTrace:{context.Exception.StackTrace} | Message:{context.Exception.Message} | Source:{context.Exception.Source}",
					IsError = isError,
					ParentTraceID = logTraceID.SafeString(),
					ResponseTime = DateTime.Now
				};
				logParam.TimeCost = Convert.ToInt32((logParam.ResponseTime - Convert.ToDateTime(_requestTime)).TotalMilliseconds);
				try
				{
					//logger.LogError(JsonConvert.SerializeObject(logParam));
					await apiLogService.AddResponseLogAsync(logParam);
				}
				catch (System.Exception)
				{
					logger.LogWarning($"{Newtonsoft.Json.JsonConvert.SerializeObject(logParam)},");
				}
			}

			#endregion

			context.Exception = null;
		}
	}
}
