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 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.Added).ToList(), "Add");

            // 修改
            await InsertAddEntitys(entitys.Where(x => x.State == EntityState.Modified&&(!typeof(ISoftDelete).IsAssignableFrom(x.Entity.GetType())
            || !(bool)x.Entity.GetType().GetProperty("IsDeleted").GetValue(x.Entity))
            ).ToList(), "Update");

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



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

        /// <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(Trial)))
            {
                await InsertInspection<Trial>(item, type, x => new DataInspection()
                {
                    TrialId = x.Id,
                    TrialName = x.ExperimentName,
                });
            }

            // 访视计划
            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(TrialUser)))
            {
                await InsertInspection<TrialUser>(item, type);
            }
            // 受试者
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(Subject)))
            {
                await InsertInspection<Subject>(item, type, x => new DataInspection()
                {
                    SubjectId = x.Id,
                    SubjectCode=x.Code,
                });
            }
            // 访视
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(SubjectVisit)))
            {
                var subjectCode = (item.Entity as SubjectVisit).Subject?.Code;
                await InsertInspection<SubjectVisit>(item, type, x => new DataInspection()
                {
                    SubjectCode= subjectCode,
                    SubjectId=x.SubjectId,
                    SubjectVisitId = x.Id,
                    SubjectVisitName=x.VisitName,
                });
            }


            // 既往手术史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousSurgery)))
            {
                await InsertInspection<PreviousSurgery>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }


            // 既往放疗史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousHistory)))
            {
                await InsertInspection<PreviousHistory>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 其他治疗史
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(PreviousOther)))
            {
                await InsertInspection<PreviousOther>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

            // 检查
            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;

                await InsertInspection<DicomSeries>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                }, new
                {
                    StudyCode = entity.DicomStudy.StudyCode,
                    Modalities = entity.DicomStudy.Modalities,
                   
                });
            }

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

            // 非Dicom文件
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(NoneDicomStudyFile)))
            {
                await InsertInspection<NoneDicomStudyFile>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }

         

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

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

            //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 问题答案
            foreach (var item in entitys.Where(x => x.Entity.GetType() == typeof(TrialQCQuestionAnswer)))
            {
                await InsertInspection<TrialQCQuestionAnswer>(item, type, x => new DataInspection()
                {
                    GeneralId = x.Id,
                });
            }
            #endregion

        }

        /// <summary>
        /// 插入稽查实体
        /// </summary>
        /// <typeparam name="T">泛型</typeparam>
        /// <param name="data">数据</param>
        /// <param name="type">类型</param>
        /// <param name="expression">表达式</param>
        /// <returns></returns>
        public async Task InsertInspection<T>(EntityEntry data, string type, Expression<Func<T, DataInspection>> expression = null,object otherItem=null) where T:class
        {
         
            DataInspection inspection = new DataInspection();
            if (expression != null)
            {
                var f = expression.Compile();
                var entity = data.Entity as T;
                inspection = f(entity);
            }
            inspection.Identification = $"{GetRequestUrl()}/{ data.Entity.GetType().ToString().Substring(data.Entity.GetType().ToString().LastIndexOf('.') + 1)}/{type}";
            var originaldata = data.OriginalValues as T;
            if (originaldata != null)
            {
                inspection.LastJsonDetail = originaldata.ToJcJson();
            }
          
            await AddInspectionRecordAsync(inspection, data.Entity, 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", "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
        }

    }
}
