using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.EntityFrameworkCore;
using System;
using System.Data;
using System.Reflection;
using System.Threading.Tasks;

namespace IRaCIS.Core.Infra.EFCore
{
    public sealed class UnitOfWorkAttribute : Attribute
    {
        public IsolationLevel _isolationLevel { get; set; }

        public bool IsCommitted { get; set; }

        public UnitOfWorkAttribute(IsolationLevel isolationLevel = IsolationLevel.ReadCommitted)
        {
            _isolationLevel = isolationLevel;
        }

    }

    public sealed class ManualCommitAttribute : Attribute
    {

    }


    public sealed class UnitOfWorkFilter : IAsyncActionFilter, IOrderedFilter
    {

        /// <summary>
        /// 过滤器排序
        /// </summary>
        internal const int FilterOrder = 9999;

        public int Order => FilterOrder;

        /// <summary>
        /// 数据库上下文
        /// </summary>
        public IRaCISDBContext _dbContext { get; }

        public UnitOfWorkFilter(IRaCISDBContext dbContext)
        {
            _dbContext = dbContext;
        }

        /// <summary>
        /// 拦截请求
        /// </summary>
        /// <param name="context">动作方法上下文</param>
        /// <param name="next">中间件委托</param>
        /// <returns></returns>
        public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            // 获取动作方法描述器
            var actionDescriptor = context.ActionDescriptor as ControllerActionDescriptor;
            var method = actionDescriptor.MethodInfo;

            // 判断是否贴有工作单元特性
            if (!method.IsDefined(typeof(UnitOfWorkAttribute), true))
            {
                var resultContext = await next();
            }
            //手动提交事务
            else if (method.IsDefined(typeof(UnitOfWorkAttribute), true) && method.IsDefined(typeof(ManualCommitAttribute), true))
            {
                var resultContext = await next();
            }
            else
            {
                //判断是否已经开启了事务
                var currentTransaction = _dbContext.Database.CurrentTransaction;


                // 获取工作单元特性
                var unitOfWorkAttribute = method.GetCustomAttribute<UnitOfWorkAttribute>();

                var strategy = _dbContext.Database.CreateExecutionStrategy();

                await strategy.Execute(async () =>
                {
                    // 开启事务
                    var _transaction = currentTransaction ?? _dbContext.Database.BeginTransaction(unitOfWorkAttribute._isolationLevel);

                    // 调用 其他过滤器和Action业务 方法
                    var resultContext = await next();

                    //await _dbContext.SaveChangesAsync();

                    var currentConnectionState = _dbContext.Database.GetDbConnection().State;


                    //之前的事务已经提交  连接已经关闭
                    if (currentConnectionState != ConnectionState.Closed)
                    {
                        if (resultContext.Exception == null)
                        {
                            //提交事务
                            await _transaction?.CommitAsync();
                        }
                        else
                        {
                            //回退事务
                            await _transaction?.RollbackAsync();
                        }
                    }
                    
                   
                });

        }
    }
}

}
