using ComputerHardwareStoreContracts.BindingModels;
using ComputerHardwareStoreContracts.SearchModels;
using ComputerHardwareStoreContracts.StorageContracts;
using ComputerHardwareStoreContracts.ViewModels;
using ComputerHardwareStoreDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;

namespace ComputerHardwareStoreDatabaseImplement.Implements
{
    public class BuildStorage : IBuildStorage
    {
        public List<BuildViewModel> GetFullList()
        {
            using var context = new ComputerHardwareStoreDBContext();
            return context.Builds
                .Include(b => b.Comments)
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .Include(b => b.Vendor)
                .Select(b => b.GetViewModel)
                .ToList();
        }

        public List<BuildViewModel> GetFilteredList(BuildSearchModel model)
        {
            if (string.IsNullOrEmpty(model.Name))
            {
                return new();
            }
            using var context = new ComputerHardwareStoreDBContext();
            return context.Builds
                // только те, что созданы пользователем
                .Include(b => b.Vendor)
                .Where(b => b.Vendor.Id == model.VendorId
                // если есть хотя бы 1 общий компонент с товарами
                && !model.ProductId.HasValue || b.Components.FirstOrDefault(
                    c => c.Component.ProductComponents.FirstOrDefault(
                        p => p.ProductId == model.ProductId)
                    != null)
                != null)
                // вместе с комментами
                .Include(b => b.Comments)
                // вместе с компонентами
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .Select(b => b.GetViewModel)
                .ToList();
        }

        public BuildViewModel? GetElement(BuildSearchModel model)
        {
            if (string.IsNullOrEmpty(model.Name) && !model.Id.HasValue)
            {
                return null;
            }
            using var context = new ComputerHardwareStoreDBContext();
            return context.Builds
                .Include(b => b.Vendor)
                .Where(b => b.Vendor.Id == model.VendorId)
                .Include(b => b.Comments)
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .FirstOrDefault(b =>
                (!string.IsNullOrEmpty(model.Name) && b.Name == model.Name) ||
                (model.Id.HasValue && b.Id == model.Id))?
                .GetViewModel;
        }        

        public BuildViewModel? Insert(BuildBindingModel model)
        {
            using var context = new ComputerHardwareStoreDBContext();
            var newBuild = Build.Create(context, model);
            if (newBuild == null)
            {
                return null;
            }
            context.Builds.Add(newBuild);
            context.SaveChanges();
            return context.Builds
                .Include(b => b.Vendor)
                .Include(b => b.Comments)
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .FirstOrDefault(p => p.Id == newBuild.Id)?
                .GetViewModel;
        }

        public BuildViewModel? Update(BuildBindingModel model)
        {
            using var context = new ComputerHardwareStoreDBContext();
            var build = context.Builds
                .Include(b => b.Comments)
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .Include(b => b.Vendor)
                .Where(b => b.Vendor.Id == model.Vendor.Id)
                .FirstOrDefault(p => p.Id == model.Id);
            if (build == null)
            {
                return null;
            }
            context.Update(model);
            context.SaveChanges();
            return build.GetViewModel;
        }
        public BuildViewModel? Delete(BuildBindingModel model)
        {
            using var context = new ComputerHardwareStoreDBContext();
            var build = context.Builds
                .Include(b => b.Comments)
                .Include(b => b.Components)
                .ThenInclude(b => b.Component)
                .Include(b => b.Vendor)
                .Where(b => b.Vendor.Id == model.Vendor.Id)
                .FirstOrDefault(p => p.Id == model.Id);
            if (build == null)
            {
                return null;
            }
            context.Builds.Remove(build);
            context.SaveChanges();
            return build.GetViewModel;
        }
    }
}