using System.Linq.Expressions;
using DataLayer.Interfaces;
using Domain;
using Microsoft.EntityFrameworkCore;

namespace DataLayer;

public class AbstractRepository<T> : IAbstractRepository<T> where T : BaseEntity
{
    #region Fields

    private readonly DeathwatchDbContext _deathwatchDbContext;
    private readonly DbSet<T> _entities;

    #endregion

    public AbstractRepository(DeathwatchDbContext deathwatchDbContext)
    {
        _deathwatchDbContext = deathwatchDbContext;
        _entities = _deathwatchDbContext.Set<T>();
    }

    #region Public Methods

    public async Task<T> GetById(int id)
    {
        return await _entities.FindAsync(id);
    }

    public async Task<T> FirstOrDefault(Expression<Func<T, bool>> predicate)
    {
        var entity = await _entities.FirstOrDefaultAsync(predicate);
        return entity;
    }

    public async Task Add(T entity)
    {
        await _entities.AddAsync(entity);
        await _deathwatchDbContext.SaveChangesAsync();
    }

    public Task Update(T entity)
    {
        // In case AsNoTracking is used
        _deathwatchDbContext.Entry(entity).State = EntityState.Modified;
        return _deathwatchDbContext.SaveChangesAsync();
    }

    public Task Remove(T entity)
    {
        _entities.Remove(entity);
        return _deathwatchDbContext.SaveChangesAsync();
    }

    public async Task<IEnumerable<T>> GetAll()
    {
        var entries = await _entities.ToListAsync();
        return entries;
    }

    public async Task<IEnumerable<T>> GetWhere(Expression<Func<T, bool>> predicate)
    {
        return await _entities.Where(predicate).ToListAsync();
    }

    public Task<int> CountAll()
    {
        return _entities.CountAsync();
    }

    public Task<int> CountWhere(Expression<Func<T, bool>> predicate)
    {
        return _entities.CountAsync(predicate);
    }

    #endregion
}