using GiftShopContracts.BindingModels;
using GiftShopContracts.SearchModels;
using GiftShopContracts.StoragesContracts;
using GiftShopContracts.ViewModels;
using GiftShopDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;

namespace GiftShopDatabaseImplement.Implements
{
    public class GiftStorage : IGiftStorage
    {
        public List<GiftViewModel> GetFullList()
        {
            using var context = new GiftShopDatabase();
            return context.Gifts
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
        }
        
        public List<GiftViewModel> GetFilteredList(GiftSearchModel model)
        {
            if (string.IsNullOrEmpty(model.GiftName))
            {
                return new();
            }
            using var context = new GiftShopDatabase();
            return context.Gifts
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .Where(x => x.GiftName.Contains(model.GiftName))
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
        }
        
        public GiftViewModel? GetElement(GiftSearchModel model)
        {
            if (string.IsNullOrEmpty(model.GiftName) &&
            !model.Id.HasValue)
            {
                return null;
            }
            using var context = new GiftShopDatabase();
            return context.Gifts
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .FirstOrDefault(x => (!string.IsNullOrEmpty(model.GiftName) &&
            x.GiftName == model.GiftName) ||  (model.Id.HasValue && x.Id ==  model.Id))
            ?.GetViewModel;
        }
        
        public GiftViewModel? Insert(GiftBindingModel model)
        {
            using var context = new GiftShopDatabase();
            var newGift = Gift.Create(context, model);
            if (newGift == null)
            {
                return null;
            }
            context.Gifts.Add(newGift);
            context.SaveChanges();
            return newGift.GetViewModel;
        }
        
        public GiftViewModel? Update(GiftBindingModel model)
        {
            using var context = new GiftShopDatabase();
            using var transaction = context.Database.BeginTransaction();
            try
            {
                var gift = context.Gifts.FirstOrDefault(rec => rec.Id == model.Id);
                if (gift == null)
                {
                    return null;
                }
                gift.Update(model);
                context.SaveChanges();
                gift.UpdateComponents(context, model);
                transaction.Commit();
                return gift.GetViewModel;
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }
        
        public GiftViewModel? Delete(GiftBindingModel model)
        {
            using var context = new GiftShopDatabase();
            var element = context.Gifts
                .Include(x => x.Components)
                .FirstOrDefault(rec => rec.Id == model.Id);
            if (element != null)
            {
                context.Gifts.Remove(element);
                context.SaveChanges();
                return element.GetViewModel;
            }
            return null;
        }
    }
}
