public override async Task <EkKioskProductAndReplacementsByPartNumberGetResponse> ExecuteAsync(EkKioskProductAndReplacementsByPartNumberGetRequest request)
        {
            Assure.ArgumentNotNull(request.PartNumberBrand, nameof(request.PartNumberBrand));
            Assure.ArgumentNotNull(request.PartNumberBrand.ProductKey, nameof(request.PartNumberBrand.ProductKey));
            Assure.ArgumentNotNull(request.PartNumberBrand.PartNumber, nameof(request.PartNumberBrand.PartNumber));

            var response = new EkKioskProductAndReplacementsByPartNumberGetResponse();

            // cancellation token
            var cancellationToken = _httpContextAccessor.HttpContext?.RequestAborted ?? CancellationToken.None;

            using (var searchIndexClient = AzureSearchHelper.CreateSearchIndexClient(_ekSearchSettings.ServiceName, _ekSearchSettings.QueryKey))
            {
                searchIndexClient.IndexName = _ekSearchSettings.ProductsIndexName;

                // FIND PRODUCT
                try
                {
                    var indexProduct = await searchIndexClient.Documents.GetAsync <IndexProduct>(
                        request.PartNumberBrand.ProductKey,
                        cancellationToken : cancellationToken);

                    response.Product = EkConvertHelper.EkNewIndexProductToProduct(indexProduct);

                    // todo: add search by Brand/PartNumber to find all direct matches since many products sources are supported
                    // it's not done since new product search model is planned anyway
                }
                catch (CloudException)
                {
                    response.Product = EkConvertHelper.EkOmegaPartNumberBrandToProduct(request.PartNumberBrand);
                }

                // FIND REPLACEMENTS
                var cleanedPartNumber = PartNumberCleaner.GetCleanedPartNumber(request.PartNumberBrand.PartNumber);

                // TecDoc replacements
                // todo: add cancellationToken support to proxy based clients
                var tecDocReplacements = await _tecDocWsClient.SearchByArticleNumberAsync(cleanedPartNumber);

                tecDocReplacements = tecDocReplacements
                                     // except direct match
                                     .Where(x => x.NumberType != ArticleNumberTypeEnum.ArticleNumber)
                                     .ToArray();

                var replacementCleanedBrandPartNumbers = tecDocReplacements
                                                         .Select(x => PartNumberCleaner.GetCleanedBrandPartNumber(x.BrandName, x.ArticleNo))
                                                         .Take(100)
                                                         .ToArray();

                if (replacementCleanedBrandPartNumbers.Length > 0)
                {
                    var replacementsIndexSearchParameters = new SearchParameters()
                    {
                        Top          = 100,
                        SearchFields = new[] { "cleanedBrandPartNumber" },
                    };
                    var searchTerm   = string.Join("|", replacementCleanedBrandPartNumbers);
                    var searchResult = await searchIndexClient.Documents.SearchAsync <IndexProduct>(
                        searchTerm,
                        replacementsIndexSearchParameters,
                        cancellationToken : cancellationToken);

                    response.Replacements = searchResult.Results
                                            .Select(x => EkConvertHelper.EkNewIndexProductToProduct(x.Document))
                                            .ToArray();
                }
                else
                {
                    response.Replacements = new EkProduct[0];
                }

                return(response);
            }
        }