using System.Collections.Generic;
using System.Linq;
using AsbCloudDb.Model;
using AsbCloudApp.Services;
using Mapster;
using Microsoft.EntityFrameworkCore;

namespace AsbCloudInfrastructure.Services
{
    public class CrudService<Tdto, TModel> : ICrudService<Tdto> 
        where TModel : class, AsbCloudDb.Model.IId
        where Tdto : AsbCloudApp.Data.IId
    {
        private readonly IAsbCloudDbContext context;
        private readonly DbSet<TModel> dbSet;

        public CrudService(IAsbCloudDbContext context)
        {
            this.context = context;
            dbSet = context.Set<TModel>();
        }

        public IEnumerable<Tdto> GetAll(System.Linq.Expressions.Expression<System.Func<object, bool>> predicate = null)
        {
            IQueryable<TModel> entities = dbSet;

            if (predicate is not null)
                entities = entities.Where(predicate).Cast<TModel>();

            var dto = entities.Adapt<Tdto>();
            return dto;
        }

        public Tdto Get(int id)
        {
            var entity = dbSet.FirstOrDefault(e => e.Id == id);

            var dto = entity.Adapt<Tdto>();
            return dto;
        }

        public Tdto Insert(Tdto newItem)
        {
            var newEntity = newItem.Adapt<TModel>();
            var dbEntity = dbSet.Add(newEntity);
            context.SaveChanges();
            return dbEntity.Entity.Adapt<Tdto>();
        }

        public IEnumerable<Tdto> InsertRange(IEnumerable<Tdto> newItems)
        {
            var newEntities = newItems.Adapt<IEnumerable<TModel>>();
            var dbEntities = new Microsoft.EntityFrameworkCore.ChangeTracking.EntityEntry<TModel>[newItems.Count()];

            for (int i = 0; i < dbEntities.Length; i++)
                dbEntities[i] = dbSet.Add(newEntities.ElementAt(i));

            context.SaveChanges();
            return dbEntities.Select(e => e.Entity.Adapt<Tdto>());
        }

        public Tdto Update(Tdto item)
        {
            var newEntity = item.Adapt<TModel>();
            var dbEntity = dbSet.Update(newEntity);
            context.SaveChanges();
            return dbEntity.Entity.Adapt<Tdto>();
        }

        public int Delete(int id)
        {
            var entity = dbSet.FirstOrDefault(e => e.Id == id);
            if (entity == default)
                return 0;
            dbSet.Remove(entity);
            return context.SaveChanges();
        }
    }

}