using Microsoft.EntityFrameworkCore;
using PlumbingRepairContracts.BindingModels;
using PlumbingRepairContracts.SearchModels;
using PlumbingRepairContracts.StoragesContracts;
using PlumbingRepairContracts.ViewModels;
using PlumbingRepairDatabaseImplement.Models;

namespace PlumbingRepairDatabaseImplement.Implements
{
    public class WorkStorage : IWorkStorage
    {
        public List<WorkViewModel> GetFullList()
        {
            using var context = new PlumbingRepairDataBase();

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

        public List<WorkViewModel> GetFilteredList(WorkSearchModel model)
        {
            if (string.IsNullOrEmpty(model.WorkName))
            {
                return new();
            }

            using var context = new PlumbingRepairDataBase();

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

        public WorkViewModel? GetElement(WorkSearchModel model)
        {
            if (string.IsNullOrEmpty(model.WorkName) && !model.Id.HasValue)
            {
                return null;
            }

            using var context = new PlumbingRepairDataBase();

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

        public WorkViewModel? Insert(WorkBindingModel model)
        {
            using var context = new PlumbingRepairDataBase();

            var newWork = Work.Create(context, model);

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

            context.Works.Add(newWork);
            context.SaveChanges();

            return newWork.GetViewModel;
        }

        public WorkViewModel? Update(WorkBindingModel model)
        {
            using var context = new PlumbingRepairDataBase();

            using var transaction = context.Database.BeginTransaction();

            try
            {
                var package = context.Works.FirstOrDefault(rec => rec.Id == model.Id);

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

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

                return package.GetViewModel;
            }
            catch
            {
                transaction.Rollback();

                throw;
            }
        }

        public WorkViewModel? Delete(WorkBindingModel model)
        {
            using var context = new PlumbingRepairDataBase();

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

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

            return null;
        }
    }
}
