using IRaCIS.Application.Contracts;
using IRaCIS.Application.Interfaces;
using IRaCIS.Core.Domain.Share;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Text;
namespace IRaCIS.Core.Application.Service
{
    /// 
    /// 数据字典-基础数据维护
    /// 
    [ApiExplorerSettings(GroupName = "Common")]
    public class DictionaryService(IRepository _dicRepository,
        IRepository _doctorDictionaryRepository,
        IRepository _trialDictionaryRepository,
        IRepository _doctorRepository,
        IRepository _trialRepository,
        IRepository _systemCriterionDictionaryCodeRepository,
        IRepository _trialCriterionDictionaryCodeRepository,
        IRepository _readingTrialCriterionDictionaryRepository,
        IRepository _readingSystemCriterionDictionaryRepository,
        IRepository _readingCriterionDictionaryRepository,
        IRepository _readingQuestionCriterionSystem,
        IRepository _readingQuestionCriterionTrial, IMapper _mapper, IUserInfo _userInfo, IStringLocalizer _localizer) : BaseService, IDictionaryService
    {
        /// 
        /// 添加bool
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task AddBoolDic(AddOrEditBasicDic addOrEditBasic)
        {
            var entity = await _dicRepository.InsertFromDTOAsync(addOrEditBasic);
            var child1 = entity.Clone();
            child1.Id = Guid.Empty;
            child1.Code = "true";
            child1.ParentId = entity.Id;
            entity.ChildList.Add(child1);
            var child2 = entity.Clone();
            child2.Id = Guid.Empty;
            child2.Code = "false";
            child2.ParentId = entity.Id;
            entity.ChildList.Add(child2);
            await _dicRepository.SaveChangesAsync();
            return ResponseOutput.Ok(entity.Id.ToString());
        }
        /// 
        /// 获取所有字典的Key
        /// 
        /// 
        [HttpPost]
        public async Task> GetAllDictionaryKey()
        {
            var result = await _dicRepository.Where(t => t.ParentId == null).OrderBy(x => x.Code).Select(x => x.Code).ToListAsync();
            return result;
        }
        /// 
        /// 添加字典 的同时 一起添加子项  --New  
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task AddBasicDicAndChild(AddBasicDicAndChild addBasicDicAndChild)
        {
            var verifyExp1 = new EntityVerifyExp()
            {
                VerifyExp = t => t.Code == addBasicDicAndChild.Code && t.ParentId == null,
                VerifyMsg = $"已有{addBasicDicAndChild.Code}名称的字典",
                IsVerify = true
            };
            if ((addBasicDicAndChild.DataTypeEnum == DicDataTypeEnum.Enum || addBasicDicAndChild.DataTypeEnum == DicDataTypeEnum.Bool))
            {
                if (addBasicDicAndChild.ChildList.GroupBy(t => t.Code).Where(g => g.Count() > 1).Any())
                {
                    return ResponseOutput.NotOk(_localizer["Dictionary_RepeateCode"]);
                }
            }
            var entity = await _dicRepository.InsertFromDTOAsync(addBasicDicAndChild, false, verifyExp1);
            var childList = _mapper.Map>(addBasicDicAndChild.ChildList);
            foreach (var item in childList)
            {
                item.DataTypeEnum = addBasicDicAndChild.DataTypeEnum;
                item.ParentId = entity.Id;
            }
            await _dicRepository.AddRangeAsync(childList);
            await _dicRepository.SaveChangesAsync();
            return ResponseOutput.Ok(entity.Id.ToString());
        }
        /// 
        /// New  查询条件  
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task> GetBasicDicList(BasicDicQuery inQuery)
        {
            var systemBasicDataQueryable = _dicRepository.Where(t => t.ParentId == null)
                .WhereIf(!string.IsNullOrEmpty(inQuery.Code), t => t.Code.Contains(inQuery.Code!))
                .WhereIf(!string.IsNullOrEmpty(inQuery.keyInfo), t => t.Description.Contains(inQuery.keyInfo!)
                || t.Code.Contains(inQuery.keyInfo!)
                || t.ChildList.Any(u => u.ValueCN.Contains(inQuery.keyInfo!))
                || t.ChildList.Any(u => u.Description.Contains(inQuery.keyInfo!))
                || t.ChildList.Any(u => u.Value.Contains(inQuery.keyInfo!)))
                .WhereIf(inQuery.ConfigTypeId != null, t => t.ConfigTypeId == inQuery.ConfigTypeId!)
                .WhereIf(inQuery.DataTypeEnum != null, t => t.DataTypeEnum == inQuery.DataTypeEnum)
                .WhereIf(inQuery.DataTypeEnum == null, t => t.DataTypeEnum != DicDataTypeEnum.Config)
                .ProjectTo(_mapper.ConfigurationProvider);
            return await systemBasicDataQueryable.ToPagedListAsync(inQuery, new[] { nameof(BasicDicView.ConfigType), nameof(BasicDicView.ShowOrder) });
        }
        /// 
        /// 添加和编辑
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task AddOrUpdateBasicDic(AddOrEditBasicDic addOrEditBasic)
        {
            var verifyExp1 = new EntityVerifyExp()
            {
                VerifyExp = t => t.Code == addOrEditBasic.Code && t.ParentId == addOrEditBasic.ParentId,
                //---------- $"已有{addOrEditBasic.Code}名称的字典"
                VerifyMsg = _localizer["Dictionary_DictionaryName", addOrEditBasic.Code],
                IsVerify = addOrEditBasic.ParentId == null
            };
            var verifyExp2 = new EntityVerifyExp()
            {
                VerifyExp = t => t.Code == addOrEditBasic.Code && t.ParentId == addOrEditBasic.ParentId && t.Code == addOrEditBasic.Code,
                VerifyMsg = _localizer["Dictionary_RepeateCode"],
                IsVerify = addOrEditBasic.ParentId != null && (addOrEditBasic.DataTypeEnum == DicDataTypeEnum.Enum || addOrEditBasic.DataTypeEnum == DicDataTypeEnum.Bool)
            };
            if (addOrEditBasic.Id != null && addOrEditBasic.ParentId == null)
            {
                await _dicRepository.UpdatePartialFromQueryAsync(t => t.ParentId == addOrEditBasic.Id, c => new Dictionary() { DataTypeEnum = addOrEditBasic.DataTypeEnum });
                //await _dicRepository.BatchUpdateNoTrackingAsync(t => t.ParentId == addOrEditBasic.Id, c => new Dictionary() { DataTypeEnum = addOrEditBasic.DataTypeEnum });
            }
            var entity = await _dicRepository.InsertOrUpdateAsync(addOrEditBasic, true, verifyExp1, verifyExp2);
            await _dicRepository.SaveChangesAsync();
            return ResponseOutput.Ok(entity.Id.ToString());
        }
        /// 
        /// 获取子项数组
        /// 
        /// 
        /// 
        [HttpGet("{parentId:guid}")]
        public async Task> GetChildList(Guid parentId)
        {
            return await _dicRepository.Where(t => t.ParentId == parentId)
                .OrderBy(t => t.ShowOrder).ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
        }
        ///  删除字典数据 
        [HttpDelete("{id:guid}")]
        public async Task DeleteDictionary(Guid id)
        {
            if (await _readingCriterionDictionaryRepository.AnyAsync(x => x.DictionaryId == id))
            {
                await _readingCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.DictionaryId == id);
                //---当前字典在标准中被引用,不允许删除!
                //return ResponseOutput.NotOk(_localizer["Dictionary_DictionaryDeletion"]);
            }
            if (await _readingTrialCriterionDictionaryRepository.AnyAsync(x => x.DictionaryId == id))
            {
                await _readingTrialCriterionDictionaryRepository.BatchDeleteNoTrackingAsync(t => t.DictionaryId == id);
                //---当前字典在标准中被引用,不允许删除!
                //return ResponseOutput.NotOk(_localizer["Dictionary_DictionaryDeletion"]);
            }
            if (await _dicRepository.AnyAsync(t => t.ParentId == id))
            {
                //---有子项数据,不允许直接删除!
                return ResponseOutput.NotOk(_localizer["Dictionary_SubitemDeletion"]);
            }
            if ((await _doctorDictionaryRepository.AnyAsync(t => t.DictionaryId == id)) ||
                (await _doctorRepository.AnyAsync(t => t.SpecialityId == id || t.PositionId == id || t.DepartmentId == id || t.RankId == id))
               )
            {
                //---当前条目已经在阅片人的简历中被引用。
                return ResponseOutput.NotOk(_localizer["Dictionary_ResumeReference"]);
            }
            if (await _trialDictionaryRepository.AnyAsync(t => t.DictionaryId == id) ||
                await _trialRepository.AnyAsync(t => t.ReviewModeId == id))
            {
                //---当前条目已经在项目信息中被引用。
                return ResponseOutput.NotOk(_localizer["Dictionary_ProjectReference"]);
            }
            var success = await _dicRepository.BatchDeleteNoTrackingAsync(t => t.Id == id);
            return ResponseOutput.Result(success);
        }
        /// 
        /// 传递父亲 code  字符串  数组  返回多个下拉框数据
        /// 
        /// 
        /// 
        [HttpPost]
        public async Task>> GetBasicDataSelect(string[] searchArray)
        {
            var searchList = await _dicRepository.Where(t => searchArray.Contains(t.Parent.Code) && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider, new { isEn_Us = _userInfo.IsEn_Us }).ToListAsync();
            return searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
        }
        /// 
        /// 根据父亲Code  获取单个下拉框数据
        /// 
        /// 
        /// 
        public async Task> GetBasicDataSelect(string searchKey)
        {
            var searchList = await _dicRepository.Where(t => t.Parent.Code == searchKey && t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
            return searchList;
        }
        /// 
        /// 根据父亲字典分组  获取子项
        /// 
        /// 
        /// 
        public async Task> GetBasicConfigSelect(string searchKey)
        {
            var searchList = await _dicRepository.Where(t => t.ConfigDictionary.Code == searchKey && t.ParentId == null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider).OrderBy(x => x.ShowOrder).ToListAsync();
            return searchList;
        }
        /// 
        /// 获取标准字典
        /// 
        /// 
        public async Task> GetCriterionDictionaryList(GetCriterionDictionaryListInDto inDto)
        {
            var criterionCodes = await _systemCriterionDictionaryCodeRepository.Where(x => x.SystemCriterionId == inDto.SystemCriterionId).ToListAsync();
            var parentCodes = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.SystemCriterionId).Select(x => x.ParentCode).ToListAsync();
            var codes = criterionCodes.Select(x => x.Code).ToList();
            var dictionaryList = await _dicRepository.Where(x => codes.Contains(x.Code) && x.ParentId == null)
                .OrderBy(x => x.ShowOrder).Select(x => new GetCriterionDictionaryListOutDto()
                {
                    Code = x.Code,
                    ShowOrder = x.ShowOrder,
                    Description = x.Description
                }).ToListAsync();
            dictionaryList.ForEach(x =>
            {
                x.Count = parentCodes.Count(y => y == x.Code);
                x.Id = criterionCodes.Where(y => y.Code == x.Code).Select(x => x.Id).FirstOrDefault();
            });
            return dictionaryList;
        }
        /// 
        /// 获取标准字典
        /// 
        /// 
        public async Task> GetTrialCriterionDictionaryList(GetTrialCriterionDictionaryListInDto inDto)
        {
            var criterionCodes = await _trialCriterionDictionaryCodeRepository.Where(x => x.TrialCriterionId == inDto.TrialCriterionId).ToListAsync();
            var parentCodes = await _readingTrialCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialCriterionId).Select(x => x.ParentCode).ToListAsync();
            var codes = criterionCodes.Select(x => x.Code).ToList();
            var dictionaryList = await _dicRepository.Where(x => codes.Contains(x.Code) && x.ParentId == null)
                .OrderBy(x => x.ShowOrder).Select(x => new GetCriterionDictionaryListOutDto()
                {
                    Code = x.Code,
                    ShowOrder = x.ShowOrder,
                    Description = x.Description
                }).ToListAsync();
            dictionaryList.ForEach(x =>
            {
                x.Count = parentCodes.Count(y => y == x.Code);
                x.Id = criterionCodes.Where(y => y.Code == x.Code).Select(x => x.Id).FirstOrDefault();
            });
            return dictionaryList;
        }
        /// 
        /// 获取标准指定字典
        /// 
        /// 
        /// 
        [AllowAnonymous]
        [HttpPost]
        public async Task>> GetCriterionDictionary(GetCriterionDictionaryInDto inDto)
        {
            var searchList = await _dicRepository.Where(t => t.ParentId != null && t.IsEnable)
                .WhereIf(!inDto.DictionaryCode.IsNullOrEmpty(), x => x.Parent.Code == inDto.DictionaryCode)
                 .WhereIf(inDto.DictionaryCodeList.Count() > 0, x => inDto.DictionaryCodeList.Contains(x.Parent.Code))
                .ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
            var result = searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
            if (inDto.ReadingCriterionId == null)
            {
                return result;
            }
            else
            {
                List selectCode = new List();
                List criterionDictionList = new List();
                var isSystemCriterion = await _readingQuestionCriterionSystem.AnyAsync(x => x.Id == inDto.ReadingCriterionId);
                if (isSystemCriterion)
                {
                    selectCode = await _systemCriterionDictionaryCodeRepository.Where(x => x.SystemCriterionId == inDto.ReadingCriterionId).Select(x => x.Code).ToListAsync();
                    criterionDictionList = await _readingCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.ReadingCriterionId).Select(x => new BasicDicSelect()
                    {
                        ChildGroup = x.Dictionary.ChildGroup,
                        Code = x.Dictionary.Code,
                        DataTypeEnum = x.Dictionary.DataTypeEnum,
                        ShowOrder = x.Dictionary.ShowOrder,
                        ParentCode = x.ParentCode,
                        CrterionDictionaryGroup = x.CrterionDictionaryGroup,
                        Id = x.DictionaryId,
                        ParentId = x.Dictionary.ParentId,
                        Value = x.Dictionary.Value,
                        ValueCN = x.Dictionary.ValueCN
                    }).ToListAsync();
                }
                else
                {
                    selectCode = await _trialCriterionDictionaryCodeRepository.Where(x => x.TrialCriterionId == inDto.ReadingCriterionId).Select(x => x.Code).ToListAsync();
                    criterionDictionList = await _readingTrialCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.ReadingCriterionId).Select(x => new BasicDicSelect()
                    {
                        ChildGroup = x.Dictionary.ChildGroup,
                        Code = x.Dictionary.Code,
                        DataTypeEnum = x.Dictionary.DataTypeEnum,
                        ShowOrder = x.Dictionary.ShowOrder,
                        ParentCode = x.ParentCode,
                        CrterionDictionaryGroup = x.CrterionDictionaryGroup,
                        Id = x.DictionaryId,
                        ParentId = x.Dictionary.ParentId,
                        Value = x.Dictionary.Value,
                        ValueCN = x.Dictionary.ValueCN
                    }).ToListAsync();
                }
                var criterionCode = await _dicRepository.Where(x => x.ConfigDictionary.Code == "Reading_eCRF_Criterion").Select(x => x.Code).ToListAsync();
                foreach (var item in criterionCode)
                {
                    if (result.ContainsKey(item))
                    {
                        result[item] = new List();
                    }
                }
                criterionDictionList = criterionDictionList.Where(x => selectCode.Contains(x.ParentCode)).ToList();
                var criterionDic = criterionDictionList.GroupBy(x => x.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
                foreach (var item in criterionDic)
                {
                    if (result.ContainsKey(item.Key))
                    {
                        result[item.Key] = item.Value;
                    }
                }
                return result;
            }
        }
        /// 
        /// 获取所有下拉框 枚举  bool  数据
        /// 
        /// 
        [AllowAnonymous]
        public async Task>> GetBasicDataAllSelect(GetBasicDataAllSelectInDto inDto)
        {
            var searchList = await _dicRepository.Where(t => t.ParentId != null && t.IsEnable).ProjectTo(_mapper.ConfigurationProvider).ToListAsync();
            var result = searchList.GroupBy(t => t.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
            if (inDto.TrialReadingCriterionId == null && inDto.SystemReadingCriterionId == null)
            {
                return result;
            }
            else if (inDto.TrialReadingCriterionId != null)
            {
                var trialCriterionType = await _readingQuestionCriterionTrial.Where(x => x.Id == inDto.TrialReadingCriterionId).Select(x => x.CriterionType).FirstOrDefaultAsync();
                if (trialCriterionType == CriterionType.SelfDefine)
                {
                    return result;
                }
                List selectCode = await _trialCriterionDictionaryCodeRepository.Where(x => x.TrialCriterionId == inDto.TrialReadingCriterionId).Select(x => x.Code).ToListAsync();
                var criterionCode = await _dicRepository.Where(x => x.ConfigDictionary.Code == "Reading_eCRF_Criterion").Select(x => x.Code).ToListAsync();
                foreach (var item in criterionCode)
                {
                    if (result.ContainsKey(item))
                    {
                        result[item] = new List();
                    }
                }
                var criterionDictionList = await _readingTrialCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.TrialReadingCriterionId).Select(x => new BasicDicSelect()
                {
                    ChildGroup = x.Dictionary.ChildGroup,
                    Code = x.Dictionary.Code,
                    Description = x.Dictionary.Description,
                    DataTypeEnum = x.Dictionary.DataTypeEnum,
                    ShowOrder = x.Dictionary.ShowOrder,
                    ParentCode = x.ParentCode,
                    Id = x.DictionaryId,
                    CrterionDictionaryGroup = x.CrterionDictionaryGroup,
                    ParentId = x.Dictionary.ParentId,
                    Value = x.Dictionary.Value,
                    ValueCN = x.Dictionary.ValueCN
                }).ToListAsync();
                criterionDictionList = criterionDictionList.Where(x => selectCode.Contains(x.ParentCode)).ToList();
                var criterionDic = criterionDictionList.GroupBy(x => x.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
                foreach (var item in criterionDic)
                {
                    result[item.Key] = item.Value;
                }
                return result;
            }
            else
            {
                List selectCode = await _systemCriterionDictionaryCodeRepository.Where(x => x.SystemCriterionId == inDto.SystemReadingCriterionId).Select(x => x.Code).ToListAsync();
                var criterionCode = await _dicRepository.Where(x => x.ConfigDictionary.Code == "Reading_eCRF_Criterion").Select(x => x.Code).ToListAsync();
                foreach (var item in criterionCode)
                {
                    if (result.ContainsKey(item))
                    {
                        result[item] = new List();
                    }
                }
                var criterionDictionList = await _readingSystemCriterionDictionaryRepository.Where(x => x.CriterionId == inDto.SystemReadingCriterionId).Select(x => new BasicDicSelect()
                {
                    ChildGroup = x.Dictionary.ChildGroup,
                    Code = x.Dictionary.Code,
                    Description = x.Dictionary.Description,
                    DataTypeEnum = x.Dictionary.DataTypeEnum,
                    ShowOrder = x.Dictionary.ShowOrder,
                    ParentCode = x.ParentCode,
                    Id = x.DictionaryId,
                    CrterionDictionaryGroup = x.CrterionDictionaryGroup,
                    ParentId = x.Dictionary.ParentId,
                    Value = x.Dictionary.Value,
                    ValueCN = x.Dictionary.ValueCN
                }).ToListAsync();
                criterionDictionList = criterionDictionList.Where(x => selectCode.Contains(x.ParentCode)).ToList();
                var criterionDic = criterionDictionList.GroupBy(x => x.ParentCode).ToDictionary(g => g.Key, g => g.OrderBy(t => t.ShowOrder).ToList());
                foreach (var item in criterionDic)
                {
                    result[item.Key] = item.Value;
                }
                return result;
            }
        }
        #region 稽查相关
        /// 
        /// 获取是和否
        /// 
        /// 
        /// 
        public async Task GetBoolValueState(bool value)
        {
            return await _dicRepository.Where(t => t.Parent.Code == "YesOrNo" && t.Code == value.ToString()).Select(x => x.ValueCN).FirstOrDefaultAsync() ?? string.Empty;
        }
        /// 
        /// 获取审核状态
        /// 
        /// 
        /// 
        /// 
        /// 
        public async Task GetAuditState(Guid trial, T childCode)
        {
            var QCProcessEnum = _trialRepository.Where(x => x.Id == trial).Select(x => x.QCProcessEnum).FirstOrDefault();
            switch (QCProcessEnum)
            {
                case TrialQCProcess.SingleAudit:
                    return await _dicRepository.Where(t => t.Parent.Code == "AuditStatePE" && t.Code == Convert.ToInt32(childCode).ToString()).Select(x => x.ValueCN).FirstOrDefaultAsync() ?? string.Empty;
                case TrialQCProcess.DoubleAudit:
                    return await _dicRepository.Where(t => t.Parent.Code == "AuditStateRC" && t.Code == Convert.ToInt32(childCode).ToString()).Select(x => x.ValueCN).FirstOrDefaultAsync() ?? string.Empty;
                default:
                    return string.Empty;
            }
        }
        public async Task GetBasicDataTranslateItem(string parentCode, T childCode)
        {
            return await _dicRepository.Where(t => t.Parent.Code == parentCode && t.Code == Convert.ToInt32(childCode).ToString()).Select(x => x.ValueCN).FirstOrDefaultAsync() ?? string.Empty;
        }
        #endregion
    }
}