using CanteenContracts.BindingModels;
using CanteenContracts.SearchModel;
using CanteenContracts.StoragesContracts;
using CanteenContracts.View;
using CanteenDatabaseImplement.Models;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CanteenDatabaseImplement.Implements
{
    public class OrderStorage : IOrderStorage
    {
        public OrderViewModel? GetElement(OrderSearchModel model)
        {
            if (!model.Id.HasValue)
            {
                return null;
            }

            using var context = new CanteenDatabase();

            return context.Orders
                .Include(x => x.Cooks)
                .ThenInclude(x => x.Cook)
                .FirstOrDefault(x => model.Id.HasValue && x.Id == model.Id)?.GetViewModel;
        }

        public List<OrderViewModel> GetFilteredList(OrderSearchModel model)
        {
            if (!model.VisitorId.HasValue)
            {
                return new();
            }

            using var context = new CanteenDatabase();

            return context.Orders
                .Include(x => x.Cooks)
                .ThenInclude(x => x.Cook)
                .Where(x => model.VisitorId.HasValue && (model.VisitorId == x.VisitorId)).Select(x => x.GetViewModel).ToList();
        }

        public List<OrderViewModel> GetFullList()
        {
            using var context = new CanteenDatabase();
            return context.Orders
                .Include(x => x.Cooks)
                .ThenInclude(x => x.Cook)
                .Select(x => x.GetViewModel).ToList();
        }

        public OrderViewModel? Insert(OrderBindingModel model)
        {
            var newOrder = Order.Create(model);
            if (newOrder == null)
            {
                return null;
            }

            using var context = new CanteenDatabase();

            context.Orders.Add(newOrder);
            context.SaveChanges();

            return newOrder.GetViewModel;
        }

        public OrderViewModel? Update(OrderBindingModel model)
        {
            using var context = new CanteenDatabase();

            var client = context.Orders.FirstOrDefault(x => x.Id == model.Id);
            if (client == null)
            {
                return null;
            }

            client.Update(model);
            context.SaveChanges();

            return client.GetViewModel;
        }

        public OrderViewModel? Delete(OrderBindingModel model)
        {
            using var context = new CanteenDatabase();

            var client = context.Orders.FirstOrDefault(x => x.Id == model.Id);
            if (client == null)
            {
                return null;
            }

            context.Orders.Remove(client);
            context.SaveChanges();

            return client.GetViewModel;
        }

        public bool AddCook(OrderCookBindingModel orderCook)
        {
            using var context = new CanteenDatabase();
            using var transaction = context.Database.BeginTransaction();
            try
            {
                if (context.OrderCook.FirstOrDefault(rec => rec.OrderId == orderCook.OrderId && rec.CookId == orderCook.CookId) != null)
                {
                    return false;
                }
                else
                {
                    context.OrderCook.Add(new OrderCook { OrderId = orderCook.OrderId, CookId = orderCook.CookId });
                }
                context.SaveChanges();
                transaction.Commit();
                return true;
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }

        public bool AddTableware(OrderTablewareBindingModel model)
        {
            using var context = new CanteenDatabase();
            using var transaction = context.Database.BeginTransaction();
            try
            {
                if (context.Orders.FirstOrDefault(rec => rec.Id == model.OrderId && rec.TablewareId == model.TablewareId) != null)
                {
                    var order = context.Orders.FirstOrDefault(rec => rec.Id == model.OrderId && rec.TablewareId == model.TablewareId);
                    order.CountTablewares = model.CountTablewares;
                }
                else
                {
                    var order = context.Orders.FirstOrDefault(rec => rec.Id == model.OrderId);
                    order.TablewareId = model.TablewareId;
                    order.CountTablewares = model.CountTablewares;
                }
                context.SaveChanges();
                transaction.Commit();
                return true;
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
        }
    }
}
