using System.Collections;
using System.Reflection;
namespace IRaCIS.Core.Infra.EFCore;
public static class DbContextExt
{
    /// 
    /// 获取变化的实体信息
    /// 
    /// 
    /// 
    /// 
    public static IEnumerable GetChanges(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified && e.Entity is T).Select(e =>
        {
            var originalObject = e.OriginalValues.ToObject();
            var currentObject = e.CurrentValues.ToObject();
            return new ChangeEntry
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.OriginalValues.EntityType.ClrType,
                ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo()
                {
                    PropertyInfo = t1.Property.PropertyInfo,
                    OriginalValue = t1.Value,
                    CurrentValue = t2.Value,
                    IsPrimaryKey = t1.Property.IsPrimaryKey(),
                    IsForeignKey = t1.Property.IsForeignKey()
                }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList()
            };
        });
    }
    /// 
    /// 获取变化的实体信息
    /// 
    /// 
    /// 
    public static IEnumerable GetChanges(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Modified).Select(e =>
        {
            var originalObject = e.OriginalValues.ToObject();
            var currentObject = e.CurrentValues.ToObject();
            return new ChangeEntry()
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.OriginalValues.EntityType.ClrType,
                ChangeProperties = e.OriginalValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(originalObject))).Zip(e.CurrentValues.Properties.Select(p => (Property: p, Value: p.PropertyInfo.GetValue(currentObject))), (t1, t2) => new ChangePropertyInfo()
                {
                    PropertyInfo = t1.Property.PropertyInfo,
                    OriginalValue = t1.Value,
                    CurrentValue = t2.Value,
                    IsPrimaryKey = t1.Property.IsPrimaryKey(),
                    IsForeignKey = t1.Property.IsForeignKey(),
                }).Where(t => Comparer.Default.Compare(t.OriginalValue, t.CurrentValue) != 0).ToList()
            };
        });
    }
    /// 
    /// 获取添加的实体信息
    /// 
    /// 
    /// 
    /// 
    public static IEnumerable GetAdded(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added && e.Entity is T).Select(e =>
        {
            var currentObject = e.CurrentValues.ToObject();
            return new ChangeEntry
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.CurrentValues.EntityType.ClrType,
                ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
                {
                    PropertyInfo = p.PropertyInfo,
                    CurrentValue = p.PropertyInfo.GetValue(currentObject),
                    IsPrimaryKey = p.IsPrimaryKey(),
                    IsForeignKey = p.IsForeignKey(),
                }).ToList()
            };
        });
    }
    /// 
    /// 获取添加的实体信息
    /// 
    /// 
    /// 
    public static IEnumerable GetAdded(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added).Select(e =>
        {
            var currentObject = e.CurrentValues.ToObject();
            return new ChangeEntry
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.CurrentValues.EntityType.ClrType,
                ChangeProperties = e.CurrentValues.Properties.Select(p => new ChangePropertyInfo()
                {
                    PropertyInfo = p.PropertyInfo,
                    CurrentValue = p.PropertyInfo.GetValue(currentObject),
                    IsPrimaryKey = p.IsPrimaryKey(),
                    IsForeignKey = p.IsForeignKey(),
                }).ToList()
            };
        });
    }
    /// 
    /// 获取移除的实体信息
    /// 
    /// 
    /// 
    /// 
    public static IEnumerable GetRemoved(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted && e.Entity is T).Select(e =>
        {
            var originalObject = e.OriginalValues.ToObject();
            return new ChangeEntry
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.OriginalValues.EntityType.ClrType,
                ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo()
                {
                    PropertyInfo = p.PropertyInfo,
                    OriginalValue = p.PropertyInfo.GetValue(originalObject),
                    IsPrimaryKey = p.IsPrimaryKey(),
                    IsForeignKey = p.IsForeignKey(),
                }).ToList()
            };
        });
    }
    /// 
    /// 获取移除的实体信息
    /// 
    /// 
    /// 
    public static IEnumerable GetRemoved(this DbContext db)
    {
        return db.ChangeTracker.Entries().Where(e => e.State == EntityState.Deleted).Select(e =>
        {
            var originalObject = e.OriginalValues.ToObject();
            return new ChangeEntry
            {
                EntityState = e.State,
                Entity = e.Entity,
                EntityType = e.OriginalValues.EntityType.ClrType,
                ChangeProperties = e.OriginalValues.Properties.Select(p => new ChangePropertyInfo()
                {
                    PropertyInfo = p.PropertyInfo,
                    OriginalValue = p.PropertyInfo.GetValue(originalObject),
                    IsPrimaryKey = p.IsPrimaryKey(),
                    IsForeignKey = p.IsForeignKey(),
                }).ToList()
            };
        });
    }
    /// 
    /// 获取所有的变更信息
    /// 
    /// 
    /// 
    /// 
    public static IEnumerable GetAllChanges(this DbContext db)
    {
        return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db));
    }
    /// 
    /// 获取所有的变更信息
    /// 
    /// 
    /// 
    public static IEnumerable GetAllChanges(this DbContext db)
    {
        return GetChanges(db).Union(GetAdded(db)).Union(GetRemoved(db));
    }
}
public class ChangePropertyInfo
{
    /// 
    /// 属性
    /// 
    public PropertyInfo PropertyInfo { get; set; }
    /// 
    /// 原始值
    /// 
    public object OriginalValue { get; set; }
    /// 
    /// 新值
    /// 
    public object CurrentValue { get; set; }
    /// 
    /// 是否是主键
    /// 
    public bool IsPrimaryKey { get; set; }
    /// 
    /// 是否是外键
    /// 
    public bool IsForeignKey { get; set; }
}
public class ChangeEntry
{
    /// 
    /// 所属实体
    /// 
    public object Entity { get; set; }
    /// 
    /// 实体类型
    /// 
    public Type EntityType { get; set; }
    /// 
    /// 变更类型
    /// 
    public EntityState EntityState { get; set; }
    /// 
    /// 字段变更信息
    /// 
    public List ChangeProperties { get; set; }
}