using ERPCore.Infra.Persistence;
using ERPCore.Repositories.Interfaces;
using Microsoft.EntityFrameworkCore;

namespace ERPCore.Repositories;

/// <summary>
/// Default <see cref="IRepository{T}"/> implementation over <see cref="ErpDbContext"/>.
/// Registered open-generically so any entity gets a repository for free; specialise
/// by deriving when an aggregate needs bespoke queries.
/// </summary>
public class Repository<T> : IRepository<T> where T : class
{
    protected readonly ErpDbContext Db;
    protected readonly DbSet<T> Set;

    public Repository(ErpDbContext db)
    {
        Db = db;
        Set = db.Set<T>();
    }

    public virtual async Task<T?> GetByIdAsync(object id, CancellationToken ct = default)
        => await Set.FindAsync(new[] { id }, ct);

    public virtual async Task<IReadOnlyList<T>> ListAsync(CancellationToken ct = default)
        => await Set.AsNoTracking().ToListAsync(ct);

    public IQueryable<T> Query() => Set.AsQueryable();

    public virtual async Task AddAsync(T entity, CancellationToken ct = default)
        => await Set.AddAsync(entity, ct);

    public virtual void Update(T entity) => Set.Update(entity);

    public virtual void Remove(T entity) => Set.Remove(entity);
}
