using Grand.Business.Core.Interfaces.Catalog.Discounts;
using Grand.Business.Core.Interfaces.Checkout.CheckoutAttributes;
using Grand.Business.Core.Interfaces.Checkout.GiftVouchers;
using Grand.Business.Core.Interfaces.Checkout.Orders;
using Grand.Business.Core.Interfaces.Common.Directory;
using Grand.Business.Core.Interfaces.Common.Localization;
using Grand.Business.Core.Interfaces.Common.Security;
using Grand.Business.Core.Interfaces.Customers;
using Grand.Business.Core.Interfaces.Storage;
using Grand.Business.Core.Utilities.Common.Security;
using Grand.Domain.Catalog;
using Grand.Domain.Common;
using Grand.Domain.Customers;
using Grand.Domain.Media;
using Grand.Domain.Orders;
using Grand.Infrastructure;
using Grand.Web.Commands.Models.ShoppingCart;
using Grand.SharedKernel.Attributes;
using Grand.Web.Common.Controllers;
using Grand.Web.Common.Extensions;
using Grand.Web.Common.Filters;
using Grand.Web.Features.Models.ShoppingCart;
using Grand.Web.Models.ShoppingCart;
using MediatR;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;

namespace Grand.Web.Controllers
{
    public class ShoppingCartController : BasePublicController
    {
        #region Fields

        private readonly IWorkContext _workContext;
        private readonly IShoppingCartService _shoppingCartService;
        private readonly ITranslationService _translationService;
        private readonly IDiscountService _discountService;
        private readonly ICustomerService _customerService;
        private readonly IGroupService _groupService;
        private readonly ICheckoutAttributeService _checkoutAttributeService;
        private readonly IPermissionService _permissionService;
        private readonly IUserFieldService _userFieldService;
        private readonly IMediator _mediator;
        private readonly IShoppingCartValidator _shoppingCartValidator;
        private readonly ShoppingCartSettings _shoppingCartSettings;
        private readonly OrderSettings _orderSettings;

        #endregion

        #region Constructors

        public ShoppingCartController(
            IWorkContext workContext,
            IShoppingCartService shoppingCartService,
            ITranslationService translationService,
            IDiscountService discountService,
            ICustomerService customerService,
            IGroupService groupService,
            ICheckoutAttributeService checkoutAttributeService,
            IPermissionService permissionService,
            IUserFieldService userFieldService,
            IMediator mediator,
            IShoppingCartValidator shoppingCartValidator,
            ShoppingCartSettings shoppingCartSettings,
            OrderSettings orderSettings)
        {
            _workContext = workContext;
            _shoppingCartService = shoppingCartService;
            _translationService = translationService;
            _discountService = discountService;
            _customerService = customerService;
            _groupService = groupService;
            _checkoutAttributeService = checkoutAttributeService;
            _permissionService = permissionService;
            _userFieldService = userFieldService;
            _mediator = mediator;
            _shoppingCartValidator = shoppingCartValidator;
            _shoppingCartSettings = shoppingCartSettings;
            _orderSettings = orderSettings;
        }

        #endregion

        #region Utilities

        private ShoppingCartType[] PrepareCartTypes()
        {
            var shoppingCartTypes = new List<ShoppingCartType> {
                ShoppingCartType.ShoppingCart,
                ShoppingCartType.Auctions
            };
            if (_shoppingCartSettings.AllowOnHoldCart)
                shoppingCartTypes.Add(ShoppingCartType.OnHoldCart);

            return shoppingCartTypes.ToArray();
        }

        #endregion

        #region Shopping cart

        [HttpGet]
        [ProducesResponseType(typeof(MiniShoppingCartModel), StatusCodes.Status200OK)]
        public async Task<IActionResult> SidebarShoppingCart()
        {
            if (!_shoppingCartSettings.MiniShoppingCartEnabled)
                return Content("");

            if (!await _permissionService.Authorize(StandardPermission.EnableShoppingCart))
                return Content("");

            var model = await _mediator.Send(new GetMiniShoppingCart {
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType,
                Store = _workContext.CurrentStore
            });
            return Json(model);
        }

        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> CheckoutAttributeChange(CheckoutAttributeSelectedModel model,
            [FromServices] ICheckoutAttributeParser checkoutAttributeParser,
            [FromServices] ICheckoutAttributeFormatter checkoutAttributeFormatter)
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                ShoppingCartType.ShoppingCart, ShoppingCartType.Auctions);

