using BarContracts.BindingModels;
using BarContracts.SearchModels;
using BarContracts.StoragesContracts;
using BarContracts.ViewModels;
using BarDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;

namespace BarDatabaseImplement.Implements
{
    public class CocktailStorage : ICocktailStorage
    {
        public List<CocktailViewModel> GetFullList()
        {
            using var Context = new BarDatabase();
            return Context.Cocktails
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
        }

        public List<CocktailViewModel> GetFilteredList(CocktailSearchModel Model)
        {
            if (string.IsNullOrEmpty(Model.CocktailName))
                return new();

            using var Context = new BarDatabase();

            return Context.Cocktails
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .Where(x => x.CocktailName.Contains(Model.CocktailName))
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
        }

        public CocktailViewModel? GetElement(CocktailSearchModel Model)
        {
            if (string.IsNullOrEmpty(Model.CocktailName) && !Model.Id.HasValue)
                return null;

            using var Context = new BarDatabase();

            return Context.Cocktails
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .FirstOrDefault(x => (!string.IsNullOrEmpty(Model.CocktailName) && x.CocktailName == Model.CocktailName) ||
                (Model.Id.HasValue && x.Id == Model.Id))?
                .GetViewModel;
        }

        public CocktailViewModel? Insert(CocktailBindingModel Model)
        {
            using var Context = new BarDatabase();

            var NewCocktail = Cocktail.Create(Context, Model);
            if (NewCocktail == null)
                return null;

            Context.Cocktails.Add(NewCocktail);
            Context.SaveChanges();

            return NewCocktail.GetViewModel;
        }

        public CocktailViewModel? Update(CocktailBindingModel Model)
        {
            using var Context = new BarDatabase();

            using var Transaction = Context.Database.BeginTransaction();
            try
            {
                var Cocktail = Context.Cocktails.FirstOrDefault(rec => rec.Id == Model.Id);

                if (Cocktail == null)
                    return null;

                Cocktail.Update(Model);
                Context.SaveChanges();
                Cocktail.UpdateComponents(Context, Model);

                Transaction.Commit();
                return Cocktail.GetViewModel;
            }
            catch
            {
                Transaction.Rollback();
                throw;
            }
        }
        public CocktailViewModel? Delete(CocktailBindingModel Model)
        {
            using var Context = new BarDatabase();

            var Cocktail = Context.Cocktails
                .Include(x => x.Components)
                .FirstOrDefault(rec => rec.Id == Model.Id);

            if (Cocktail == null)
                return null;

            Context.Cocktails.Remove(Cocktail);
            Context.SaveChanges();
            return Cocktail.GetViewModel;
        }
    }
}
