//--------------------------------------------------------------------
//     此代码由T4模板自动生成  byzhouhang 20210918
//	   生成时间 2021-11-11 11:04:54 
//     对此文件的更改可能会导致不正确的行为，并且如果重新生成代码，这些更改将会丢失。
//--------------------------------------------------------------------

using IRaCIS.Core.Application.Auth;
using IRaCIS.Core.Application.Filter;
using IRaCIS.Core.Infra.EFCore;
using IRaCIS.Core.Infrastructure;
using MassTransit;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;

namespace IRaCIS.Core.Application.Contracts
{
    /// <summary>
    /// 项目QC 问题 管理
    /// </summary>	
    [ApiExplorerSettings(GroupName = "Image")]
    public class TrialQCQuestionConfigureService : BaseService, ITrialQCQuestionConfigureService
    {
        private readonly IRepository<TrialQCQuestion> _trialQcQuestionRepository;
        private readonly IRepository<QCQuestion> _qCQuestionRepository;

        public TrialQCQuestionConfigureService(
            IRepository<TrialQCQuestion> trialQcQuestionRepository,
            IRepository<QCQuestion> qCQuestionRepository
            )
        {
            _trialQcQuestionRepository = trialQcQuestionRepository;
            this._qCQuestionRepository = qCQuestionRepository;
        }


        [HttpPost]
        public async Task<(List<TrialQCQuestionConfigureView>, object)> GetTrialQCQuestionConfigureList(TrialQCQuestionQuery queryTrialQCQuestionConfigure)
        {


            var trialQCQuestionQueryable = _trialQcQuestionRepository.Where(t => t.TrialId == queryTrialQCQuestionConfigure.TrialId)
               .WhereIf(!string.IsNullOrWhiteSpace(queryTrialQCQuestionConfigure.QuestionName), t => t.QuestionName.Contains(queryTrialQCQuestionConfigure.QuestionName))
               .WhereIf(!string.IsNullOrWhiteSpace(queryTrialQCQuestionConfigure.Type), t => t.Type.Contains(queryTrialQCQuestionConfigure.Type))
                .WhereIf(queryTrialQCQuestionConfigure.IsEnable != null, t => t.IsEnable == queryTrialQCQuestionConfigure.IsEnable)
                .WhereIf(queryTrialQCQuestionConfigure.IsRequired != null, t => t.IsRequired == queryTrialQCQuestionConfigure.IsRequired)


            .ProjectTo<TrialQCQuestionConfigureView>(_mapper.ConfigurationProvider);

            var list = await trialQCQuestionQueryable.OrderBy(t => t.ShowOrder).ToListAsync();

            var isHaveQCQuestion = _repository.Where<TrialQCQuestion>(t => t.TrialId == queryTrialQCQuestionConfigure.TrialId).Any();


            var signInfo = await _repository.Where<Trial>(t => t.Id == queryTrialQCQuestionConfigure.TrialId)
                .Select(trial => new
                {
                    trial.QCProcessEnum,
                    trial.QCQuestionConfirmedTime,
                    trial.QCQuestionConfirmedUserId,
                    RealName = trial.QCQuestionConfirmedUser.FullName,
                    trial.QCQuestionConfirmedUser.UserName,
                    IsHaveQCQuestion = isHaveQCQuestion
                }).FirstOrDefaultAsync();

            return (list, signInfo!);
        }


        /// <summary>
        /// 父问题  下拉框选项  需要排除自己  、把自己设置为父亲 (互为父亲) 、是自己孙辈的（明明是自己子孙，却设置为自己父亲）
        /// </summary>
        /// <param name="trialQCQuestionFilterSelect"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<List<TrialQCQuestionSelect>> GetTrialQCQuestionSelectList(TrialQCQuestionFilterSelect trialQCQuestionFilterSelect)
        {

            //设置父亲的时候，不允许设置为自己的孙子   这种会形成环

            var initList = await _trialQcQuestionRepository.Where(t => t.TrialId == trialQCQuestionFilterSelect.TrialId)
                 .WhereIf(trialQCQuestionFilterSelect.TypeArray.Count() > 0, t => trialQCQuestionFilterSelect.TypeArray.Contains(t.Type))
                .WhereIf(trialQCQuestionFilterSelect.Id != null, t => t.Id != trialQCQuestionFilterSelect.Id && t.ParentId != trialQCQuestionFilterSelect.Id)
                .OrderBy(t => t.ShowOrder).ProjectTo<TrialQCQuestionSelect>(_mapper.ConfigurationProvider).ToListAsync();

            //父亲的序号肯定要比自己小
            if (trialQCQuestionFilterSelect.Id != null)
            {
                var selectItem = initList.FirstOrDefault(t => t.Id == trialQCQuestionFilterSelect.Id);

                initList = initList.WhereIf(selectItem != null, t => t.Id != selectItem!.Id && t.ShowOrder < selectItem.ShowOrder).ToList();
            }


            var exceptList = GetChildId(trialQCQuestionFilterSelect.Id ?? Guid.Empty, initList);


            return initList.Where(t => !exceptList.Contains(t.Id)).ToList();
        }


        private List<Guid> GetChildId(Guid parentId, List<TrialQCQuestionSelect> list)
        {

            var ids = new List<Guid>();

            var childIds = list.Where(t => t.ParentId == parentId).Select(t => t.Id).ToList();

            foreach (var childId in childIds)
            {
                ids.AddRange(childId);

                var childs = GetChildId(childId, list);

                ids.AddRange(childs);

            }

            return ids;
        }


