using Microsoft.EntityFrameworkCore;
using SushiBarContracts.BindingModels;
using SushiBarContracts.SearchModels;
using SushiBarContracts.StoragesContracts;
using SushiBarContracts.ViewModels;
using SushiBarDatabaseImplement.Models;

namespace SushiBarDatabaseImplement.Implements
{
    public class SushiStorage : ISushiStorage
    {
        public SushiViewModel? Delete(SushiBindingModel model)
        {
            using var context = new SushiBarDatabase();

            var element = context.Sushi
                .Include(x => x.Components)
                .FirstOrDefault(rec => rec.Id == model.Id);

            if (element != null)
            {
                context.Sushi.Remove(element);
                context.SaveChanges();
                return element.GetViewModel;
            }

            return null;
        }

        public SushiViewModel? GetElement(SushiSearchModel model)
        {
            if (string.IsNullOrEmpty(model.SushiName) && !model.Id.HasValue)
            {
                return null;
            }

            using var context = new SushiBarDatabase();

            return context.Sushi
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .FirstOrDefault(x => (
                    !string.IsNullOrEmpty(model.SushiName) &&
                    x.SushiName == model.SushiName) ||
                    (model.Id.HasValue && x.Id == model.Id))
                ?.GetViewModel;
        }

        public List<SushiViewModel> GetFilteredList(SushiSearchModel model)
        {
            if (string.IsNullOrEmpty(model.SushiName))
            {
                return new();
            }

            using var context = new SushiBarDatabase();

            return context.Sushi
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .Where(x => x.SushiName.Contains(model.SushiName))
                .ToList()
                .Select(x => x.GetViewModel)
                .ToList();
        }

        public List<SushiViewModel> GetFullList()
        {
            using var context = new SushiBarDatabase();

            return context.Sushi
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .ToList().Select(x => x.GetViewModel)
                .ToList();
        }

        public SushiViewModel? Insert(SushiBindingModel model)
        {
            using var context = new SushiBarDatabase();

            var newSushi = Sushi.Create(context, model);

            if (newSushi == null)
            {
                return null;
            }

            context.Sushi.Add(newSushi);
            context.SaveChanges();

            return newSushi.GetViewModel;
        }

        public SushiViewModel? Update(SushiBindingModel model)
        {
            using var context = new SushiBarDatabase();
            using var transaction = context.Database.BeginTransaction();

            try {
                var sushi = context.Sushi.FirstOrDefault(rec => rec.Id == model.Id);

                if (sushi == null)
                {
                    return null;
                }

                sushi.Update(model);
                context.SaveChanges();
                sushi.UpdateComponents(context, model);
                transaction.Commit();

                return sushi.GetViewModel;
            }
            catch {
                transaction.Rollback();
                throw;
            }
        }
    }
}
