using Core.Entities.Abstract;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Core.DataAccess.EntityFramework
{
    public class EfEntityRepositoryBase<TEntity, TContext> : IEntityRepository<TEntity>
        where TEntity : class, IEntity, new()
        where TContext : DbContext, new()
    {
        public async Task<TEntity?> Add(TEntity entity)
        {
            using (TContext context = new TContext())
            {
                await context.Set<TEntity>().AddAsync(entity);
                await context.SaveChangesAsync();
            }
            return entity;
        }

        public async Task Delete(TEntity entity)
        {
            using (TContext context = new TContext())
            {
                context.Set<TEntity>().Entry(entity).State = EntityState.Deleted;
                await context.SaveChangesAsync();
            }
        }

        public async Task<TEntity?> Get(Expression<Func<TEntity, bool>> expr)
        {
            using (TContext context = new TContext())
            {
                return await context.Set<TEntity>().SingleOrDefaultAsync(expr);
            }
        }

        public async Task<List<TEntity>> GetAll(Expression<Func<TEntity, bool>>? expr=null)
        {
            using (TContext context = new TContext())
            {
                return expr == null 
                    ? await context.Set<TEntity>().ToListAsync()
                    : await context.Set<TEntity>().Where(expr).ToListAsync();
            }
        }

        public async Task<TEntity?> Update(TEntity entity)
        {
            using (TContext context = new TContext())
            {
                context.Set<TEntity>().Entry(entity).State = EntityState.Modified;
                await context.SaveChangesAsync();
            }
            return entity;
        }
    }
}
