using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using AuditFieldSample.Datas;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.AspNetCore.Http;
using System.Threading;

namespace AuditFieldSample.Datas
{
    public class BloggingContext : DbContext
    {
        private readonly IHttpContextAccessor _httpContextAccessor;

        public BloggingContext(DbContextOptions<BloggingContext> options, IHttpContextAccessor httpContextAccessor) : base(options)
        {
            _httpContextAccessor = httpContextAccessor;
            Database.EnsureCreated();
        }

        protected override void OnModelCreating(ModelBuilder builder)
        {
            builder.Entity<Post>().Property(b => b.Title).HasMaxLength(20);
            builder.Entity<Post>().Property(b => b.Content).HasMaxLength(100);

            #region Example-2
            //builder.Entity<Post>().Property<string>("Modifier");
            //builder.Entity<Post>().Property<DateTime?>("Modified");
            #endregion

            builder.Entity<Post>().HasData(new Post { PostId = 1, Title = "First Title", Content = "First Content" });

            base.OnModelCreating(builder);
        }

        public DbSet<Post> Posts { get; set; }

        public override int SaveChanges()
        {
            OnBeforeSaveChanges();
            return base.SaveChanges();
        }

        public override Task<int> SaveChangesAsync(bool acceptAllChangesOnSuccess, CancellationToken cancellationToken = default)
        {
            OnBeforeSaveChanges();
            return base.SaveChangesAsync(acceptAllChangesOnSuccess, cancellationToken);
        }

        private void OnBeforeSaveChanges()
        {
            #region Example-1
            foreach (var auditableEntity in ChangeTracker.Entries<IAuditable>())
            {
                if (auditableEntity.State == EntityState.Modified)
                {
                    auditableEntity.Entity.Modifier = _httpContextAccessor.HttpContext.User.Identity.Name;
                    auditableEntity.Entity.Modified = DateTime.Now;
                }
            }
            #endregion

            #region Example-2
            //var modifiedEntries = ChangeTracker.Entries().Where(e => e.State == EntityState.Modified);

            //foreach (EntityEntry entry in modifiedEntries)
            //{
            //    var entityType = entry.Context.Model.FindEntityType(entry.Entity.GetType());

            //    var modifiedProperty = entityType.FindProperty("Modifier");
            //    var createdProperty = entityType.FindProperty("Modified");

            //    if (entry.State == EntityState.Modified && modifiedProperty != null)
            //    {
            //        entry.Property("Modified").CurrentValue = DateTime.Now;
            //    }

            //    if (entry.State == EntityState.Added && createdProperty != null)
            //    {
            //        entry.Property("Created").CurrentValue = DateTime.Now;
            //    }
            //}
            #endregion
        }
    }
}