using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using QYZH.InteractiveMagazine.Models.Common;
using QYZH.InteractiveMagazine.Models.Dto;
using System.Text.Json;

namespace QYZH.InteractiveMagazine.Infrastructure.Middleware;

/// <summary>
/// 全局异常中间件
/// </summary>
public class GlobalExceptionMiddleware : IMiddleware
{
    private readonly ILogger<GlobalExceptionMiddleware> _logger;

    /// <summary>
    /// JSON序列化选项（camelCase，与Controller保持一致）
    /// </summary>
    private static readonly JsonSerializerOptions JsonOptions = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase
    };

    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="logger">日志记录器</param>
    public GlobalExceptionMiddleware(ILogger<GlobalExceptionMiddleware> logger)
    {
        _logger = logger;
    }

    /// <summary>
    /// 执行中间件
    /// </summary>
    /// <param name="context">HTTP上下文</param>
    /// <param name="next">下一个中间件委托</param>
    public async Task InvokeAsync(HttpContext context, RequestDelegate next)
    {
        try
        {
            await next(context);
        }
        catch (BusinessException ex)
        {
            _logger.LogWarning(ex, "业务异常：{Message}，状态码：{ResultCode}", ex.Message, ex.ResultCode);
            await HandleBusinessExceptionAsync(context, ex);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "系统异常：{Message}", ex.Message);
            await HandleSystemExceptionAsync(context, ex);
        }
    }

    /// <summary>
    /// 处理业务异常（按业务状态码映射HTTP状态码）
    /// </summary>
    /// <param name="context">HTTP上下文</param>
    /// <param name="ex">业务异常</param>
    private static async Task HandleBusinessExceptionAsync(HttpContext context, BusinessException ex)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = GetHttpStatusCode(ex.ResultCode);

        var response = BaseResponse<object>.Fail(ex.ResultCode, ex.Message);
        var json = JsonSerializer.Serialize(response, JsonOptions);

        await context.Response.WriteAsync(json);
    }

    /// <summary>
    /// 处理系统异常
    /// </summary>
    /// <param name="context">HTTP上下文</param>
    /// <param name="ex">系统异常</param>
    private static async Task HandleSystemExceptionAsync(HttpContext context, Exception ex)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = StatusCodes.Status500InternalServerError;

        var response = BaseResponse<object>.Fail(ResultCode.GLOBAL_ERROR, "系统内部错误，请稍后重试");
        var json = JsonSerializer.Serialize(response, JsonOptions);

        await context.Response.WriteAsync(json);
    }

    /// <summary>
    /// 根据业务状态码获取对应的HTTP状态码
    /// </summary>
    /// <param name="resultCode">业务状态码</param>
    /// <returns>HTTP状态码</returns>
    private static int GetHttpStatusCode(ResultCode resultCode)
    {
        return resultCode switch
        {
            ResultCode.DENY => StatusCodes.Status401Unauthorized,
            ResultCode.FORBIDDEN => StatusCodes.Status403Forbidden,
            ResultCode.NOT_FOUND => StatusCodes.Status404NotFound,
            ResultCode.BAD_REQUEST => StatusCodes.Status400BadRequest,
            ResultCode.PARAM_ERROR => StatusCodes.Status400BadRequest,
            ResultCode.CONFLICT => StatusCodes.Status409Conflict,
            ResultCode.UNPROCESSABLE_ENTITY => StatusCodes.Status422UnprocessableEntity,
            ResultCode.TOO_MANY_REQUESTS => StatusCodes.Status429TooManyRequests,
            ResultCode.BAD_GATEWAY => StatusCodes.Status502BadGateway,
            ResultCode.SERVICE_UNAVAILABLE => StatusCodes.Status503ServiceUnavailable,
            _ => StatusCodes.Status400BadRequest
        };
    }
}
