using ComputerShopContracts.BindingModels;
using ComputerShopContracts.SearchModels;
using ComputerShopContracts.StorageContracts;
using ComputerShopContracts.ViewModels;
using ComputerShopDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComputerShopDatabaseImplement.Implements
{
    public class OrderStorage : IOrderStorage
    {
        public OrderViewModel? Delete(OrderBindingModel model)
        {
            using var context = new ComputerShopDatabase();
            var element = context.Orders.FirstOrDefault(rec => rec.Id ==
            model.Id);
            if (element != null)
            {
                context.Orders.Remove(element);
                context.SaveChanges();
                return element.GetViewModel;
            }
            return null;
        }

        public OrderViewModel? GetElement(OrderSearchModel model)
        {
            if (!model.Id.HasValue)
            {
                return null;
            }
            using var context = new ComputerShopDatabase();
            return context.Orders
            .Include(x => x.Assemblies)
            .ThenInclude(x => x.Assembly)
            .FirstOrDefault(x => (model.Id.HasValue && x.Id == model.Id))?
            .GetViewModel;
        }

        public List<OrderViewModel> GetFilteredList(OrderSearchModel model)
        {
            
            if (!model.ClientId.HasValue)
			{
				return new();
			}
			using var context = new ComputerShopDatabase();
			if (model.DateFrom.HasValue & model.DateTo.HasValue)
            {
                return context.Orders
                .Where(x => x.DateCreate >= model.DateFrom && x.DateCreate <= model.DateTo)
                .Include(x => x.OrderAssemblies).Include(x => x.Client)
                .Select(x => x.GetViewModel)
                .ToList();
            }

			return context.Orders
				.Include(x => x.Assemblies)
				.ThenInclude(x => x.Assembly)
				.Where(x => x.ClientId == model.ClientId)
				.Select(x => x.GetViewModel)
				.ToList();
            
		}

        public List<OrderViewModel> GetFullList()
        {
            using var context = new ComputerShopDatabase();
			return context.Orders
				.Include(x => x.OrderAssemblies).Include(x => x.Client)
				.Select(x => x.GetViewModel)
				.ToList();
		}

        public OrderViewModel? Insert(OrderBindingModel model)
        {
			using var context = new ComputerShopDatabase();
			var newOrder = Order.Create(context, model);

            if (newOrder == null)
            {
                return null;
            }
            context.Orders.Add(newOrder);
            context.SaveChanges();
            return newOrder.GetViewModel;
		}

        public OrderViewModel? Update(OrderBindingModel model)
        {
            using var context = new ComputerShopDatabase();
			using var transaction = context.Database.BeginTransaction();
			var order = context.Orders.FirstOrDefault(x => x.Id == model.Id);
			try
			{
				var product = context.Orders.FirstOrDefault(rec =>
				rec.Id == model.Id);
				if (product == null)
				{
					return null;
				}
				product.Update(model);
				context.SaveChanges();
				product.UpdateAssemblies(context, model);
				transaction.Commit();
				return product.GetViewModel;
			}
			catch
			{
				transaction.Rollback();
				throw;
			}
		}

        public List<AssemblyViewModel>? GetAssembliesByOrder(OrderSearchModel model)
        {
			using var context = new ComputerShopDatabase();
            var order_components = context.OrderAssemblies.FirstOrDefault(x => x.OrderId == model.Id);
			if (order_components == null)
			{
				return null;
			}
			var components = context.Assemblies.Where(x => x.Id == order_components.AssemblyId)
                .Include(x => x.Components)
                .ThenInclude(x => x.Component)
                .Select(x => x.GetViewModel)
				.ToList();
			if (components.Count < 1)
			{
				return null;
			}
			return components;
		}
    }
}
