using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using TakeoutSaaS.Shared.Abstractions.Constants;
using TakeoutSaaS.Shared.Abstractions.Results;

namespace TakeoutSaaS.Shared.Web.Filters;

/// <summary>
/// ApiResponse 结果过滤器：自动将 ApiResponse 转换为对应的 HTTP 状态码。
/// 使用此过滤器后，控制器可以直接返回 ApiResponse&lt;T&gt;，无需再包一层 Ok() 或 Unauthorized()。
/// </summary>
public sealed class ApiResponseResultFilter : IAsyncResultFilter
{
    /// <summary>
    /// 执行结果过滤，将 ApiResponse 映射为对应 HTTP 状态码。
    /// </summary>
    /// <param name="context">结果执行上下文。</param>
    /// <param name="next">后续委托。</param>
    /// <returns>异步任务。</returns>
    public Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
    {
        // 1. 仅处理 ObjectResult
        // 只处理 ObjectResult 类型的结果
        if (context.Result is not ObjectResult objectResult)
        {
            return next();
        }

        // 2. 结果为空直接跳过
        var value = objectResult.Value;
        if (value == null)
        {
            return next();
        }

        // 3. 确认类型为 ApiResponse<T>
        // 检查是否是 ApiResponse<T> 类型
        var valueType = value.GetType();
        if (!IsApiResponseType(valueType))
        {
            return next();
        }

        // 4. 读取 Success 与 Code
        // 使用反射获取 Success 和 Code 属性
        // 注意：由于已通过 IsApiResponseType 检查，属性名是固定的
        const string successPropertyName = "Success";
        const string codePropertyName = "Code";
        var successProperty = valueType.GetProperty(successPropertyName);
        var codeProperty = valueType.GetProperty(codePropertyName);

        if (successProperty == null || codeProperty == null)
        {
            return next();
        }

        var success = (bool)(successProperty.GetValue(value) ?? false);
        var code = (int)(codeProperty.GetValue(value) ?? 200);

        // 5. 映射 HTTP 状态码
        // 根据 Success 和 Code 设置 HTTP 状态码
        var statusCode = success ? MapSuccessCode(code) : MapErrorCode(code);

        // 6. 回写状态码
        // 更新 ObjectResult 的状态码
        objectResult.StatusCode = statusCode;

        return next();
    }

    private static bool IsApiResponseType(Type type)
    {
        // 检查是否是 ApiResponse<T> 类型
        if (type.IsGenericType)
        {
            var genericTypeDefinition = type.GetGenericTypeDefinition();
            return genericTypeDefinition == typeof(ApiResponse<>);
        }

        return false;
    }

    private static int MapSuccessCode(int code)
    {
        // 成功情况下，通常返回 200
        // 但也可以根据业务码返回其他成功状态码（如 201 Created）
        return code switch
        {
            200 => StatusCodes.Status200OK,
            201 => StatusCodes.Status201Created,
            204 => StatusCodes.Status204NoContent,
            _ => StatusCodes.Status200OK
        };
    }

    private static int MapErrorCode(int code)
    {
        // 根据业务错误码映射到 HTTP 状态码
        return code switch
        {
            ErrorCodes.BadRequest => StatusCodes.Status400BadRequest,
            ErrorCodes.Unauthorized => StatusCodes.Status401Unauthorized,
            ErrorCodes.Forbidden => StatusCodes.Status403Forbidden,
            ErrorCodes.NotFound => StatusCodes.Status404NotFound,
            ErrorCodes.Conflict => StatusCodes.Status409Conflict,
            ErrorCodes.ValidationFailed => StatusCodes.Status422UnprocessableEntity,
            ErrorCodes.InternalServerError => StatusCodes.Status500InternalServerError,
            // 业务错误码（10000+）统一返回 422
            >= 10000 => StatusCodes.Status422UnprocessableEntity,
            // 默认返回 400
            _ => StatusCodes.Status400BadRequest
        };
    }
}