            var checkoutAttributes = await _mediator.Send(new SaveCheckoutAttributesCommand {
                Customer = _workContext.CurrentCustomer,
                Store = _workContext.CurrentStore,
                Cart = cart,
                SelectedAttributes = model.Attributes
            });

            var enabledAttributeIds = new List<string>();
            var disabledAttributeIds = new List<string>();
            var attributes =
                await _checkoutAttributeService.GetAllCheckoutAttributes(_workContext.CurrentStore.Id,
                    !cart.RequiresShipping());
            foreach (var attribute in attributes)
            {
                var conditionMet = await checkoutAttributeParser.IsConditionMet(attribute, checkoutAttributes);
                if (!conditionMet.HasValue) continue;

                if (conditionMet.Value)
                    enabledAttributeIds.Add(attribute.Id);
                else
                    disabledAttributeIds.Add(attribute.Id);
            }

            var orderTotals = await _mediator.Send(new GetOrderTotals {
                Cart = cart,
                IsEditable = true,
                Store = _workContext.CurrentStore,
                Currency = _workContext.WorkingCurrency,
                Customer = _workContext.CurrentCustomer,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                enabledattributeids = enabledAttributeIds.ToArray(),
                disabledattributeids = disabledAttributeIds.ToArray(),
                model = orderTotals,
                checkoutattributeinfo =
                    await checkoutAttributeFormatter.FormatAttributes(checkoutAttributes, _workContext.CurrentCustomer)
            });
        }

        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> UploadFileCheckoutAttribute(string attributeId,
            [FromServices] IDownloadService downloadService)
        {
            var attribute = await _checkoutAttributeService.GetCheckoutAttributeById(attributeId);
            if (attribute is not { AttributeControlTypeId: AttributeControlType.FileUpload })
            {
                return Json(new {
                    success = false,
                    downloadGuid = Guid.Empty
                });
            }

            var form = await HttpContext.Request.ReadFormAsync();
            var httpPostedFile = form.Files.FirstOrDefault();
            if (httpPostedFile == null)
            {
                return Json(new {
                    success = false,
                    message = "No file uploaded",
                    downloadGuid = Guid.Empty
                });
            }

            var fileBinary = httpPostedFile.GetDownloadBits();
            var fileName = httpPostedFile.FileName;

            fileName = Path.GetFileName(fileName);

            var contentType = httpPostedFile.ContentType;

            var fileExtension = Path.GetExtension(fileName);
            if (!string.IsNullOrEmpty(fileExtension))
                fileExtension = fileExtension.ToLowerInvariant();

            if (!string.IsNullOrEmpty(attribute.ValidationFileAllowedExtensions))
            {
                var allowedFileExtensions = attribute.ValidationFileAllowedExtensions.ToLowerInvariant()
                    .Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                    .ToList();
                if (!allowedFileExtensions.Contains(fileExtension.ToLowerInvariant()))
                {
                    return Json(new {
                        success = false,
                        message = _translationService.GetResource("ShoppingCart.ValidationFileAllowed"),
                        downloadGuid = Guid.Empty
                    });
                }
            }

            if (attribute.ValidationFileMaximumSize.HasValue)
            {
                //compare in bytes
                var maxFileSizeBytes = attribute.ValidationFileMaximumSize.Value * 1024;
                if (fileBinary.Length > maxFileSizeBytes)
                {
                    //when returning JSON the mime-type must be set to text/plain
                    //otherwise some browsers will pop-up a "Save As" dialog.
                    return Json(new {
                        success = false,
                        message = string.Format(_translationService.GetResource("ShoppingCart.MaximumUploadedFileSize"),
                            attribute.ValidationFileMaximumSize.Value),
                        downloadGuid = Guid.Empty
                    });
                }
            }

            var download = new Download {
                DownloadGuid = Guid.NewGuid(),
                CustomerId = _workContext.CurrentCustomer.Id,
                UseDownloadUrl = false,
                DownloadUrl = "",
                DownloadBinary = fileBinary,
                ContentType = contentType,
                Filename = Path.GetFileNameWithoutExtension(fileName),
                Extension = fileExtension,
                DownloadType = DownloadType.CheckoutAttribute,
                ReferenceId = attributeId
            };
            await downloadService.InsertDownload(download);

            //when returning JSON the mime-type must be set to text/plain
            //otherwise some browsers will pop-up a "Save As" dialog.
            return Json(new {
                success = true,
                message = _translationService.GetResource("ShoppingCart.FileUploaded"),
                downloadUrl = Url.Action("GetFileUpload", "Download", new { downloadId = download.DownloadGuid }),
                downloadGuid = download.DownloadGuid
            });
        }

        [HttpGet]
        //[ProducesResponseType(typeof(ShoppingCartModel), StatusCodes.Status200OK)]
        public virtual async Task<IActionResult> Cart(bool checkoutAttributes)
        {
            if (!await _permissionService.Authorize(StandardPermission.EnableShoppingCart))
                return RedirectToRoute("HomePage");

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());
            var model = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                ValidateCheckoutAttributes = checkoutAttributes,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType,
                Store = _workContext.CurrentStore
            });
            return View(model);
        }

        [HttpGet]
        [DenySystemAccount]
        [ProducesResponseType(typeof(ShoppingCartModel), StatusCodes.Status200OK)]
        public async Task<IActionResult> CartSummary()
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                ShoppingCartType.ShoppingCart, ShoppingCartType.Auctions);

            var model = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                IsEditable = false,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(model);
        }

        [HttpGet]
        [DenySystemAccount]
        [ProducesResponseType(typeof(OrderTotalsModel), StatusCodes.Status200OK)]
        public async Task<IActionResult> CartTotal()
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                ShoppingCartType.ShoppingCart, ShoppingCartType.Auctions);

            var model = await _mediator.Send(new GetOrderTotals {
                Cart = cart,
                Store = _workContext.CurrentStore,
                Currency = _workContext.WorkingCurrency,
                Customer = _workContext.CurrentCustomer,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType
            });
            return Json(model);
        }


        [AutoValidateAntiforgeryToken]
        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> UpdateQuantity(UpdateQuantityModel model)
        {
            if (!ModelState.IsValid)
            {
                return Json(new {
                    success = false,
                    warnings = string.Join(',', ModelState.Values.SelectMany(x => x.Errors.Select(x => x.ErrorMessage)))
                });
            }

            var cart = (await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes()))
                .FirstOrDefault(x => x.Id == model.ShoppingCartId);
            var warnings = new List<string>();

            if (cart != null)
            {
                var currSciWarnings = await _shoppingCartService.UpdateShoppingCartItem(_workContext.CurrentCustomer,
                    cart.Id, cart.WarehouseId, cart.Attributes, cart.EnteredPrice,
                    cart.RentalStartDateUtc, cart.RentalEndDateUtc,
                    model.Quantity);
                warnings.AddRange(currSciWarnings);
            }

            var cartModel = await _mediator.Send(new GetShoppingCart {
                Cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes()),
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                success = !warnings.Any(),
                warnings = string.Join(", ", warnings),
                totalproducts = string.Format(_translationService.GetResource("ShoppingCart.HeaderQuantity"),
                    cartModel.Items.Sum(x => x.Quantity)),
                model = cartModel
            });
        }

        [HttpGet]
        [DenySystemAccount]
        public virtual async Task<IActionResult> ClearCart()
        {
            if (!await _permissionService.Authorize(StandardPermission.EnableShoppingCart))
                return RedirectToRoute("HomePage");

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());

            foreach (var sci in cart)
            {
                await _shoppingCartService.DeleteShoppingCartItem(_workContext.CurrentCustomer, sci,
                    ensureOnlyActiveCheckoutAttributes: true);
            }

            return RedirectToRoute("HomePage");
        }

        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> DeleteCartItem(DeleteCartItemModel model)
        {
            if (!await _permissionService.Authorize(StandardPermission.EnableShoppingCart))
                return RedirectToRoute("HomePage");

            var shoppingCartTypes = new List<ShoppingCartType> { ShoppingCartType.ShoppingCart };
            if (_shoppingCartSettings.AllowOnHoldCart)
                shoppingCartTypes.Add(ShoppingCartType.OnHoldCart);

            var item = (await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                    shoppingCartTypes.ToArray()))
                .FirstOrDefault(sci => sci.Id == model.Id);

            if (item != null)
            {
                await _shoppingCartService.DeleteShoppingCartItem(_workContext.CurrentCustomer, item,
                    ensureOnlyActiveCheckoutAttributes: true);
            }

            var miniShoppingCartmodel = await _mediator.Send(new GetMiniShoppingCart {
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType,
                Store = _workContext.CurrentStore
            });
            if (!model.ShoppingCartPage)
            {
                return Json(new {
                    totalproducts = string.Format(_translationService.GetResource("ShoppingCart.HeaderQuantity"),
                        miniShoppingCartmodel.TotalProducts),
                    sidebarshoppingcartmodel = miniShoppingCartmodel
                });
            }

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());
            var shoppingcartmodel = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                totalproducts = string.Format(_translationService.GetResource("ShoppingCart.HeaderQuantity"),
                    miniShoppingCartmodel.TotalProducts),
                sidebarshoppingcartmodel = miniShoppingCartmodel,
                model = shoppingcartmodel
            });
        }

        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> ChangeTypeCartItem(ChangeTypeCartItemModel model)
        {
            if (!await _permissionService.Authorize(StandardPermission.EnableShoppingCart))
                return RedirectToRoute("HomePage");

            if (!_shoppingCartSettings.AllowOnHoldCart)
                return RedirectToRoute("HomePage");

            var shoppingCartTypes = new List<ShoppingCartType> { ShoppingCartType.ShoppingCart };
            if (_shoppingCartSettings.AllowOnHoldCart)
                shoppingCartTypes.Add(ShoppingCartType.OnHoldCart);

            var item = (await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                    shoppingCartTypes.ToArray()))
                .FirstOrDefault(sci => sci.Id == model.Id);

            if (item != null)
            {
                item.ShoppingCartTypeId = model.Status ? ShoppingCartType.ShoppingCart : ShoppingCartType.OnHoldCart;
                await _customerService.UpdateShoppingCartItem(_workContext.CurrentCustomer.Id, item);
            }

            var miniShoppingCart = await _mediator.Send(new GetMiniShoppingCart {
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                TaxDisplayType = _workContext.TaxDisplayType,
                Store = _workContext.CurrentStore
            });

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());
            var shoppingcartmodel = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                model = shoppingcartmodel,
                sidebarshoppingcartmodel = miniShoppingCart
            });
        }

        [IgnoreApi]
        [HttpGet]
        public virtual IActionResult ContinueShopping()
        {
            var returnUrl =
                _workContext.CurrentCustomer.GetUserFieldFromEntity<string>(
                    SystemCustomerFieldNames.LastContinueShoppingPage, _workContext.CurrentStore.Id);
            if (!string.IsNullOrEmpty(returnUrl) && Url.IsLocalUrl(returnUrl))
                return Redirect(returnUrl);

            return RedirectToRoute("HomePage");
        }

        [HttpPost]
        [DenySystemAccount]
        public virtual async Task<IActionResult> StartCheckout(CheckoutAttributeSelectedModel model)
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                ShoppingCartType.ShoppingCart, ShoppingCartType.Auctions);
            List<CustomAttribute> checkoutAttributes;
            //parse and save checkout attributes
            if (model?.Attributes is { Count: > 0 })
            {
                checkoutAttributes = (await _mediator.Send(new SaveCheckoutAttributesCommand {
                    Customer = _workContext.CurrentCustomer,
                    Store = _workContext.CurrentStore,
                    Cart = cart,
                    SelectedAttributes = model.Attributes
                })).ToList();
            }
            else
            {
                checkoutAttributes =
                    _workContext.CurrentCustomer.GetUserFieldFromEntity<List<CustomAttribute>>(
                        SystemCustomerFieldNames.CheckoutAttributes, _workContext.CurrentStore.Id);
            }

            var checkoutAttributeWarnings =
                await _shoppingCartValidator.GetShoppingCartWarnings(cart, checkoutAttributes, true, true);
            if (checkoutAttributeWarnings.Any())
            {
                return RedirectToRoute("ShoppingCart", new { checkoutAttributes = true });
            }

            //everything is OK
            if (!await _groupService.IsGuest(_workContext.CurrentCustomer)) return RedirectToRoute("Checkout");
            if (!_orderSettings.AnonymousCheckoutAllowed)
                return Challenge();

            return RedirectToRoute("LoginCheckoutAsGuest", new { returnUrl = Url.RouteUrl("ShoppingCart") });
        }

        [AutoValidateAntiforgeryToken]
        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> ApplyDiscountCoupon(DiscountCouponModel model)
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());

            var message = string.Empty;
            var isApplied = false;

            if (ModelState.IsValid)
            {
                //valid
                var applyCouponCode =
                    _workContext.CurrentCustomer.ApplyCouponCode(SystemCustomerFieldNames.DiscountCoupons,
                        model.DiscountCouponCode);
                //apply new value
                await _userFieldService.SaveField(_workContext.CurrentCustomer,
                    SystemCustomerFieldNames.DiscountCoupons, applyCouponCode);
                message = _translationService.GetResource("ShoppingCart.DiscountCouponCode.Applied");
                isApplied = true;
            }
            else
                message = string.Join(',', ModelState.Values.SelectMany(x => x.Errors.Select(x => x.ErrorMessage)));

            var cartModel = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            cartModel.DiscountBox.Message = message;
            cartModel.DiscountBox.IsApplied = isApplied;

            return Json(new {
                model = cartModel
            });
        }

        [AutoValidateAntiforgeryToken]
        [DenySystemAccount]
        [HttpPost]
        public virtual async Task<IActionResult> ApplyGiftVoucher(GiftVoucherCouponModel model)
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());

            var message = string.Empty;
            var isApplied = false;

            if (ModelState.IsValid)
            {
                model.GiftVoucherCouponCode = model.GiftVoucherCouponCode.Trim();

                var result = _workContext.CurrentCustomer.ApplyCouponCode(SystemCustomerFieldNames.GiftVoucherCoupons,
                    model.GiftVoucherCouponCode.ToLower());
                //apply new value
                await _userFieldService.SaveField(_workContext.CurrentCustomer,
                    SystemCustomerFieldNames.GiftVoucherCoupons, result);

                message = _translationService.GetResource("ShoppingCart.Code.Applied");
                isApplied = true;
            }
            else
                message = string.Join(',', ModelState.Values.SelectMany(x => x.Errors.Select(x => x.ErrorMessage)));

            var cartModel = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            cartModel.GiftVoucherBox.Message = message;
            cartModel.GiftVoucherBox.IsApplied = isApplied;

            return Json(new {
                model = cartModel
            });
        }

        [AutoValidateAntiforgeryToken]
        [HttpPost]
        public virtual async Task<IActionResult> GetEstimateShipping(EstimateShippingModel model)
        {
            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id,
                ShoppingCartType.ShoppingCart, ShoppingCartType.Auctions);

            var result = await _mediator.Send(new GetEstimateShippingResult {
                Cart = cart,
                Currency = _workContext.WorkingCurrency,
                Customer = _workContext.CurrentCustomer,
                Store = _workContext.CurrentStore,
                CountryId = model.CountryId,
                StateProvinceId = model.StateProvinceId,
                ZipPostalCode = model.ZipPostalCode
            });

            return PartialView("Partials/EstimateShippingResult", result);
        }

        [DenySystemAccount]
        [HttpGet]
        public virtual async Task<IActionResult> RemoveDiscountCoupon(string discountId)
        {
            var discount = await _discountService.GetDiscountById(discountId);
            if (discount != null)
            {
                var coupons =
                    _workContext.CurrentCustomer.ParseAppliedCouponCodes(SystemCustomerFieldNames.DiscountCoupons);
                foreach (var item in coupons)
                {
                    var dd = await _discountService.GetDiscountByCouponCode(item);
                    if (dd.Id != discount.Id) continue;

                    //remove coupon
                    var result =
                        _workContext.CurrentCustomer.RemoveCouponCode(SystemCustomerFieldNames.DiscountCoupons, item);
                    await _userFieldService.SaveField(_workContext.CurrentCustomer,
                        SystemCustomerFieldNames.DiscountCoupons, result);
                }
            }

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());

            var model = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                model
            });
        }

        [DenySystemAccount]
        [HttpGet]
        public virtual async Task<IActionResult> RemoveGiftVoucherCode(string giftVoucherId,
            [FromServices] IGiftVoucherService giftVoucherService)
        {
            if (!string.IsNullOrEmpty(giftVoucherId))
            {
                //remove card
                var giftvoucher = await giftVoucherService.GetGiftVoucherById(giftVoucherId);
                if (giftvoucher != null)
                {
                    var result =
                        _workContext.CurrentCustomer.RemoveCouponCode(SystemCustomerFieldNames.GiftVoucherCoupons,
                            giftvoucher.Code);
                    await _userFieldService.SaveField(_workContext.CurrentCustomer,
                        SystemCustomerFieldNames.GiftVoucherCoupons, result);
                }
            }

            var cart = await _shoppingCartService.GetShoppingCart(_workContext.CurrentStore.Id, PrepareCartTypes());

            var model = await _mediator.Send(new GetShoppingCart {
                Cart = cart,
                Customer = _workContext.CurrentCustomer,
                Currency = _workContext.WorkingCurrency,
                Language = _workContext.WorkingLanguage,
                Store = _workContext.CurrentStore,
                TaxDisplayType = _workContext.TaxDisplayType
            });

            return Json(new {
                model
            });
        }

        #endregion
    }
}