using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.AspNetCore.Mvc;

namespace IRaCIS.Application.Services.BusinessFilter
{
    /// <summary>
    ///  统一返回前端数据包装，之前在控制器包装，现在修改为动态Api  在ResultFilter这里包装，减少重复冗余代码
    /// by zhouhang 2021.09.12 周末
    /// </summary>
    public class UnifiedApiResultFilter : Attribute, IAsyncResultFilter  
    {             
        /// <summary>
        /// 异步版本
        /// </summary>
        /// <param name="context"></param>
        /// <param name="next"></param>
        /// <returns></returns>
        public async Task OnResultExecutionAsync(ResultExecutingContext context, ResultExecutionDelegate next)
        {

            if (context.Result is ObjectResult objectResult)
            {
                var statusCode = objectResult.StatusCode ?? context.HttpContext.Response.StatusCode;

                //是200 并且没有包装  那么包装结果
                if (statusCode == 200 && !(objectResult.Value is IResponseOutput))
                {
                    //if (objectResult.Value == null)
                    //{
                    //    var apiResponse = ResponseOutput.DBNotExist();

                    //    objectResult.Value = apiResponse;
                    //    objectResult.DeclaredType = apiResponse.GetType();
                    //}
                    //else
                    //{

                    var type = objectResult.Value?.GetType();


                    if (  type!=null&& type.IsGenericType&&(type.GetGenericTypeDefinition()==typeof(ValueTuple<,>)|| type.GetGenericTypeDefinition()==typeof(Tuple<,>)))
                    {

                        //报错
                        //var tuple = (object, object))objectResult.Value;

                        //var (val1, val2) = ((dynamic, dynamic))objectResult.Value;
                        //var apiResponse = ResponseOutput.Ok(val1, val2);

                        //OK
                        var tuple = (dynamic)objectResult.Value;
                        var apiResponse = ResponseOutput.Ok(tuple.Item1, tuple.Item2);


                        objectResult.Value = apiResponse;
                        objectResult.DeclaredType = apiResponse.GetType();
                    }
                    else
                    {
                        var apiResponse = ResponseOutput.Ok(objectResult.Value);

                        objectResult.Value = apiResponse;
                        objectResult.DeclaredType = apiResponse.GetType();
                    }

                      
                    //}
                   
                }
                //如果不是200  是IResponseOutput  不处理
                else if (statusCode != 200 && (objectResult.Value is IResponseOutput))
                {
                }

                else if(statusCode != 200&&!(objectResult.Value is IResponseOutput))
                {
                    var apiResponse = ResponseOutput.NotOk("程序错误，请联系开发人员。");

                    objectResult.Value = apiResponse;
                    objectResult.DeclaredType = apiResponse.GetType();
                }

            }

            await next.Invoke();

        }

        public static bool IsTupleType(Type type, bool checkBaseTypes = false)
        {
            if (type == null)
                throw new ArgumentNullException(nameof(type));

            if (type == typeof(Tuple))
                return true;

            while (type != null)
            {
                if (type.IsGenericType)
                {
                    var genType = type.GetGenericTypeDefinition();
                    if (genType == typeof(Tuple<>)
                        || genType == typeof(Tuple<,>)
                        || genType == typeof(Tuple<,>))
                        return true;
                }

                if (!checkBaseTypes)
                    break;

                type = type.BaseType;
            }

            return false;
        }
    }
}