using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Domain.Share;
using IRaCIS.Core.Infra.EFCore.Common.Dto;
using IRaCIS.Core.Infrastructure;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.ChangeTracking.Internal;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;

namespace IRaCIS.Core.Infra.EFCore.Common
{
    /// <summary>
    /// 添加稽查稽查数据
    /// </summary>
    public class AuditingData : IAuditingData
    {

        /// <summary>
        /// 数据库对象o
        /// </summary>
        public IRaCISDBContext _dbContext { get; set; }

        /// <summary>
        /// 用户信息
        /// </summary>
        public IUserInfo _userInfo { get; set; }

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="dbContext"></param>
        /// <param name="userInfo"></param>
        public AuditingData(IRaCISDBContext dbContext, IUserInfo userInfo)
        {
            _dbContext = dbContext;
            _userInfo = userInfo;
        }

        /// <summary>
        /// 传入实体对象
        /// </summary>
        public async Task IncomingEntitys(List<EntityEntry> entitys)
        {
            // 修改
            await InsertAddEntitys(
                entitys.Where(x => x.State == EntityState.Modified &&
                (!typeof(ISoftDelete).IsAssignableFrom(x.Entity.GetType()) || !(bool)x.Entity.GetType().GetProperty("IsDeleted").GetValue(x.Entity) || NodeleteTableTypes.Contains(x.Entity.GetType()))
            ).ToList(), "Update");

            // 新增
            await InsertAddEntitys(entitys.Where(x => x.State == EntityState.Added).ToList(), "Add");

            // 删除
            await InsertAddEntitys(entitys.Where(x => x.State == EntityState.Deleted
            || (typeof(ISoftDelete).IsAssignableFrom(x.Entity.GetType()) && (bool)x.Entity.GetType().GetProperty("IsDeleted").GetValue(x.Entity) && x.State == EntityState.Modified && !NodeleteTableTypes.Contains(x.Entity.GetType()))
            ).ToList(), "Deleted");



            //var value = data.GetType().GetProperty(item).GetValue(data);
            //entitys.Where(x=>x.Entity.is)
        }


        /// <summary>
        /// 特殊删除
        /// </summary>
        private List<Type> NodeleteTableTypes
        {
            get
            {
                return new List<Type>()
                {
                   typeof(TrialUser),
                   typeof(TrialSiteSurvey),
                   typeof(TrialSiteUser),
                   typeof(VisitStage),
                   typeof(TrialSite)
                };
            }
        }

