/// <summary>
        /// Invoke the widget view component
        /// </summary>
        /// <param name="widgetZone">Widget zone</param>
        /// <param name="additionalData">Additional parameters</param>
        /// <returns>View component result</returns>
        public IViewComponentResult Invoke(string widgetZone, object additionalData)
        {
            //ensure that Avalara tax provider is active
            if (!_taxPluginManager.IsPluginActive(AvalaraTaxDefaults.SystemName, _workContext.CurrentCustomer, _storeContext.CurrentStore.Id))
            {
                return(Content(string.Empty));
            }

            //ensure that it's a proper widget zone
            if (!widgetZone.Equals(PublicWidgetZones.CheckoutConfirmTop) && !widgetZone.Equals(PublicWidgetZones.OpCheckoutConfirmTop))
            {
                return(Content(string.Empty));
            }

            //ensure thet address validation is enabled
            if (!_avalaraTaxSettings.ValidateAddress)
            {
                return(Content(string.Empty));
            }

            //validate entered by customer addresses only
            var addressId = _taxSettings.TaxBasedOn == TaxBasedOn.BillingAddress
                ? _workContext.CurrentCustomer.BillingAddressId
                : _taxSettings.TaxBasedOn == TaxBasedOn.ShippingAddress
                ? _workContext.CurrentCustomer.ShippingAddressId
                : null;

            var address = _addressService.GetAddressById(addressId ?? 0);

            if (address == null)
            {
                return(Content(string.Empty));
            }

            //validate address
            var validationResult = _avalaraTaxManager.ValidateAddress(new AddressValidationInfo
            {
                city       = CommonHelper.EnsureMaximumLength(address.City, 50),
                country    = CommonHelper.EnsureMaximumLength(_countryService.GetCountryByAddress(address)?.TwoLetterIsoCode, 2),
                line1      = CommonHelper.EnsureMaximumLength(address.Address1, 50),
                line2      = CommonHelper.EnsureMaximumLength(address.Address2, 100),
                postalCode = CommonHelper.EnsureMaximumLength(address.ZipPostalCode, 11),
                region     = CommonHelper.EnsureMaximumLength(_stateProvinceService.GetStateProvinceByAddress(address)?.Abbreviation, 3),
                textCase   = TextCase.Mixed
            });

            //whether there are errors in validation result
            var errorDetails = validationResult.messages?
                               .Where(message => message.severity.Equals("Error", StringComparison.InvariantCultureIgnoreCase))
                               .Select(message => message.details) ?? new List <string>();

            if (errorDetails.Any())
            {
                var errorMessage = errorDetails.Aggregate(string.Empty, (message, errorDetail) => $"{message}{errorDetail}; ");

                //log errors
                _logger.Error($"Avalara tax provider error. {errorMessage}", customer: _workContext.CurrentCustomer);

                //and display error message to customer
                return(View("~/Plugins/Tax.Avalara/Views/Checkout/AddressValidation.cshtml", new AddressValidationModel
                {
                    Message = string.Format(_localizationService.GetResource("Plugins.Tax.Avalara.AddressValidation.Error"), WebUtility.HtmlEncode(errorMessage)),
                    IsError = true
                }));
            }

            //if there are no errors and no validated addresses, nothing to display
            if (!validationResult.validatedAddresses?.Any() ?? true)
            {
                return(Content(string.Empty));
            }

            //get validated address info
            var validatedAddressInfo = validationResult.validatedAddresses.FirstOrDefault();

            //create new address as a copy of address to validate and with details of the validated one
            var validatedAddress = _addressService.CloneAddress(address);

            validatedAddress.City            = validatedAddressInfo.city;
            validatedAddress.CountryId       = _countryService.GetCountryByTwoLetterIsoCode(validatedAddressInfo.country)?.Id;
            validatedAddress.Address1        = validatedAddressInfo.line1;
            validatedAddress.Address2        = validatedAddressInfo.line2;
            validatedAddress.ZipPostalCode   = validatedAddressInfo.postalCode;
            validatedAddress.StateProvinceId = _stateProvinceService.GetStateProvinceByAbbreviation(validatedAddressInfo.region)?.Id;

            //try to find an existing address with the same values
            var existingAddress = _addressService.FindAddress(_customerService.GetAddressesByCustomerId(_workContext.CurrentCustomer.Id).ToList(),
                                                              validatedAddress.FirstName, validatedAddress.LastName, validatedAddress.PhoneNumber,
                                                              validatedAddress.Email, validatedAddress.FaxNumber, validatedAddress.Company,
                                                              validatedAddress.Address1, validatedAddress.Address2, validatedAddress.City,
                                                              validatedAddress.County, validatedAddress.StateProvinceId, validatedAddress.ZipPostalCode,
                                                              validatedAddress.CountryId, validatedAddress.CustomAttributes);

            //if the found address is the same as address to validate, nothing to display
            if (address.Id == existingAddress?.Id)
            {
                return(Content(string.Empty));
            }

            //otherwise display to customer a confirmation dialog about address updating
            var model = new AddressValidationModel();

            if (existingAddress == null)
            {
                _addressService.InsertAddress(validatedAddress);
                model.AddressId    = validatedAddress.Id;
                model.IsNewAddress = true;
            }
            else
            {
                model.AddressId = existingAddress.Id;
            }

            model.Message = string.Format(_localizationService.GetResource("Plugins.Tax.Avalara.AddressValidation.Confirm"),
                                          GetAddressLine(address), GetAddressLine(existingAddress ?? validatedAddress));

            return(View("~/Plugins/Tax.Avalara/Views/Checkout/AddressValidation.cshtml", model));
        }