using EasyCaching.Core;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace IRaCIS.Core.Application.Filter
{
    /// <summary>
    /// 主要为了 处理项目结束 锁库，不允许操作
    /// </summary>
    public class TrialResourceFilter : Attribute, IAsyncResourceFilter /* , IResourceFilter*/
    {
        private readonly IEasyCachingProvider _provider;
        private readonly IUserInfo _userInfo;


        public TrialResourceFilter(IEasyCachingProvider provider, IUserInfo userInfo)
        {
            _provider = provider;
            _userInfo = userInfo;
        }



        //优先选择异步的方法
        public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next)
        {
            #region 处理新的用户类型，不能操作项目相关接口

            if( _userInfo.UserTypeEnumInt == (int)UserTypeEnum.CRA)
            {
                context.Result = new JsonResult(ResponseOutput.NotOk("Sorry,Your UserType does not allow this operation"));

                return ;
            }

            #endregion

            //bool isEditTrialStatus = context.ActionDescriptor.DisplayName==null? false:context.ActionDescriptor.DisplayName.Contains("UpdateTrialStatus");

            //bool isTrialAdd = context.ActionDescriptor.DisplayName == null ? false: context.ActionDescriptor.DisplayName.Contains("AddOrUpdateTrial");

            //TrialId 传递的途径多种，可能在path 可能在body  可能在数组中，也可能在对象中，可能就在url
            var trialIdStr = string.Empty;

            //先尝试从path中取TrialId 
            if (context.RouteData.Values.Keys.Any(t => t.Contains("trialId")))
            {
                var index = context.RouteData.Values.Keys.ToList().IndexOf("trialId");
                trialIdStr = context.RouteData.Values.Values.ToList()[index] as string;
            }
            else
            {
                #region body 中取数据

                //设置可以多次读
                context.HttpContext.Request.EnableBuffering();
                var reader = new StreamReader(context.HttpContext.Request.Body);
                var contentFromBody = await reader.ReadToEndAsync();
                //读取后，流的位置还原
                context.HttpContext.Request.Body.Seek(0, SeekOrigin.Begin);
                //context.HttpContext.Request.Body.Position = 0;

                //找到参数位置在字符串中的索引
                var trialIdIndex = contentFromBody.IndexOf("\"TrialId\"", StringComparison.OrdinalIgnoreCase);

                if (trialIdIndex > -1)
                {
                    trialIdStr = contentFromBody.Substring(trialIdIndex + "TrialId".Length + 4, 36);
                }
                //else if(isTrialAdd)
                //{
                //    //项目的添加和编辑时例外 trailId 在Id字段中  同时，添加和更新时有区别的
                //    trialIdIndex = contentFromBody.IndexOf("\"Id\"");

                //    //添加时为-1  不进行操作
                //    if (trialIdIndex != -1)
                //    {

                //        trialIdStr = contentFromBody.Substring(trialIdIndex + "Id".Length + 4, 36);

                //        trialIdStr = Guid.TryParse(trialIdStr, out var trialId) ? trialId.ToString() : String.Empty ;
                //    }

                //}

                #endregion
            }


            //通过path 或者body 找到trialId 了  
            if (trialIdStr != string.Empty)
            {

                //如果没缓存数据，是不允许的  意外情况，IIS回收了，导致定时任务没执行或者缓存丢失
                if (_provider.GetCount() == 0)
                {

                    var _trialRepository = context.HttpContext.RequestServices.GetService(typeof(IRepository<Trial>)) as IRepository<Trial>;

                    var list = _trialRepository.IfNullThrowException().Select(t => new { TrialId = t.Id, TrialStatusStr = t.TrialStatusStr })
                      .ToList();

                    list.ForEach(t => _provider.Set(t.TrialId.ToString(), t.TrialStatusStr, TimeSpan.FromDays(7)));
                }

                var cacheResultDic = _provider.GetAll<string>(new[] { trialIdStr });

                var trialStatusStr = cacheResultDic[trialIdStr];


                //项目完成和停止，都不能操作
                if (trialStatusStr.Value == StaticData.TrialCompleted || trialStatusStr.Value == StaticData.TrialStopped)
                {
                    context.Result = new JsonResult(ResponseOutput.NotOk("Only trial in  ongoing state can the operation be performed"));
                }

                //仅仅管理员 在项目暂停 并且是编辑项目接口时  才放开操作  遗漏了正常情况 TrialOngoing
                if (/*(trialStatusStr.Value == StaticData.TrialPaused && _userInfo.UserTypeEnumInt == (int)UserTypeEnum.SuperAdmin && isEditTrialStatus)||*/ trialStatusStr.Value == StaticData.TrialOngoing)
                {

                    await next.Invoke();

                }
                //项目暂停的基础上，是其他人，或者不是编辑项目状态，那么要禁止操作
                else
                {
                    context.Result = new JsonResult(ResponseOutput.NotOk("Only trial in  ongoing state can the operation be performed"));

                }

            } 
            ////没有找到trialId  判断是否是项目添加
            //else if (isTrialAdd)
            //{
            //    await next.Invoke();
            //}
            else
            {
                //如果项目相关接口没有传递trialId 会来到这里,提醒，以便修改

                context.Result = new JsonResult(ResponseOutput.NotOk("该接口参数中，没有传递trialId，请核查"));
            }


        }
    }
}