        /// <summary>
        /// 插入Add的实体
        /// </summary>
        /// <param name="entitys"></param>
        public async Task InsertAddEntitys(List<EntityEntry> entitys, string type)
        {
            #region 所有
            //foreach (var item in entitys)
            //{
            //    await InsertInspection<TrialUser>(item.Entity, type);
            //}
            #endregion

            #region 区分

            //系统文件
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SystemDocument)))
            {
                var entity = item.Entity as SystemDocument;
                var userTypes = entity.NeedConfirmedUserTypeList;
                if (userTypes == null)
                {
                    userTypes = await _dbContext.SystemDocNeedConfirmedUserType.Where(x => x.SystemDocumentId == entity.Id).ToListAsync();
                }

                var userTypeIds = userTypes.Select(x => x.NeedConfirmUserTypeId).ToList();
                var usertypeNames = await _dbContext.UserType.Where(x => userTypeIds.Contains(x.Id)).Select(x => x.UserTypeShortName).ToListAsync();
                var usertypeName = string.Join(",", usertypeNames);
                await InsertInspection<SystemDocument>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id
                }, new
                {
                    NeedConfirmedUserType = usertypeName,
                });
            }

            // 签名模板
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SystemBasicData)))
            {
                await InsertInspection<SystemBasicData>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 项目
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(Trial)))
            {
              
                var entity = item.Entity as Trial;
                List<string> trials = new List<string>();
                var trialids = new List<Guid>();
                if (entity.TrialDicList == null || entity.TrialDicList.Count == 0)
                {
                    trialids = await this._dbContext.TrialDictionary.Where(x => x.TrialId == entity.Id && x.KeyName == "Criterion").Select(x => x.DictionaryId).ToListAsync();

                }
                else
                {
                    trialids = entity.TrialDicList.Select(x => x.DictionaryId).ToList();

                }

                trials = await this._dbContext.Dictionary.Where(x => trialids.Contains(x.Id)).Select(x => x.ValueCN).ToListAsync();

                await InsertInspection<Trial>(item.Entity, type, x => new DataInspection()

                {
                    TrialId = x.Id,
                    TrialName = x.ExperimentName,
                    ResearchProgramNo = x.ResearchProgramNo,
                    GeneralId = x.Id,
                }, new
                {
                    TrialDicList = string.Join(",", trials)
                });
            }

            // 访视计划
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(VisitStage)))
            {
                var entity = item.Entity as VisitStage;


                var VisitPlanStatus = await this._dbContext.Trial.Where(x => x.Id == entity.TrialId).Select(x => x.VisitPlanConfirmed).FirstOrDefaultAsync();
                if (type == "Add")
                {
                    VisitPlanStatus = false;
                }
                await InsertInspection<VisitStage>(item.Entity, type, x => new DataInspection()
                {
                    VisitStageId = x.Id,
                    GeneralId = x.Id,
                }, new
                {
                    VisitPlanStatus = VisitPlanStatus,
                });
            }

            // 项目文档
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialDocument)))
            {

                var entity = item.Entity as TrialDocument;
                var userTypes = entity.NeedConfirmedUserTypeList;
                if (userTypes == null)
                {
                    userTypes = await _dbContext.TrialDocNeedConfirmedUserType.Where(x => x.TrialDocumentId == entity.Id).ToListAsync();
                }

                var userTypeIds = userTypes.Select(x => x.NeedConfirmUserTypeId).ToList();
                var usertypeNames = await _dbContext.UserType.Where(x => userTypeIds.Contains(x.Id)).Select(x => x.UserTypeShortName).ToListAsync();
                var usertypeName = string.Join(",", usertypeNames);
                await InsertInspection<TrialDocument>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id
                }, new
                {
                    NeedConfirmedUserType = usertypeName,
                });


            }

            // 系统文件签署
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SystemDocConfirmedUser)))
            {
                var entity = item.Entity as SystemDocConfirmedUser;
                var systemDocument = await _dbContext.SystemDocument.Where(x => x.Id == entity.SystemDocumentId).FirstOrDefaultAsync();
                await InsertInspection<SystemDocConfirmedUser>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {

                    FileTypeId = systemDocument.FileTypeId,
                    Name = systemDocument.Name,
                    CreateTime = systemDocument.CreateTime,
                    IsSigned = "是",// 是否签署  添加了就是签署了
                });
            }

            // 项目文件签署
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialDocUserTypeConfirmedUser)))
            {
                var entity = item.Entity as TrialDocUserTypeConfirmedUser;
                var trialDocument = await _dbContext.TrialDocument.Where(x => x.Id == entity.TrialDocumentId).FirstOrDefaultAsync();

                var trialid = trialDocument.TrialId;
                await InsertInspection<TrialDocUserTypeConfirmedUser>(item.Entity, type, x => new DataInspection()
                {
                    TrialId = trialid,
                    GeneralId = x.Id,
                }, new
                {
                    FileTypeId = trialDocument.FileTypeId,
                    Name = trialDocument.Name,
                    CreateTime = trialDocument.CreateTime,
                    IsSigned = "是",// 是否签署  添加了就是签署了
                });
            }

            // 医生
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(Enroll)))
            {
                await InsertInspection<Enroll>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 医生详情
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(EnrollDetail)))
            {
                await InsertInspection<EnrollDetail>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 项目中心
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSite)))
            {
                var entity = item.Entity as TrialSite;
                if (entity.Site == null)
                {
                    entity.Site = await _dbContext.Site.Where(x => x.Id == entity.SiteId).FirstOrDefaultAsync();
                }
                await InsertInspection<TrialSite>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,

                }, new
                {
                    TrialSiteCode = entity.TrialSiteCode,
                    SiteName = entity.Site.SiteName,
                    SiteAliasName = entity.TrialSiteAliasName,
                    City = entity.Site.City,
                    Country = entity.Site.Country,
                    Status = entity.IsDeleted ? "禁用" : "启用",
                });
            }

            // 项目人员
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialUser)))
            {

                var entity = item.Entity as TrialUser;
                var user = await _dbContext.Users.Include(x => x.UserTypeRole).FirstOrDefaultAsync(x => x.Id == entity.UserId);
                await InsertInspection<TrialUser>(item.Entity, type, x => new DataInspection
                {
                    TrialId = x.TrialId,
                }, new
                {
                    UserRealName = user.FullName,
                    UserName = user.UserName,
                    UserType = user.UserTypeRole.UserTypeShortName,
                    EMail = user.EMail,
                    Phone = user.Phone,
                    OrganizationName = user.OrganizationName,
                    State = entity.IsDeleted ? "退出" : "加入",
                });
            }

            // 项目中心人员
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSiteUser)))
            {
                var entity = item.Entity as TrialSiteUser;
                if (entity.TrialSite == null)
                {
                    entity.TrialSite = await _dbContext.TrialSite.Where(x => x.TrialId == entity.TrialId && x.SiteId == entity.SiteId).FirstOrDefaultAsync();
                }

                if (entity.Site == null)
                {
                    entity.Site = await _dbContext.Site.Where(x => x.Id == entity.SiteId).FirstOrDefaultAsync();
                }

                var user = new User();



                if (entity.User == null)
                {
                    user = await _dbContext.User.Where(x => x.Id == entity.UserId).FirstOrDefaultAsync();
                }
                else
                {
                    user = entity.User;
                }

                // 这里有问题

                UserType userType = new UserType();
                userType = await _dbContext.UserType.Where(x => x.Id == user.UserTypeId).FirstOrDefaultAsync();

                await InsertInspection<TrialSiteUser>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {
                    TrialSiteCode = entity.TrialSite.TrialSiteCode,
                    SiteName = entity.Site.SiteName,
                    SiteAliasName = entity.TrialSite.TrialSiteAliasName,
                    City = entity.Site.City,
                    Country = entity.Site.Country,
                    Status = entity.IsDeleted ? "禁用" : "启用",
                    UserName = user.UserName,
                    UserRealName = user.FullName,
                    UserType = userType.UserTypeShortName,
                    Phone = user.Phone,
                    Email = user.EMail,
                    Organization = entity.User.OrganizationName,

                });
            }

            // 中心调研表
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialSiteSurvey)))
            {
                var entity = item.Entity as TrialSiteSurvey;
                if (entity.TrialSite == null)
                {
                    entity.TrialSite = await _dbContext.TrialSite.Where(x => x.SiteId == entity.SiteId && x.TrialId == entity.TrialId).FirstOrDefaultAsync();
                }

                if (entity.PreliminaryUser == null)
                {
                    entity.PreliminaryUser = await _dbContext.User.Where(x => x.Id == entity.PreliminaryUserId).FirstOrDefaultAsync();
                }

                if (entity.ReviewerUser == null)
                {
                    entity.ReviewerUser = await _dbContext.User.Where(x => x.Id == entity.ReviewerUserId).FirstOrDefaultAsync();
                }

                await InsertInspection<TrialSiteSurvey>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,


                }, new
                {
                    TrialSiteCode = entity.TrialSite.TrialSiteCode,
                    TrialSiteAliasName = entity.TrialSite.TrialSiteAliasName,
                    Phone = entity.Phone,
                    Email = entity.Email,
                    PreliminaryUser = entity.PreliminaryUser == null ? "" : entity.PreliminaryUser.LastName + " / " + entity.PreliminaryUser.FirstName,
                    ReviewerUser = entity.ReviewerUser == null ? "" : entity.ReviewerUser.LastName + " / " + entity.ReviewerUser.FirstName,
                    IsDeleted = entity.IsDeleted ? "是" : "否",
                });
            }

            // 项目问题
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialQCQuestion)))
            {
                var entity = item.Entity as TrialQCQuestion;
                var paretName = await _dbContext.TrialQCQuestionConfigure.Where(x => x.Id == entity.ParentId).Select(x => x.QuestionName).FirstOrDefaultAsync();
                await InsertInspection<TrialQCQuestion>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {
                    QuestionName = entity.QuestionName,
                    Type = entity.Type,
                    TypeValue = entity.TypeValue,
                    ShowOrder = entity.ShowOrder,
                    IsRequired = entity.IsRequired,
                    ParentName = paretName,
                    ParentTriggerValue = entity.ParentTriggerValue,
                    IsEnable = entity.IsEnable,
                    IsQCQuestionConfirmed = entity.IsConfirm,
                });
            }

            // 受试者
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(Subject)))
            {
                var entity = item.Entity as Subject;
                var FinalSubjectVisitName = await _dbContext.SubjectVisit.AsNoTracking().Where(x => x.Id == entity.FinalSubjectVisitId && entity.FinalSubjectVisitId != null).Select(x => x.VisitName).FirstOrDefaultAsync();

                await InsertInspection<Subject>(item.Entity, type, x => new DataInspection()
                {
                    SubjectId = x.Id,
                    SubjectCode = x.Code,
                }, new
                {
                    FinalSubjectVisitName = FinalSubjectVisitName,
                });
            }

            // 检查
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(DicomStudy)))
            {
                await InsertInspection<DicomStudy>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 序列
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(DicomSeries)))
            {
                var entity = item.Entity as DicomSeries;
                var dicomStudy = entity.DicomStudy.Clone();
                if (dicomStudy == null)
                {
                    dicomStudy = await _dbContext.DicomStudys.AsNoTracking().FirstOrDefaultAsync(x => x.Id == entity.StudyId);
                }
                await InsertInspection<DicomSeries>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {
                    StudyCode = dicomStudy?.StudyCode,
                    Modalities = dicomStudy?.Modalities,

                });
            }

            // 非Dicom
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(NoneDicomStudy)))
            {
                var entity = item.Entity as NoneDicomStudy;
                var filecount = await _dbContext.NoneDicomStudyFile.Where(x => x.NoneDicomStudyId == entity.Id).CountAsync();
               

                await InsertInspection<NoneDicomStudy>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {
                    FileCount = filecount,
                });
            }

            // 非Dicom文件
            if (entitys.Any(x => x.Entity.GetType() == typeof(NoneDicomStudyFile)))
            {
                var noneDicomStudyfile = entitys.Where(x => x.Entity.GetType() == typeof(NoneDicomStudyFile)).Select(x => x.Entity).FirstOrDefault() as NoneDicomStudyFile;
                var noneDicomStudy = await _dbContext.NoneDicomStudy.Where(x => x.Id == noneDicomStudyfile.NoneDicomStudyId).FirstOrDefaultAsync();
                if (noneDicomStudy != null)
                {
                    var filecount = await _dbContext.NoneDicomStudyFile.Where(x => x.NoneDicomStudyId == noneDicomStudyfile.NoneDicomStudyId).CountAsync();
                    var count = entitys.Where(x => x.Entity.GetType() == typeof(NoneDicomStudyFile)).ToList().Count;
                    if (type == "Deleted")
                    {
                        filecount = filecount - count;
                    }
                    else
                    {
                        filecount = filecount + count;
                    }

                    await InsertInspection<NoneDicomStudy>(noneDicomStudy, type, x => new DataInspection()
                    {
                        GeneralId = x.Id,
                    }, new
                    {
                        FileCount = filecount,
                    });

                }
            }


            #region 注释代码
            ////非Dicom文件
            //foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(NoneDicomStudyFile)))
            //{
            //    var entity = item.Entity as NoneDicomStudyFile;
            //    var noneDicomStudy = entity.NoneDicomStudy;
            //    if (noneDicomStudy == null)
            //    {
            //        noneDicomStudy = await _dbContext.NoneDicomStudy.FirstOrDefaultAsync(x => x.Id == entity.NoneDicomStudyId);
            //    }
            //    noneDicomStudy = noneDicomStudy ?? new NoneDicomStudy();
            //    var fileCount = 0;
            //    if (type == "Add")
            //    {
            //        fileCount = _dbContext.NoneDicomStudyFile.Where(x => x.NoneDicomStudyId == entity.NoneDicomStudyId).Count() + 1;
            //    }
            //    else if (type == "Deleted")
            //    {
            //        fileCount = _dbContext.NoneDicomStudyFile.Where(x => x.NoneDicomStudyId == entity.NoneDicomStudyId).Count() - 1;
            //    }
            //    await InsertInspection<NoneDicomStudyFile>(item.Entity, type, x => new DataInspection()
            //    {
            //        GeneralId = x.Id,
            //        TrialId = noneDicomStudy.TrialId,
            //        SubjectId = noneDicomStudy.SubjectId,
            //        SiteId = noneDicomStudy.SiteId,
            //        SubjectVisitId = noneDicomStudy.SubjectVisitId,

            //    }, new
            //    {
            //        StudyCode = noneDicomStudy.StudyCode,
            //        Modality = noneDicomStudy.Modality,
            //        BodyPart = noneDicomStudy.BodyPart,
            //        FileCount = fileCount,
            //        ImageDate = noneDicomStudy.ImageDate,
            //        UpNum = 1,// 每次上传或下载一个
            //    });
            //}
            #endregion



            //一致性核查
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(CheckChallengeDialog)))
            {
              
                var entity = item.Entity as CheckChallengeDialog;
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                var reason = string.Empty;

                switch (_userInfo.RequestUrl.ToLower())
                {
                    case "qcoperation/closecheckchallenge":
                        reason = entity.TalkContent.Substring(entity.TalkContent.LastIndexOf(':') + 1);
                        break;
                }
                await InsertInspection<CheckChallengeDialog>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = entity.SubjectVisitId,
                    TrialId = subjectvisit.TrialId,
                    SubjectVisitId = x.SubjectVisitId,
                    SiteId = subjectvisit.SiteId,
                    SubjectId = subjectvisit.SubjectId,
                    SubjectVisitName = subjectvisit.VisitName,
                    BlindName = subjectvisit.BlindName,
                    Reason = reason,
                    CreateTime=x.CreateTime,
                }, new
                {
                    CheckState = subjectvisit.CheckState,
                    RequestBackState = subjectvisit.RequestBackState,
                    CheckChallengeState = subjectvisit.CheckChallengeState,
                });
            }

            // 访视
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SubjectVisit)))
            {
                var entity = item.Entity as SubjectVisit;
                string reason = string.Empty;

                if (_userInfo.RequestUrl.ToLower() == "qcoperation/setcheckpass")
                {
                    reason = entity.ManualPassReason;
                }
                            

                var subjectCode = entity.Subject?.Code;
                await InsertInspection<SubjectVisit>(item.Entity, type, x => new DataInspection()
                {
                    SubjectCode = subjectCode,
                    SubjectId = x.SubjectId,
                    SubjectVisitId = x.Id,
                    SubjectVisitName = x.VisitName,
                    BlindName = x.BlindName,
                    Reason = reason,
                });
            }

            // 既往手术史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousSurgery)))
            {
                var entity = item.Entity as PreviousSurgery;
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                await InsertInspection<PreviousSurgery>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                    SiteId = subjectvisit.SiteId,
                    SubjectVisitName = subjectvisit.VisitName,
                    TrialId = subjectvisit.TrialId,
                    SubjectId = subjectvisit.SubjectId,

                }, new
                {
                    Type = "既往手术史"
                });
            }

            // 既往放疗史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousHistory)))
            {
                var entity = item.Entity as PreviousHistory;
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                await InsertInspection<PreviousHistory>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                    SiteId = subjectvisit.SiteId,
                    SubjectVisitName = subjectvisit.VisitName,
                    TrialId = subjectvisit.TrialId,
                    SubjectId = subjectvisit.SubjectId,
                }, new
                {
                    Type = "既往放疗史"
                });
            }

            // 其他治疗史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousOther)))
            {
                var entity = item.Entity as PreviousOther;
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                await InsertInspection<PreviousOther>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                    SiteId = subjectvisit.SiteId,
                    SubjectVisitName = subjectvisit.VisitName,
                    TrialId = subjectvisit.TrialId,
                    SubjectId = subjectvisit.SubjectId,
                }, new
                {
                    Type = "其他治疗史"
                });
            }

            //质疑
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(QCChallenge)))
            {
                var entity = item.Entity as QCChallenge;
               
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                var content = string.Empty;
                if (type == "Add")
                {
                    content = entity.Content;
                }
                await InsertInspection<QCChallenge>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                    TrialId = x.TrialId,
                    SubjectVisitId = x.SubjectVisitId,
                    SiteId = subjectvisit.SiteId,
                    SubjectId = subjectvisit.SubjectId,
                    SubjectVisitName = subjectvisit.VisitName,
                    BlindName = subjectvisit.BlindName,
                }, new
                {
                    ChallengeCode = "Q" + entity.ChallengeCode.ToString("D5"),
                    AuditState = subjectvisit.AuditState,
                    TalkContent = content,
                    IsOverTime = entity.IsClosed ? entity.ClosedTime > entity.DeadlineTime : DateTime.Now > entity.DeadlineTime,
                });
            }

            // 质疑信息
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(QCChallengeDialog)))
            {
                var reason = string.Empty;
                var entity = item.Entity as QCChallengeDialog;
                switch (_userInfo.RequestUrl.ToLower())
                {
                    case "qcoperation/closeqcchallenge":
                        reason = entity.TalkContent.Substring(entity.TalkContent.LastIndexOf(':') + 1);
                        break;
                }
              
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
                var qCChallenge = await _dbContext.QCChallenge.Where(x => x.Id == entity.QCChallengeId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                qCChallenge = qCChallenge ?? new QCChallenge();
                await InsertInspection<QCChallengeDialog>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = qCChallenge.Id,
                    TrialId = subjectvisit.TrialId,
                    SubjectVisitId = x.SubjectVisitId,
                    SiteId = subjectvisit.SiteId,
                    SubjectId = subjectvisit.SubjectId,
                    SubjectVisitName = subjectvisit.VisitName,
                    BlindName = subjectvisit.BlindName,
                    Reason = reason,
                }, new
                {
                    AuditState = subjectvisit.AuditState,
                    ChallengeCode = "Q" + qCChallenge.ChallengeCode.ToString("D5"),
                    ReuploadEnum = qCChallenge.ReuploadEnum,
                    Content = qCChallenge.Content,
                    DeadlineTime = qCChallenge.DeadlineTime,
                    IsOverTime = qCChallenge.IsClosed ? qCChallenge.ClosedTime > qCChallenge.DeadlineTime : DateTime.Now > qCChallenge.DeadlineTime,
                    IsClosed = qCChallenge.IsClosed
                });
            }

           
            //Qc 问题
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(QCQuestion)))
            {
                await InsertInspection<QCQuestion>(item.Entity, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // Qc 问题答案
            if (entitys.Any(x => x.Entity.GetType() == typeof(TrialQCQuestionAnswer)))
            {
                var entitylist = entitys.Where(x => x.Entity.GetType() == typeof(TrialQCQuestionAnswer)).Select(x => x.Entity as TrialQCQuestionAnswer).ToList();
                var firstentity = entitylist.FirstOrDefault();
                var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == firstentity.SubjectVisitId).FirstOrDefaultAsync();
                subjectvisit = subjectvisit ?? new SubjectVisit();
                if (type == "Add")
                {
                    await AddInspectionRecordAsync(new DataInspection()
                    {
                        SiteId = subjectvisit.SiteId,
                        Identification = $"{_userInfo.RequestUrl}/{ firstentity.GetType().Name}/{type}",
                        SubjectId = subjectvisit.SubjectId,
                        SubjectVisitName = subjectvisit.VisitName,
                        TrialId = subjectvisit.TrialId,
                        SubjectVisitId = subjectvisit.Id,
                        GeneralId = subjectvisit.Id,
                    }, new
                    {
                        QcQuestionAnswerCommands = await Getdata(entitylist),
                    });
                }
                else if (type == "Update")
                {
                  
                    var questionids = entitylist.Where(x => x.SubjectVisitId == subjectvisit.Id).Select(x => x.Id).ToList();
                    var createUserId = entitylist.Select(x => x.CreateUserId).FirstOrDefault();
                    var noupdatedata = _dbContext.TrialQCQuestionAnswer.Where(x => x.CreateUserId== createUserId&& x.SubjectVisitId == subjectvisit.Id && !questionids.Contains(x.Id)).ToList();
                    entitylist.AddRange(noupdatedata);
                    await AddInspectionRecordAsync(new DataInspection()
                    {
                        Identification = $"{_userInfo.RequestUrl}/{ firstentity.GetType().Name}/{type}",
                        SiteId = subjectvisit.SiteId,
                        SubjectId = subjectvisit.SubjectId,
                        TrialId = subjectvisit.TrialId,
                        SubjectVisitId = subjectvisit.Id,
                        SubjectVisitName = subjectvisit.VisitName,
                        GeneralId = subjectvisit.Id,
                    }, new
                    {
                        QcQuestionAnswerCommands = await Getdata(entitylist),
                    });
                }

                async Task<List<AnswerDto>> Getdata(List<TrialQCQuestionAnswer> questionAnswers)
                {
                    var ids = questionAnswers.Select(x => x.TrialQCQuestionConfigureId).ToList();
                    var trialQCQuestionConfigureDatas = await _dbContext.TrialQCQuestionConfigure.Where(x => ids.Contains(x.Id)).ToListAsync();
                    var collect = questionAnswers.GroupJoin(trialQCQuestionConfigureDatas, one => one.TrialQCQuestionConfigureId, two => two.Id, (x, y) => new { one = x, two = y })
                      .SelectMany(a => a.two.DefaultIfEmpty(), (c, d) => new { c = c.one, d })
                      .OrderBy(x=>x.d.ShowOrder)
                      .Select(o => new AnswerDto()
                      {
                          QuestionName = o.d.QuestionName,
                          Answer = o.c.Answer,
                      }).ToList();
                    return collect;
                }

            }

            #region 备注
            ////Qc 问题答案
            //foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialQCQuestionAnswer)))
            //{
            //    var entity = item.Entity as TrialQCQuestionAnswer;
            //    var subjectvisit = await _dbContext.SubjectVisit.Where(x => x.Id == entity.SubjectVisitId).FirstOrDefaultAsync();
            //    subjectvisit = subjectvisit ?? new SubjectVisit();
            //    type = type == "Update" ? "Add" : type;
            //    await InsertInspection<TrialQCQuestionAnswer>(item.Entity, type, x => new DataInspection()
            //    {
            //        SiteId= subjectvisit.SiteId,
            //        SubjectId= subjectvisit.SubjectId,
            //        SubjectVisitName= subjectvisit.VisitName,
            //        GeneralId = x.Id,
            //    });
            //}
            #endregion

            #endregion

        }

        /// <summary>
        /// 插入稽查实体
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="data">数据</param>
        /// <param name="type">类型</param>
        /// <param name="expression">表达式</param>
        /// <param name="otherItem">其他对象</param>
        /// <returns></returns>
        public async Task InsertInspection<T>(object data, string type, Expression<Func<T, DataInspection>> expression = null, object otherItem = null,object originaldata=null) where T : class
        {
            object entityobj = data;
            DataInspection inspection = new DataInspection();
            if (expression != null)
            {
                var f = expression.Compile();
                var entitydata = entityobj as T;
                inspection = f(entitydata);
            }

            var entityTypeName = entityobj.GetType().Name;

            //文档签署这块，不区分系统和项目的 需要处理为同一个标识
            if (typeof(T) == typeof(TrialDocUserTypeConfirmedUser) || typeof(T) == typeof(SystemDocConfirmedUser))
            {
                entityTypeName = "New/" + "UserSigned";
            }



            dynamic entity;
            switch (entityobj.GetType().Name)
            {
                case nameof(QCChallengeDialog):
                case nameof(QCChallenge):
                case nameof(CheckChallengeDialog):
                    type = type + "/(" + _userInfo.UserTypeShortName + ")";
                    break;

                case nameof(NoneDicomStudy):
                    switch (_userInfo.RequestUrl.ToLower())
                    {
                        case "nonedicomstudy/addorupdatenonedicomstudy":
                            type =   type + "/("+ _userInfo.UserTypeShortName + ")";
                            break;
                    }
                    break;
                case nameof(SystemBasicData):
                     entity = entityobj as SystemBasicData;
                    type = type + (entity.ParentId == null ? "/parent" : string.Empty);
                    break;
                case nameof(Trial):
                    entity = originaldata as Trial;
                    switch (_userInfo.RequestUrl.ToLower())
                    {
                        case "configtrialbasicinfo/configtrialbasicinfoconfirm":
                            type = type + "/" + entity.IsTrialBasicLogicConfirmed.ToString();
                            break;
                        case "configtrialbasicinfo/configtrialprocessinfoconfirm":
                            type = type + "/" + entity.IsTrialProcessConfirmed.ToString();
                            break;
                        case "configtrialbasicinfo/configtrialurgentinfoconfirm":
                            type = type + "/" + entity.IsTrialUrgentConfirmed.ToString();
                            break;
                    }
                    break;
                case nameof(SubjectVisit):
                    entity = originaldata as SubjectVisit;
                    switch (_userInfo.RequestUrl.ToLower())
                    {
                        case "qcoperation/obtainorcancelqctask":
                            type = type + "/" + entity.IsTake.ToString();
                            break;
                        case "qcoperation/qcpassedorfailed":
                            try
                            {
                                type = type + "/" + (40 % (int)entity.AuditState).ToString();
                            }
                            catch (Exception)
                            {
                            }
                            break;
                    }
                    break;
            }



            inspection.Identification = $"{_userInfo.RequestUrl}/{ entityTypeName}/{type}";

            #region 注释
            //if (data != null)
            //{
            //    var originaldata = data.OriginalValues.ToObject();
            //    if (originaldata != null)
            //    {
            //        inspection.LastJsonDetail = originaldata.ToJcJson();
            //    }
            //}
            #endregion

            await AddInspectionRecordAsync(inspection, entityobj, otherItem);
        }






        /// <summary>
        /// 获取URl参数
        /// </summary>
        /// <returns></returns>
        //public string GetRequestUrl()
        //{
        //    return _userInfo.RequestUrl;
        //}

        /// <summary>
        /// 映射数据
        /// </summary>
        /// <param name="data"></param>
        /// <param name="mapData">要赋值的对象</param>
        public void MapData(dynamic data, dynamic mapData)
        {
            List<string> column = new List<string>() { "TrialId", "SiteId", "SubjectId", "SubjectVisitId", "CreateUserName", "TrialName", "SiteName", "SubjectCode", "VisitName", "SubjectVisitName", "RoleName", "SiteCode", "ResearchProgramNo" };
            foreach (var item in column)
            {
                try
                {
                    var i = mapData.GetType().GetProperty(item).GetValue(mapData);
                    if (i == null || i == default(Guid))
                    {
                        var value = data.GetType().GetProperty(item).GetValue(data);
                        mapData.GetType().GetProperty(item).SetValue(mapData, value);
                    }

                }
                catch (Exception)
                {
                    continue;

                }
            }
        }

        /// <summary>
        /// 添加稽查
        /// </summary>
        /// <param name="add">新增的稽查对象</param>
        /// <param name="data">数据</param>
        /// <returns></returns>
        /// <exception cref="BusinessValidationFailedException"></exception>
        public async Task AddInspectionRecordAsync(DataInspection add, dynamic data, object otherItem = null)
        {
            MapData(data, add);
            InspectionGeneralData generalData = new InspectionGeneralData();
            MapData(add, generalData);
            await SetInspectionNameValue(generalData);
            #region 处理标识

            var from = await _dbContext.FrontAuditConfig.FirstOrDefaultAsync(x => x.Identification == add.Identification);
            add.ObjectType = from?.ObjectTypeId;
            add.OptType = from?.OptTypeId;
            add.ChildrenType = from?.ChildrenTypeId;
            add.ModuleType = from?.ModuleTypeId;

            #endregion
            if (add.ParentId == null)
            {
                add.ParentId = (await _dbContext.DataInspection.AsQueryable().Where(x => x.TrialId == add.TrialId && x.SubjectVisitId == add.SubjectVisitId && x.SubjectId == add.SubjectId && x.SiteId == add.SiteId && x.VisitStageId == add.VisitStageId && x.GeneralId == add.GeneralId).OrderByDescending(x => x.CreateTime).FirstOrDefaultAsync())?.Id;
            }
            add.CreateUserId = _userInfo.Id;
            add.IP = _userInfo.IP;
            add.CreateTime = add.CreateTime == default(DateTime) ? DateTime.Now : add.CreateTime;

            if (_userInfo.SignId != null)
            {
                add.SignId = _userInfo.SignId;
                add.IsSign = true;
            }

            var inspectionData = new InspectionJsonDetail()
            {
                Data = AddJsonItem(data, otherItem),
                Inspection = generalData
            };
            add.JsonDetail = inspectionData.ToJsonStr();

            await _dbContext.DataInspection.AddAsync(add);
        }



        /// <summary>
        /// 往json里面添加属性
        /// </summary>
        /// <param name="json">json</param>
        /// <param name="otherItem">添加对象</param>
        /// <returns></returns>
        public IDictionary<string, object> AddJsonItem(dynamic json, object otherItem = null)
        {


            var JsonData = JsonConvert.DeserializeObject<IDictionary<string, object>>((json as object).ToJsonStr());

            if (otherItem == null)
            {
                return JsonData;
            }
            var other = JsonConvert.DeserializeObject<IDictionary<string, object>>(otherItem.ToJsonStr());

            foreach (var item in other)
            {
                if (JsonData.ContainsKey(item.Key))
                {
                    JsonData[item.Key] = item.Value;
                }
                else
                {
                    JsonData.Add(item.Key, item.Value);
                }

            }
            return JsonData;

        }

        /// <summary>
        /// 判断是否为空
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private bool IsNullOrEmpty(object value)
        {
            if (value == null || value.ToString() == string.Empty)
            {
                return true;
            }
            else
            {
                return false;
            }
        }




        /// <summary>
        /// 设置项目以及名称
        /// </summary>
        /// <param name="generalData"></param>
        /// <returns></returns>
        public async Task SetInspectionNameValue(InspectionGeneralData generalData)
        {
            #region 项目名称


            if (generalData.TrialId != null)
            {

                //项目添加哪里 直接会带信息过来，不用查询数据库  其他的地方需要查询数据库
                if (string.IsNullOrEmpty(generalData.ResearchProgramNo) || string.IsNullOrEmpty(generalData.TrialName))
                {
                    var trialdata = (await _dbContext.Trial.Select(x => new { x.Id, x.ResearchProgramNo, x.ExperimentName, }).FirstOrDefaultAsync(x => x.Id == generalData.TrialId)).IfNullThrowException();

                    generalData.ResearchProgramNo = trialdata.ResearchProgramNo;

                    generalData.TrialName = trialdata.ExperimentName;
                }


            }

            #endregion

            #region 测试中心名称

            if (generalData.TrialId != null && generalData.SiteId != null)
            {

                generalData.SiteCode = (await _dbContext.TrialSite.IgnoreQueryFilters().Where(x => x.TrialId == generalData.TrialId && x.SiteId == generalData.SiteId).Select(t => t.TrialSiteCode).FirstOrDefaultAsync()).IfNullThrowException();


                // 添加Site 哪里会带信息过来
                if (string.IsNullOrEmpty(generalData.SiteName))
                {
                    generalData.SiteName = (await _dbContext.Site.Where(x => x.Id == generalData.SiteId).Select(x => x.SiteName).FirstOrDefaultAsync()).IfNullThrowException();

                }
            }


            #endregion

            #region 受试者

            if (generalData.SubjectId != null)
            {

                // 添加Subject 哪里会带信息过来
                if (string.IsNullOrEmpty(generalData.SubjectCode))
                {
                    generalData.SubjectCode = (await _dbContext.Subject.Where(x => x.Id == generalData.SubjectId).Select(x => x.Code).FirstOrDefaultAsync()).IfNullThrowException();

                }
            }



            #endregion

            #region 访视

            if (generalData.SubjectVisitId != null)
            {
                //添加访视的时候，会带信息过来
                if (string.IsNullOrEmpty(generalData.SubjectVisitName))
                {
                    generalData.SubjectVisitName = (await _dbContext.SubjectVisit.Where(x => x.Id == generalData.SubjectVisitId).Select(x => x.VisitName).FirstOrDefaultAsync()).IfNullThrowException();
                }
            }


            #endregion


            generalData.CreateUserName = _userInfo.RealName;

            generalData.RoleName = _userInfo.UserTypeShortName;

        }

    }
}
