using Domains;
using Infrastructure.Database.GeneralExceptions;
using Microsoft.EntityFrameworkCore;
namespace Infrastructure.Database.Generic
{
    /// Generic repository pattern
    /// 
    /// 
    /// Type of entity
    /// Should be inherited to create typed repositories
    public abstract class GenericRepository(IGenericReader reader, IGenericWriter writer, IUnitOfWork unitOfWork) : IGenericRepository
        where T : class, IEntity
    {
        /// 
        public async Task> GetAllAsync(CancellationToken cancellationToken)
            => await LoadDomain().ToListAsync(cancellationToken);
        /// 
        public async Task GetOneAsync(Guid id, CancellationToken cancellationToken)
        {
            var result = await LoadDomain().SingleOrDefaultAsync(a => a.Id == id, cancellationToken);
            return result ?? throw new EntityNotFoundException(id);
        }
        /// 
        public async Task AddAsync(T entity, CancellationToken cancellationToken)
            => await writer.AddAsync(entity, cancellationToken);
        /// 
        public async Task UpdateAsync(T entity, CancellationToken cancellationToken)
        {
            await GetOneAsync(entity.Id, cancellationToken);
            writer.Update(entity);
        }
        /// 
        public void Remove(T entity)
        {
            writer.Remove(entity);
        }
        /// 
        public async Task SaveAsync(CancellationToken cancellationToken)
            => await unitOfWork.SaveAsync(cancellationToken);
        /// Should be overriden to load navigation properties of entity
        protected virtual IQueryable LoadDomain()
        {
            return reader.GetAll();
        }
    }
}