using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Persistence.Models;
using System.Linq;

namespace Persistence.Repositories;
//public abstract class AbstractChangeLogRepository<TEntity, TChangeLogDto, TDto> : IChangeLogRepository<TDto, TChangeLogDto>
//    where TDto : class, new()
//    where TEntity : class, IChangeLogAbstract
//    where TChangeLogDto : ChangeLogDto<TDto>
//{
//    private readonly DbContext dbContext;

//    protected AbstractChangeLogRepository(DbContext dbContext)
//    {
//        this.dbContext = dbContext;
//    }

//    public abstract TEntity Convert(TDto entity);
//    public async Task<int> Clear(int idUser,CancellationToken token)
//    {
//        throw new NotImplementedException();

//        //var updateTime = DateTimeOffset.UtcNow;

//        ////todo
//        //var query = BuildQuery(request);
//        //query = query.Where(e => e.Obsolete == null);

//        //var entitiesToDelete = await query.ToArrayAsync(token);

//        //foreach (var entity in entitiesToDelete)
//        //{
//        //    entity.IdState = IChangeLogAbstract.IdCleared;
//        //    entity.Obsolete = updateTime;
//        //    entity.IdEditor = idUser;
//        //}

//        //var result = await SaveChangesWithExceptionHandling(token);
//        //return result;
//    }

//    public async Task<int> ClearAndInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
//    {
//        var result = 0;
//        using var transaction = await dbContext.Database.BeginTransactionAsync(token);
//        try
//        {
//            result += await Clear(idUser, token);
//            result += await InsertRangeWithoutTransaction(idUser, dtos, token);

//            await transaction.CommitAsync(token);
//            return result;
//        }
//        catch
//        {
//            await transaction.RollbackAsync(token);
//            throw;
//        }
//    }

//    public Task<IEnumerable<TDto>> GetCurrent(DateTimeOffset moment, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public Task<IEnumerable<DateOnly>> GetDatesChange(CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public Task<IEnumerable<TDto>> GetGtDate(DateTimeOffset date, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public async Task<int> AddRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
//    {
//        using var transaction = dbContext.Database.BeginTransaction();
//        try
//        {
//            var result = await InsertRangeWithoutTransaction(idUser, dtos, token);
//            await transaction.CommitAsync(token);
//            return result;
//        }
//        catch
//        {
//            await transaction.RollbackAsync(token);
//            throw;
//        }
//    }

//    protected abstract DatabaseFacade GetDataBase();

//    public Task<int> MarkAsDeleted(int idUser, IEnumerable<int> ids, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public Task<int> UpdateOrInsertRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public Task<int> UpdateRange(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    public Task<IEnumerable<TChangeLogDto>> GetChangeLogForDate(DateTimeOffset? updateFrom, CancellationToken token)
//    {
//        throw new NotImplementedException();
//    }

//    private async Task<int> InsertRangeWithoutTransaction(int idUser, IEnumerable<TDto> dtos, CancellationToken token)
//    {
//        var result = 0;
//        if (dtos.Any())
//        {
//            var entities = dtos.Select(Convert);
//            var creation = DateTimeOffset.UtcNow;
//            var dbSet = dbContext.Set<TEntity>();
//            foreach (var entity in entities)
//            {
//                entity.Id = default;
//                entity.IdAuthor = idUser;
//                entity.Creation = creation;
//                entity.IdState = IChangeLogAbstract.IdStateActual;
//                entity.IdEditor = null;
//                entity.IdPrevious = null;
//                entity.Obsolete = null;
//                dbSet.Add(entity);
//            }

//            result += await SaveChangesWithExceptionHandling(token);
//        }

//        return result;
//    }

//    private async Task<int> SaveChangesWithExceptionHandling(CancellationToken token)
//    {
//        var result = await dbContext.SaveChangesAsync(token);
//        return result;
//        //try
//        //{
//        //    var result = await dbContext.SaveChangesAsync(token);
//        //    return result;
//        //}
//        //catch (DbUpdateException ex)
//        //{
//        //    if (ex.InnerException is PostgresException pgException)
//        //        TryConvertPostgresExceptionToValidateException(pgException);
//        //    throw;
//        //}
//    }



//    //private static void TryConvertPostgresExceptionToValidateException(PostgresException pgException)
//    //{
//    //    if (pgException.SqlState == PostgresErrorCodes.ForeignKeyViolation)
//    //        throw new ArgumentInvalidException("dtos", pgException.Message + "\r\n" + pgException.Detail);
//    //}
//}