using IRaCIS.Core.Domain.Common;
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.Text;
using System.Threading.Tasks;

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

        /// <summary>
        /// 数据库对象
        /// </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)
                 };
            }
        }

        /// <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, 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, type, x => new DataInspection()
                {
                    GeneralId = x.Id
                },new {
                    NeedConfirmedUserType= usertypeName,
                });
            }

            // 签名模板
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SystemBasicData)))
            {
                var entity = item.Entity as SystemBasicData;
                type = type + (entity.ParentId == null ? "/parent" : string.Empty);
                await InsertInspection<SystemBasicData>(item, type, x => new DataInspection()
                {
                    VisitStageId = x.Id,
                });
            }

            // 项目
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(Trial)))
            {
                var originalValues = item.OriginalValues.ToObject() as Trial;
                switch (GetRequestUrl().ToLower())
                {
                    case "configtrialbasicinfo/configtrialbasicinfoconfirm":
                        type = type + "/" + originalValues.IsTrialBasicLogicConfirmed.ToString();
                        break;
                    case "configtrialbasicinfo/configtrialprocessinfoconfirm":
                        type = type + "/" + originalValues.IsTrialProcessConfirmed.ToString();
                        break;
                    case "configtrialbasicinfo/configtrialurgentinfoconfirm":
                        type = type + "/" + originalValues.IsTrialUrgentConfirmed.ToString();
                        break;
                }

                var entity = item.Entity as Trial;
                await InsertInspection<Trial>(item, type, x => new DataInspection()
                {
                    TrialId = x.Id,
                    TrialName = x.ExperimentName,
                    ResearchProgramNo=x.ResearchProgramNo,
                    GeneralId = x.Id,
                },new {
                    TrialDicList= string.Join(",",entity.TrialDicList.Select(x => x.KeyName).ToList()) 
                });
            }

            // 访视计划
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(VisitStage)))
            {
                await InsertInspection<VisitStage>(item, type, x => new DataInspection()
                {
                    VisitStageId = x.Id,
                });
            }

            // TrialDocument
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialDocument)))
            {
                await InsertInspection<TrialDocument>(item, type);
            }

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


            // 项目人员
            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, 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(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, 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, 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, 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();
                switch (GetRequestUrl().ToLower())
                {
                    case "nonedicomstudy/addorupdatenonedicomstudy":
                        type = _userInfo.UserTypeShortName + "/" + type;
                        break;
                }

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

            // 非Dicom文件
            //var noneDicomFile=

            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(null, type, x => new DataInspection()
                    {
                        GeneralId = x.Id,
                    }, new
                    {
                        FileCount = filecount,
                    }, noneDicomStudy);

                }
            }
            #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, 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(SubjectVisit)))
            {
                var entity = item.Entity as SubjectVisit;
                string reason = string.Empty;

                switch (GetRequestUrl().ToLower())
                {
                    case "qcoperation/obtainorcancelqctask":
                        type = type +"/"+ entity.IsTake.ToString();
                        break;
                        // 设置通过一致性核查
                    case "qcoperation/setcheckpass":
                        reason = entity.ManualPassReason;
                        break;
                    case "qcoperation/qcpassedorfailed":
                        try
                        {
                            type = type + "/" + (40 % (int)entity.AuditState).ToString();
                        }
                        catch (Exception)
                        {

                          
                        }
                      
                        break;
                }

                var subjectCode = entity.Subject?.Code;
                await InsertInspection<SubjectVisit>(item, 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, 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, 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, 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;
                type = _userInfo.UserTypeShortName +"/"+ type;
                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, 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 (GetRequestUrl().ToLower())
                {
                    case "qcoperation/closeqcchallenge":
                        reason = entity.TalkContent.Substring(entity.TalkContent.LastIndexOf(':') + 1);
                        break;
                }
                type = _userInfo.UserTypeShortName + "/" + type;
                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, 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
                });
            }

            //一致性核查
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(CheckChallengeDialog)))
            {
                type = _userInfo.UserTypeShortName + "/" + type;
                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 (GetRequestUrl().ToLower())
                {
                    case "qcoperation/closecheckchallenge":
                        reason = entity.TalkContent.Substring(entity.TalkContent.LastIndexOf(':') + 1);
                        break;
                }
                await InsertInspection<CheckChallengeDialog>(item, 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,
                },new {
                    CheckState= subjectvisit.CheckState,
                    RequestBackState = subjectvisit.RequestBackState,
                    CheckChallengeState= subjectvisit.CheckChallengeState,
                });
            }

            //Qc 问题
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(QCQuestion)))
            {
                await InsertInspection<QCQuestion>(item, 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")
                {
                    type = "Add";
                    var questionids = entitylist.Where(x => x.SubjectVisitId == subjectvisit.Id).Select(x => x.Id).ToList();
                    var noupdatedata = _dbContext.TrialQCQuestionAnswer.Where(x => 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 })
                      .Select(o => new AnswerDto()
                      {
                         QuestionName = o.d.QuestionName,
                         Answer = o.c.Answer,
                       }).ToList();
                      return collect;
                }

            }

            ////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, type, x => new DataInspection()
            //    {
            //        SiteId= subjectvisit.SiteId,
            //        SubjectId= subjectvisit.SubjectId,
            //        SubjectVisitName= subjectvisit.VisitName,
            //        GeneralId = x.Id,
            //    });
            //}
            #endregion

        }

        /// <summary>
        /// 插入稽查实体
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="data">数据</param>
        /// <param name="type">类型</param>
        /// <param name="expression">表达式</param>
        /// <param name="entityData">实体对象</param>
        /// <returns></returns>
        public async Task InsertInspection<T>(EntityEntry data, string type, Expression<Func<T, DataInspection>> expression = null,object otherItem=null,T entityData=null) where T:class
        {
            object entityobj = entityData == null ? data.Entity : entityData;
            DataInspection inspection = new DataInspection();
            if (expression != null)
            {
                var f = expression.Compile();
                var entity = entityobj as T;
                inspection = f(entity);
            }
            inspection.Identification = $"{_userInfo.RequestUrl}/{ entityobj.GetType().Name}/{type}";
            if (data != null)
            {
                var originaldata = data.OriginalValues.ToObject();
                if (originaldata != null)
                {
                    inspection.LastJsonDetail = originaldata.ToJcJson();
                }
            }
           
          
            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 处理标识
            try
            {
                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;
            }
            catch (Exception)
            {

                throw new BusinessValidationFailedException("操作标识异常");
            }
            #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;
            if (add.CreateTime == default(DateTime))
            {
                add.CreateTime = DateTime.Now;
            }

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

            var inspectionData = new InspectionData()
            {
                Data = AddJsonItem(data,otherItem),
                Inspection = generalData
            };
            add.JsonDetail = inspectionData.ToJcJson();
        
            await _dbContext.DataInspection.AddAsync(add);
        }



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

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

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

            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="Data"></param>
        /// <returns></returns>
        public async Task SetInspectionNameValue(InspectionGeneralData Data)
        {
            #region 项目名称

            var trialdata = await _dbContext.Trial.Select(x => new { x.Id, x.ResearchProgramNo, x.ExperimentName, }).FirstOrDefaultAsync(x => x.Id == Data.TrialId);
            if (IsNullOrEmpty(Data.ResearchProgramNo))
            {

                Data.ResearchProgramNo = trialdata?.ResearchProgramNo;
            }

            if (IsNullOrEmpty(Data.TrialName))
            {
                Data.TrialName = trialdata?.ExperimentName;
            }
            #endregion

            #region 测试中心名称


            Data.SiteCode = (await _dbContext.TrialSite.IgnoreQueryFilters().FirstOrDefaultAsync(x => x.TrialId == Data.TrialId && x.SiteId == Data.SiteId))?.TrialSiteCode;



            if (IsNullOrEmpty(Data.SiteName) && Data.SiteId != null)
            {
                var sitedata = await _dbContext.Site.Where(x => x.Id == Data.SiteId).Select(x => new { x.SiteName }).FirstOrDefaultAsync();
                Data.SiteName = sitedata?.SiteName;
            }
            #endregion

            #region 受试者


            if (IsNullOrEmpty(Data.SubjectCode) && Data.SubjectId != null)
            {

                Data.SubjectCode = (await _dbContext.Subject.Where(x => x.Id == Data.SubjectId).Select(x => new { x.Code }).FirstOrDefaultAsync())?.Code;
            }
            #endregion

            #region 访视
            if (IsNullOrEmpty(Data.SubjectVisitName))
            {
                Data.SubjectVisitName = (await _dbContext.SubjectVisit.Where(x => x.Id == Data.SubjectVisitId).Select(x => new { x.VisitName }).FirstOrDefaultAsync())?.VisitName;
            }
            #endregion

            #region 创建者

            if (IsNullOrEmpty(Data.CreateUserName))
            {
                Data.CreateUserName = _userInfo.RealName;
            }

            if (IsNullOrEmpty(Data.RoleName))
            {
                Data.RoleName = _userInfo.UserTypeShortName;
            }
            #endregion
        }

    }
}