using ApplicationLayer.InfrastructureServicesInterfaces;
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) : IGenericRepository
    where T : class, IEntity
{
    /// 
    public async Task> GetAllAsync(CancellationToken cancellationToken)
        => await LoadDomain().ToListAsync(cancellationToken);
    /// 
    public async Task GetByIdAsync(Guid id, CancellationToken cancellationToken)
    {
        var result = await LoadDomain().SingleOrDefaultAsync(a => a.Id == id, cancellationToken);
        return result ?? throw new EntityNotFoundByIdException(id);
    }
    /// 
    public async Task AddAsync(T entity, CancellationToken cancellationToken)
        => await writer.AddAsync(entity, cancellationToken);
    /// 
    public async Task UpdateAsync(T entity, CancellationToken cancellationToken)
    {
        await GetByIdAsync(entity.Id, cancellationToken);
        writer.Update(entity);
    }
    /// 
    public void Remove(T entity)
    {
        writer.Remove(entity);
    }
    /// Should be overriden to load navigation properties of entity
    protected virtual IQueryable LoadDomain()
    {
        return reader.GetAll();
    }
}