public async Task <ActionResult> DeleteMealPhoto(int id, int photoId)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            var photo = meal.Photos.SingleOrDefault(x => x.Id == photoId);

            if (photo != null)
            {
                if (photo.IsMain)
                {
                    return(BadRequest(new ApiResponse(400,
                                                      "You cannot delete the main photo")));
                }

                _photoService.DeleteFromDisk(photo);
            }
            else
            {
                return(BadRequest(new ApiResponse(400, "Photo does not exist")));
            }

            meal.RemovePhoto(photoId);

            _unitOfWork.Repository <Meal>().Update(meal);

            var result = await _unitOfWork.Complete();

            if (result <= 0)
            {
                return(BadRequest(new ApiResponse(400, "Problem adding meal product")));
            }

            return(Ok());
        }
        public async Task <ActionResult <Pagination <MealToReturnDto> > > GetMeals([FromQuery] MealSpecParams mealParams)
        {
            var spec = new MealsWithTypesAndMenusSpecification(mealParams);

            var countSpec = new MealWithFiltersForCountSpecification(mealParams);

            var totalItems = await _unitOfWork.Repository <Meal>().CountAsync(countSpec);

            var meals = await _unitOfWork.Repository <Meal>().ListAsync(spec);

            var mealsToReturn = new List <Meal>();

            foreach (var meal in meals)
            {
                if (meal.Stock > 0)
                {
                    mealsToReturn.Add(meal);
                }
                if (meal.Stock < 1)
                {
                    totalItems--;
                }
            }

            var data = _mapper.Map <IReadOnlyList <Meal>, IReadOnlyList <MealToReturnDto> >(mealsToReturn);

            return(Ok(new Pagination <MealToReturnDto>(mealParams.PageIndex, mealParams.PageSize, totalItems, data)));
        }
        public async Task <ActionResult <MealToReturnDto> > AddMealPhoto(int id, [FromForm] MealPhotoDto photoDto)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            if (photoDto.Photo.Length > 0)
            {
                var photo = await _photoService.SaveToDiskAsync(photoDto.Photo);

                if (photo != null)
                {
                    meal.AddPhoto(photo.PictureUrl, photo.FileName);

                    _unitOfWork.Repository <Meal>().Update(meal);

                    var result = await _unitOfWork.Complete();

                    if (result <= 0)
                    {
                        return(BadRequest(new ApiResponse(400, "Problem adding photo meal")));
                    }
                }
                else
                {
                    return(BadRequest(new ApiResponse(400, "problem saving photo to disk")));
                }
            }

            return(_mapper.Map <Meal, MealToReturnDto>(meal));
        }
        public async Task <ActionResult <Pagination <MealToReturnDto> > > GetMealsForManager([FromQuery] MealSpecParams mealParams)
        {
            var spec  = new MealsWithTypesAndMenusSpecification(mealParams);
            var email = HttpContext.User.RetrieveEmailFromPrincipal();
            var user  = await _userManager.FindByEmailAsync(email);

            var restaurants = await _unitOfWork.Repository <Restaurant>().ListAllAsync();

            foreach (var restaurant in restaurants)
            {
                if (restaurant.Name == user.DisplayName)
                {
                    mealParams.RestaurantId = restaurant.Id;
                }
            }
            ;

            var countSpec = new MealWithFiltersForCountSpecification(mealParams);

            var totalItems = await _unitOfWork.Repository <Meal>().CountAsync(countSpec);

            var meals = await _unitOfWork.Repository <Meal>().ListAsync(spec);

            var data = _mapper.Map <IReadOnlyList <Meal>, IReadOnlyList <MealToReturnDto> >(meals);

            return(Ok(new Pagination <MealToReturnDto>(mealParams.PageIndex, mealParams.PageSize, totalItems, data)));
        }
        public async Task <ActionResult <MealToReturnDto> > GetMeal(int id)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);

            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            if (meal == null)
            {
                return(NotFound(new ApiResponse(404)));
            }

            return(_mapper.Map <Meal, MealToReturnDto>(meal));
        }
        public async Task <ActionResult> DeleteMealIngrediant(int id, int ingrediantId)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            meal.RemoveIngrediant(ingrediantId);

            _unitOfWork.Repository <Meal>().Update(meal);

            var result = await _unitOfWork.Complete();

            if (result <= 0)
            {
                return(BadRequest(new ApiResponse(400, "Problem adding meal product")));
            }

            return(Ok());
        }
        public async Task <ActionResult <MealToReturnDto> > UpdateMealIngrediant(int id, IngrediantToReturnDto ingrediantDto, int ingrediantId)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            meal.UpdateIngrediant(ingrediantDto.Name, ingrediantDto.Price, ingrediantDto.Quantity, ingrediantId);

            _unitOfWork.Repository <Meal>().Update(meal);

            var result = await _unitOfWork.Complete();

            if (result <= 0)
            {
                return(BadRequest(new ApiResponse(400, "Problem updating ingrediant")));
            }


            return(_mapper.Map <Meal, MealToReturnDto>(meal));
        }
        public async Task <ActionResult <MealToReturnDto> > SetMainPhoto(int id, int photoId)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            if (meal.Photos.All(x => x.Id != photoId))
            {
                return(NotFound());
            }

            meal.SetMainPhoto(photoId);

            _unitOfWork.Repository <Meal>().Update(meal);

            var result = await _unitOfWork.Complete();

            if (result <= 0)
            {
                return(BadRequest(new ApiResponse(400, "Problem adding meal product")));
            }

            return(_mapper.Map <Meal, MealToReturnDto>(meal));
        }
        public async Task <ActionResult> DeleteMeal(int id)
        {
            var spec = new MealsWithTypesAndMenusSpecification(id);
            var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(spec);

            foreach (var photo in meal.Photos)
            {
                if (meal.Id > 18)
                {
                    _photoService.DeleteFromDisk(photo);
                }
            }

            _unitOfWork.Repository <Meal>().Delete(meal);

            var result = await _unitOfWork.Complete();

            if (result <= 0)
            {
                return(BadRequest(new ApiResponse(400, "Problem deleting meal")));
            }

            return(Ok());
        }
        public async Task <Order> CreateOrderAsync(string buyerEmail, int deliveryMethodId, string basketId, Address shippingAddress, bool paymentMethod, DateTimeOffset shippingDate)
        {
            // get basket
            var basket = await _basketRepo.GetBasketAsync(basketId);

            // get items from meal repo
            var items = new List <OrderItem>();

            foreach (var item in basket.Items)
            {
                // Get meal - but just for Id since it won't grab photos
                var mealItem = await _unitOfWork.Repository <Meal>().GetByIdAsync(item.Id);

                // Create Spec cause we need to get Meals with Photos or Photo is null when viewed in Orders
                var mealspec = new MealsWithTypesAndMenusSpecification(mealItem.Id);
                // Get meal with Photos and other entitys
                var meal = await _unitOfWork.Repository <Meal>().GetEnitityWithSpec(mealspec);

                // Update Stock
                meal.Stock -= item.Quantity;
                _unitOfWork.Repository <Meal>().Update(meal);
                // Create Item Ordered
                var itemOrdered = new MealItemOrdered(meal.Id, meal.Name, meal.Photos.FirstOrDefault(x => x.IsMain)?.PictureUrl);
                // Add Ingrediants and Quantity
                var itemIngrediantsOrdered = new List <OrderItemIngrediant>();
                foreach (var ingrediant in item.Ingrediants)
                {
                    // If ingrediant Quantity is greater than default value then add to list
                    if (ingrediant.Quantity != meal.Ingrediants.FirstOrDefault(x => x.Id == ingrediant.Id).Quantity)
                    {
                        // Get ingrediant from repo
                        var repoIngrediant = meal.Ingrediants.FirstOrDefault(x => x.Id == ingrediant.Id);
                        // Get Quantity
                        var quantity        = ingrediant.Quantity;
                        var ingrediantToAdd = new OrderItemIngrediant(quantity, repoIngrediant.Price, repoIngrediant.Name);
                        itemIngrediantsOrdered.Add(ingrediantToAdd);
                    }
                }
                // Create orderItem
                var orderItem = new OrderItem(itemOrdered, meal.Price, item.Quantity, itemIngrediantsOrdered);
                // Add extra ingrediant price to total order Price
                foreach (var ingrediant in orderItem.Ingrediants)
                {
                    if (ingrediant.Quantity > 1)
                    {
                        orderItem.Price += ingrediant.Price * (ingrediant.Quantity);
                    }
                    else
                    {
                        orderItem.Price -= ingrediant.Price;
                    }
                }
                // Add to list
                items.Add(orderItem);
            }

            // get delivery method from repo
            var deliveryMethod = await _unitOfWork.Repository <DeliveryMethod>().GetByIdAsync(deliveryMethodId);

            // calc subtotal
            var subtotal = items.Sum(item => item.Price * item.Quantity);

            // check to see if order exists for orders done by credit card
            if (paymentMethod)
            {
                var spec          = new OrderByPaymentIntentIdSpecification(basket.PaymentIntentId);
                var existingOrder = await _unitOfWork.Repository <Order>().GetEnitityWithSpec(spec);

                if (existingOrder != null)
                {
                    _unitOfWork.Repository <Order>().Delete(existingOrder);
                    await _paymentService.CreateOrUpdatePaymentIntent(basket.PaymentIntentId);
                }
            }


            // create order
            var order = new Order(items, buyerEmail, shippingAddress, deliveryMethod, subtotal, basket.PaymentIntentId, paymentMethod, shippingDate);

            // edit status for payroll
            if (!paymentMethod)
            {
                order.Status = OrderStatus.PayRollPending;
            }

            _unitOfWork.Repository <Order>().Add(order);

            // save to db
            var result = await _unitOfWork.Complete();

            if (result < 0)
            {
                return(null);
            }

            // return order
            return(order);
        }