using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage;

namespace Netina.Repository.Repositories.UnitOfWork;

public class UnitOfWork(ApplicationContext applicationContext) : IUnitOfWork
{
    private IDbContextTransaction? _currentTransaction ;

    public async Task RollBackAsync()
    {
        if (_currentTransaction == null)
            throw new ArgumentNullException(nameof(_currentTransaction));
        await _currentTransaction.RollbackAsync();
    }
    public async Task CommitAsync()
    {
        if (_currentTransaction == null)
            throw new ArgumentNullException(nameof(_currentTransaction));
        await _currentTransaction.CommitAsync();
    }
    public async Task BeginTransaction()
    {
        _currentTransaction = await applicationContext.Database.BeginTransactionAsync();
    }
    public async Task SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        SetAuditables();
        await applicationContext.SaveChangesAsync(cancellationToken);
    }

    private void SetAuditables()
    {
        IEnumerable<EntityEntry<IApiEntity>> entries = applicationContext.ChangeTracker.Entries<IApiEntity>();
        foreach (EntityEntry<IApiEntity> entity in entries)
        {
            if (entity.State == EntityState.Added)
            {
                entity.Property(e=>e.CreatedAt)
                    .CurrentValue = DateTime.Now;
            }

            if (entity.State == EntityState.Modified)
            {
                entity.Property(e => e.ModifiedAt)
                    .CurrentValue = DateTime.Now;
            }

            if (entity.State == EntityState.Deleted)
            {
                entity.Property(e => e.RemovedAt)
                    .CurrentValue = DateTime.Now;
                entity.Property(e => e.IsRemoved)
                    .CurrentValue = true;
                entity.State = EntityState.Modified;
            }
        }
    }
}