using IRaCIS.Core.Domain.BaseModel;
using IRaCIS.Core.Domain.Models;
using IRaCIS.Core.Infra.EFCore.Common;
using IRaCIS.Core.Infrastructure.Encryption;
using IRaCIS.Core.Infrastructure.Extention;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Newtonsoft.Json;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Data;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
namespace IRaCIS.Core.Infra.EFCore;
#region 连接池废弃 
/// 
/// 报错,添加subject 报错,重复添加访视
/// 
//public class IRaCISDBScopedFactory : IDbContextFactory
//{
//    private readonly IDbContextFactory _pooledFactory;
//    private readonly IUserInfo _userInfo;
//    public IRaCISDBScopedFactory(IDbContextFactory pooledFactory,IUserInfo userInfo)
//    {
//        _pooledFactory = pooledFactory;
//        _userInfo = userInfo;
//    }
//    public IRaCISDBContext CreateDbContext()
//    {
//        var context = _pooledFactory.CreateDbContext();
//        context._userInfo = _userInfo;
//        return context;
//    }
//}
#endregion
public class IRaCISDBContext : DbContext
{
    public IRaCISDBContext(DbContextOptions options) : base(options)
    {
    }
    /// 
    /// efcore codefirst 防止数据注解过多配置,全局统一配置
    /// 
    /// 
    protected override void ConfigureConventions(ModelConfigurationBuilder configurationBuilder)
    {
        //decimal 不配置,默认精度是18,2
        //configurationBuilder.Conventions.Add(_ => new DecimalPrecisionConvention(18,2));
        //针对字符串使用默认的长度配置为200,如果标注了StringLength 其他长度,就是标注的长度,如果标注了MaxLength 那么就是nvarcharMax
        configurationBuilder.Conventions.Add(_ => new DefaultStringLengthConvention(400));
    }
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity(entity =>
        {
            // 使用部分加密值转换器,前 2 个字符不加密,方便模糊搜索
            entity.Property(e => e.Name).HasConversion(new PartialEncryptionConverter(2));
            //entity.OwnsMany(x => x.TestJsonObjectLsit, ownedNavigationBuilder =>
            //{
            //    ownedNavigationBuilder.ToJson();
            //});
            entity.Property(e => e.TestJsonObjectLsit).HasConversion(v => v == null ? "[]" : JsonConvert.SerializeObject(v),
                v => string.IsNullOrEmpty(v) ? null : JsonConvert.DeserializeObject>(v));
        });
        modelBuilder.Entity(entity =>
        {
            //项目术语配置
            entity.OwnsMany(x => x.TrialObjectNameList, ownedNavigationBuilder =>
            {
                ownedNavigationBuilder.ToJson();
            });
        });
        #region pgsql codefirst 配置 暂时屏蔽
        //if (base.Database.IsNpgsql())
        //{
        //    modelBuilder.HasPostgresExtension("uuid-ossp");
        //    //保证pgsql 生成的时间默认为timestamp 而不是  timestamp with time zone
        //    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        //    {
        //        foreach (var property in entityType.GetProperties())
        //        {
        //            if (property.ClrType == typeof(DateTime) || property.ClrType == typeof(DateTime?))
        //            {
        //                property.SetColumnType("timestamp without time zone");
        //            }
        //        }
        //    }
        //}
        #endregion
        #region decimal 自定义精度,适配多种数据库
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            foreach (var property in entityType.GetProperties())
            {
                // 如果属性类型是 decimal 或 nullable decimal
                if (property.ClrType == typeof(decimal) || property.ClrType == typeof(decimal?))
                {
                    // 获取自定义的 DecimalPrecisionAttribute
                    var precisionAttr = property.PropertyInfo?.GetCustomAttributes(typeof(DecimalPrecisionAttribute), false)
                        .FirstOrDefault() as DecimalPrecisionAttribute;
                    if (precisionAttr != null)
                    {
                        property.SetPrecision(precisionAttr.Precision);
                        property.SetScale(precisionAttr.Scale);
                    }
                    else
                    {
                        // 默认的精度设置
                        property.SetPrecision(18);
                        property.SetScale(2);
                    }
                }
            }
        }
        #endregion
        //遍历实体模型手动配置
        var typesToRegister = Assembly.GetExecutingAssembly().GetTypes().Where(q => q.GetInterface(typeof(IEntityTypeConfiguration<>).FullName) != null);
        foreach (var type in typesToRegister)
        {
            dynamic configurationInstance = Activator.CreateInstance(type);
            modelBuilder.ApplyConfiguration(configurationInstance);
        }
        base.OnModelCreating(modelBuilder);
        //软删除筛选器通常依赖于实体模型的完整定义(例如属性映射、继承关系等)
        foreach (var entityType in modelBuilder.Model.GetEntityTypes())
        {
            // 软删除配置
            if (typeof(ISoftDelete).IsAssignableFrom(entityType.ClrType))
            {
                //entityType.AddSoftDeleteQueryFilter();
                // 动态创建表达式:e => e.IsDeleted==false
                var parameter = Expression.Parameter(entityType.ClrType, "e");
                var property = Expression.Property(parameter, nameof(ISoftDelete.IsDeleted));
                var filter = Expression.Lambda(
                    Expression.Equal(property, Expression.Constant(false)),
                    parameter);
                // 应用全局查询筛选器
                modelBuilder.Entity(entityType.ClrType).HasQueryFilter(filter);
                //Console.WriteLine($"实体应用软删除:{entityType.ClrType.Name}");
            }
            foreach (var navigation in entityType.GetNavigations())
            {
                if (navigation.IsCollection) continue;
                #region 有问题 
                // 比如 e.SourceSubjectVisit.IsDeleted == False  还会导致 dicom 查询增加额外很多的连表  因为访视  项目  项目中心,dicom 都是软删除
                //
                //// 配置基于导航属性的软删除查询筛选器
                //if (typeof(ISoftDelete).IsAssignableFrom(navigation.TargetEntityType.ClrType))
                //{
                //    var clrType = entityType.ClrType;
                //    var targetType = navigation.TargetEntityType.ClrType;
                //    //e => e.Subject.IsDeleted==false
                //    var parameterNav = Expression.Parameter(clrType, "e");
                //    var navigationProperty = Expression.Property(parameterNav, navigation.Name);
                //    var navigationFilter = Expression.Equal(
                //        Expression.Property(navigationProperty, nameof(ISoftDelete.IsDeleted)),
                //        Expression.Constant(false));
                //    var filterNav = Expression.Lambda(navigationFilter, parameterNav);
                //    modelBuilder.Entity(clrType).HasQueryFilter(filterNav);
                //    Console.WriteLine($"实体应用软删除:{entityType.ClrType.Name}   导航属性{filterNav}");
                //}
                #endregion
            }
            if (typeof(Entity).IsAssignableFrom(entityType.ClrType))
            {
                modelBuilder.Entity(entityType.ClrType).Property(nameof(Entity.Id)).HasValueGenerator();
            }
            if (typeof(IEntitySeqId).IsAssignableFrom(entityType.ClrType))
            {
                modelBuilder.Entity(entityType.ClrType).Property(nameof(IEntitySeqId.SeqId)).HasValueGenerator();
            }
        }
    }
    #region  获取表名 和字段名 优化
    /// 
    /// 直接获取代码定义的模型,以及表上定义的Description 获取表信息 以及备注
    /// 
    /// 
    public List GetContextTablesList()
    {
        var tableList = new List();
        foreach (var entityType in this.Model.GetEntityTypes())
        {
            var clrType = entityType.ClrType;
            var tableName = entityType.GetTableName();
            var tableDescription = clrType.GetCustomAttribute()?.Description ?? string.Empty;
            tableList.Add(new TableList
            {
                Name = tableName,
                Remake = tableDescription,
            });
        }
        return tableList;
    }
    /// 
    /// 直接获取代码定义的某个表的属性,以及属性上定义的Description 获取备注
    /// 
    /// 
    public List GetContextTableColumnList(string tableName)
    {
        var tableColumList = new List();
        var entityType = this.Model.GetEntityTypes().FirstOrDefault(t => t.GetTableName().ToLower() == tableName.ToLower());
        if (entityType == null)
        {
            throw new ArgumentException($"Table '{tableName}' not found.");
        }
        var clrType = entityType.ClrType;
        foreach (var property in entityType.GetProperties())
        {
            var columnName = property.GetColumnName();
            var columnDescription = clrType.GetProperty(property.Name)?.GetCustomAttribute()?.Description ?? string.Empty;
            tableColumList.Add(new TableList
            {
                Name = columnName,
                Remake = columnDescription,
            });
        }
        return tableColumList.OrderBy(t => t.Name).ToList();
    }
    #endregion
    #region Doctor
    public virtual DbSet Dictionary { get; set; }
    public virtual DbSet Doctor { get; set; }
    public virtual DbSet DoctorSummarize { get; set; }
    public virtual DbSet DoctorCriterionFile { get; set; }
    public virtual DbSet DoctorDictionary { get; set; }
    public virtual DbSet Postgraduate { get; set; }
    public virtual DbSet Education { get; set; }
    public virtual DbSet ResearchPublications { get; set; }
    public virtual DbSet TrialExperience { get; set; }
    public virtual DbSet Vacation { get; set; }
    public virtual DbSet Attachment { get; set; }
    public virtual DbSet TrialExperienceCriteria { get; set; }
    #endregion
    #region Enroll
    public virtual DbSet DoctorWorkload { get; set; }
    public virtual DbSet Enroll { get; set; }
    public virtual DbSet EnrollReadingCategory { get; set; }
    public virtual DbSet EnrollDetails { get; set; }
    #endregion
    #region Reading
    public virtual DbSet TrialCriterionDictionaryCode { get; set; }
    public virtual DbSet ReadingCustomTag { get; set; }
    public virtual DbSet SystemCriterionDictionaryCode { get; set; }
    public virtual DbSet ReadingTaskRelation { get; set; }
    public virtual DbSet OrganInfo { get; set; }
    public virtual DbSet ReadingSystemCriterionDictionary { get; set; }
    public virtual DbSet ReadingTableAnswerRowInfo { get; set; }
    public virtual DbSet OrganTrialInfo { get; set; }
    public virtual DbSet ReadingTableQuestionSystem { get; set; }
    public virtual DbSet ReadingPeriodSet { get; set; }
    public virtual DbSet ReadingTaskQuestionAnswer { get; set; }
    public virtual DbSet ReadingPeriodPlan { get; set; }
    public virtual DbSet ReadingClinicalData { get; set; }
    public virtual DbSet ReadingOncologyTaskInfo { get; set; }
    public virtual DbSet ReadingGlobalTaskInfo { get; set; }
    public virtual DbSet ReadingQuestionCriterionSystem { get; set; }
    public virtual DbSet ReadingQuestionCriterionTrial { get; set; }
    public virtual DbSet ReadingQuestionSystem { get; set; }
    public virtual DbSet ReadingQuestionTrial { get; set; }
    public virtual DbSet ReadingClinicalDataPDF { get; set; }
    public virtual DbSet ReadingConsistentClinicalData { get; set; }
    public virtual DbSet ReadingConsistentClinicalDataPDF { get; set; }
    public virtual DbSet ReadingJudgeInfo { get; set; }
    public virtual DbSet ReadModule { get; set; }
    public virtual DbSet ClinicalDataTrialSet { get; set; }
    public virtual DbSet ClinicalDataSystemSet { get; set; }
    public virtual DbSet ReadingMedicineSystemQuestion { get; set; }
    public virtual DbSet ReadingMedicineTrialQuestion { get; set; }
    public virtual DbSet ReadingMedicineQuestionAnswer { get; set; }
    public virtual DbSet ReadingMedicalReviewDialog { get; set; }
    public virtual DbSet CriterionNidusSystem { get; set; }
    public virtual DbSet CriterionNidusTrial { get; set; }
    public virtual DbSet ReadingTrialCriterionDictionary { get; set; }
    public virtual DbSet ReadingTableQuestionTrial { get; set; }
    public virtual DbSet TumorAssessment_RECIST1Point1BM { get; set; }
    public virtual DbSet TumorAssessment_RECIST1Point1 { get; set; }
    public virtual DbSet TumorAssessment_IRECIST1Point1 { get; set; }
    public virtual DbSet TrialClinicalDataSetCriterion { get; set; }
    public virtual DbSet TrialCriterionAdditionalAssessmentType { get; set; }
    public virtual DbSet SubjectCriteriaEvaluation { get; set; }
    public virtual DbSet SubjectAdditionalEvaluationResult { get; set; }
    public virtual DbSet SubjectCriteriaEvaluationVisitFilter { get; set; }
    public virtual DbSet SubjectCriteriaEvaluationVisitStudyFilter { get; set; }
    public virtual DbSet ReadingTaskQuestionMark { get; set; }
    //public virtual DbSet TrialClinicalDataCriterion { get; set; }
    //public virtual DbSet SystemClinicalDataCriterion { get; set; }
    #endregion
    #region Subject and Visit and study
    public virtual DbSet StudyMonitor { get; set; }
    public virtual DbSet Subject { get; set; }
    public virtual DbSet VisitPlans { get; set; }
    public virtual DbSet VisitPlanInfluenceStudy { get; set; }
    public virtual DbSet VisitPlanInfluenceStat { get; set; }
    public virtual DbSet NoneDicomStudyFile { get; set; }
    public virtual DbSet NoneDicomStudy { get; set; }
    public virtual DbSet PreviousPDF { get; set; }
    public virtual DbSet PreviousSurgery { get; set; }
    public virtual DbSet PreviousOther { get; set; }
    public virtual DbSet PreviousHistory { get; set; }
    public virtual DbSet DicomStudys { get; set; }
    public virtual DbSet DicomSeries { get; set; }
    public virtual DbSet DicomInstances { get; set; }
    public virtual DbSet ImageShare { get; set; }
    #endregion
    #region Management
    public virtual DbSet VerificationCodes { get; set; }
    public virtual DbSet