using Microsoft.Data.SqlClient;
namespace OASystem.API.Middlewares
{
    /// 
    /// 全局异常捕获中间件
    /// 
    public class ExceptionHandlingMiddleware
    {
        private readonly RequestDelegate _next;  // 用来处理上下文请求
        private readonly ILogger _logger;
        /// 
        /// 初始化
        /// 
        /// 
        /// 
        public ExceptionHandlingMiddleware(RequestDelegate next, ILogger logger)
        {
            _next = next;
            _logger = logger;
        }
        /// 
        /// 执行中间件
        /// 
        /// 
        /// 
        /// 
        public async Task InvokeAsync(HttpContext httpContext, SqlSugarClient db)
        {
            try
            {
                await _next(httpContext); //要么在中间件中处理,要么被传递到下一个中间件中去
            }
            catch (Exception ex)
            {
                await HandleExceptionAsync(httpContext, ex, db); // 捕获异常了 在HandleExceptionAsync中处理
            }
        }
        /// 
        /// 自定义全局异常处理方法
        /// 
        /// 
        /// 
        /// 
        /// 
        private async Task HandleExceptionAsync(HttpContext context, Exception exception, SqlSugarClient db)
        {
            //if (db.Ado != null && db.Ado.Transaction != null)
            //{
            //    try
            //    {
            //        db.Ado.RollbackTran();
            //    }
            //    catch (Exception ex)
            //    {
            //        _logger.LogError("Error rolling back transaction: {ErrorMessage}", ex.Message);
            //    }
            //}
            // 检查响应是否已开始
            if (!context.Response.HasStarted)
            {
                context.Response.ContentType = "application/json"; // 设置响应内容类型为 JSON
                var response = context.Response;
                var errorResponse = new JsonView
                {
                    Code = StatusCodes.Status500InternalServerError,
                    Data = ""
                };
                // 根据异常类型设置不同的响应状态码和消息
                switch (exception)
                {
                    case SqlException sqlEx when sqlEx.Number == -2:
                        response.StatusCode = StatusCodes.Status503ServiceUnavailable;
                        errorResponse.Msg = "数据库连接超时,请稍后重试。";
                        break;
                    case SqlException sqlEx when sqlEx.Number == -4:
                        response.StatusCode = StatusCodes.Status503ServiceUnavailable;
                        errorResponse.Msg = "数据库连接池耗尽,请稍后重试。";
                        break;
                    case ApplicationException ex when ex.Message.Contains("Invalid token"):
                        response.StatusCode = StatusCodes.Status403Forbidden;
                        errorResponse.Msg = ex.Message;
                        break;
                    case ApplicationException ex:
                        response.StatusCode = StatusCodes.Status400BadRequest;
                        errorResponse.Msg = ex.Message;
                        break;
                    case KeyNotFoundException ex:
                        response.StatusCode = StatusCodes.Status404NotFound;
                        errorResponse.Msg = ex.Message;
                        break;
                    case SqlSugarException ex:
                        response.StatusCode = ex.Message.Contains("timeout")
                            ? StatusCodes.Status503ServiceUnavailable
                            : StatusCodes.Status500InternalServerError;
                        errorResponse.Msg = ex.Message.Contains("timeout")
                            ? "数据库连接超时,请稍后重试。"
                            : ex.Message;
                        break;
                    default:
                        response.StatusCode = StatusCodes.Status500InternalServerError;
                        errorResponse.Msg = "服务器内部错误"; // 不直接暴露异常详细信息
                        break;
                }
                _logger.LogError(exception, "An exception occurred."); // 记录异常详细信息
                var result = JsonConvert.SerializeObject(errorResponse);
                await context.Response.WriteAsync(result); // 将错误响应写入客户端
            }
            else
            {
                // 如果响应已开始,记录日志但不做进一步处理
                _logger.LogError(exception, "An exception occurred after response started.");
            }
        }
    }
}