        public async Task VerifyIsQCConfirmedAsync(Guid trialId)
        {
            if (!await _repository.AnyAsync<Trial>(t => t.Id == trialId && t.QCQuestionConfirmedUserId == null))
            {
                throw new BusinessValidationFailedException("影像质控审核问题模板已经确认，不允许操作。");
            }
        }

        /// <summary>
        /// 批量添加 QC 问题
        /// </summary>
        /// <param name="batchList"></param>
        /// <param name="trialId"></param>
        /// <returns></returns>
        [HttpPost("{trialId:guid}")]
       // [Authorize(Policy = IRaCISPolicy.IQC)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> BatchAddTrialQCQuestionConfigure(List<TrialQCQuestionConfigureBatchAdd> batchList, Guid trialId)
        {

            await VerifyIsQCConfirmedAsync(trialId);

            var maxShowOrder = await _trialQcQuestionRepository.Where(x => x.TrialId == trialId).OrderByDescending(x => x.ShowOrder).Select(x => x.ShowOrder).FirstOrDefaultAsync();
            maxShowOrder++;

            #region OLd
            //batchList.ForEach(x =>
            //{
            //    maxShowOrder++;
            //    x.ShowOrder = maxShowOrder;
            //    x.SystemQuestionId = x.Id.Value;
            //    x.Id = NewId.NextGuid();

            //});

            //foreach (var item in batchList.Where(x => x.ParentId != null))
            //{
            //    var parent = batchList.Where(x => x.SystemQuestionId == item.ParentId).FirstOrDefault();
            //    if (parent == null)
            //    {
            //        item.ParentId = null;
            //        item.ParentTriggerValue = String.Empty;
            //    }
            //    else
            //    {
            //        item.ParentId = parent.Id;
            //    }
            //}

            #endregion

            #region New
            //查询所有的子问题
            var list = await _qCQuestionRepository.Where(t => t.ParentId != null).ToListAsync();

            var mappedList = _mapper.Map<List<TrialQCQuestion>>(list);

            var childList = new List<TrialQCQuestion>();

            //遍历父层级的问题
            var batchConfigList = _mapper.Map<List<TrialQCQuestion>>(batchList.Where(t => t.ParentId == null));

            foreach (var item in batchConfigList.Where(t => t.ParentId == null).OrderBy(t => t.ShowOrder))
            {
                var oldParentId = item.Id;
                item.Id = NewId.NextGuid();
                item.TrialId = trialId;
                item.ShowOrder = maxShowOrder++;

                var findChildList = GetChildList(oldParentId, item.Id, mappedList);


                foreach (var findChild in findChildList)
                {

                    findChild.TrialId = trialId;

                    findChild.ShowOrder = maxShowOrder++;
                }

                childList.AddRange(findChildList);
            }



            #endregion


            await _trialQcQuestionRepository.AddRangeAsync(batchConfigList);

            await _trialQcQuestionRepository.AddRangeAsync(childList);

            var success = await _repository.SaveChangesAsync();

            return ResponseOutput.Result(success);
        }


        private List<TrialQCQuestion> GetChildList(Guid parentId, Guid newParentId, List<TrialQCQuestion> list)
        {
            var childList = new List<TrialQCQuestion>();

            var findlist = list.Where(t => t.ParentId == parentId).ToList();

            foreach (var child in findlist)
            {
                var oldParentId = child.Id;

                child.Id = NewId.NextGuid();
                child.ParentId = newParentId;

                childList.Add(child);

                var findList = GetChildList(oldParentId, child.Id, list);

                childList.AddRange(findList);

            }

            return childList;
        }

       // [Authorize(Policy = IRaCISPolicy.IQC)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> AddOrUpdateTrialQCQuestionConfigure(TrialQCQuestionAddOrEdit addOrEditTrialQCQuestionConfigure)
        {


            if (await _trialQcQuestionRepository.AnyAsync(x => x.TrialId == addOrEditTrialQCQuestionConfigure.TrialId && x.Id != addOrEditTrialQCQuestionConfigure.Id && x.ShowOrder == addOrEditTrialQCQuestionConfigure.ShowOrder))
            {
                throw new BusinessValidationFailedException("序号重复,操作失败");

            }

            await VerifyIsQCConfirmedAsync(addOrEditTrialQCQuestionConfigure.TrialId);

            var entity = await _trialQcQuestionRepository.InsertOrUpdateAsync(addOrEditTrialQCQuestionConfigure, true);

            return ResponseOutput.Ok(entity.Id.ToString());
        }





        [HttpDelete("{trialId:guid}/{trialQCQuestionConfigureId:guid}")]
       // [Authorize(Policy = IRaCISPolicy.IQC)]
        [TypeFilter(typeof(TrialResourceFilter), Arguments = new object[] { "AfterStopCannNotOpt" })]
        public async Task<IResponseOutput> DeleteTrialQCQuestionConfigure(Guid trialQCQuestionConfigureId, Guid trialId)
        {
            await VerifyIsQCConfirmedAsync(trialId);

            if (await _trialQcQuestionRepository.AnyAsync(t => t.ParentId == trialQCQuestionConfigureId))
            {
                return ResponseOutput.NotOk("请在删除父问题前，请先删除引用该父问题的子问题。");
            }

            if (await _repository.AnyAsync<TrialQCQuestionAnswer>(t => t.TrialQCQuestionConfigureId == trialQCQuestionConfigureId))
            {
                return ResponseOutput.NotOk("该审核问题已被影像质控过程引用，不允许删除。");
            }

            await _trialQcQuestionRepository.DeleteFromQueryAsync(t => t.Id == trialQCQuestionConfigureId, true);
            return ResponseOutput.Result(true);
        }




    }
}
