<commit_before>﻿using FluentAssertions;
using Newtonsoft.Json;
using Picturepark.SDK.V1.Contract;
using Picturepark.SDK.V1.Tests.Contracts;
using Picturepark.SDK.V1.Tests.Fixtures;
using Picturepark.SDK.V1.Tests.FluentAssertions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace Picturepark.SDK.V1.Tests.Clients
{
    public class ContentTests : IClassFixture<ContentFixture>
    {
        private readonly ClientFixture _fixture;
        private readonly IPictureparkService _client;

        public ContentTests(ContentFixture fixture)
        {
            _fixture = fixture;
            _client = _fixture.Client;
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldTransferOwnership()
        {
            // Arrange
            var contentId = await _fixture.GetRandomContentIdAsync("fileMetadata.fileExtension:.jpg", 50).ConfigureAwait(false);

            // Act
            var previousContent = await _client.Content.GetAsync(contentId).ConfigureAwait(false);
            var previousOwner = await _client.User.GetByOwnerTokenAsync(previousContent.OwnerTokenId).ConfigureAwait(false);
            var searchResult = await _client.User.SearchAsync(new UserSearchRequest { Limit = 10, UserRightsFilter = new List<UserRight> { UserRight.ManageContent } }).ConfigureAwait(false);

            var newUser = searchResult.Results.First(u => u.Id != previousOwner.Id);
            var request = new ContentOwnershipTransferRequest
            {
                TransferUserId = newUser.Id
            };
            await _client.Content.TransferOwnershipAsync(contentId, request).ConfigureAwait(false);

            var newContent = await _client.Content.GetAsync(contentId).ConfigureAwait(false);
            var newOwner = await _client.User.GetByOwnerTokenAsync(newContent.OwnerTokenId).ConfigureAwait(false);

            // Assert
            Assert.Equal(previousContent.Id, newContent.Id);
            Assert.NotEqual(previousContent.OwnerTokenId, newContent.OwnerTokenId);
            Assert.NotEqual(previousOwner.Id, newOwner.Id);
            Assert.Equal(newUser.Id, newOwner.Id);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldGetMany()
        {
            // Arrange
            var randomContents = await _fixture.GetRandomContentsAsync(".jpg", 2).ConfigureAwait(false);
            var contentIds = randomContents.Results.Select(i => i.Id).ToList();

            // Act
            var contents = await _client.Content.GetManyAsync(contentIds, new[] { ContentResolveBehavior.Owner, ContentResolveBehavior.Permissions }).ConfigureAwait(false);

            // Assert
            Assert.Equal(2, contents.Count);
            Assert.Equal(contentIds[0], contents.ToList()[0].Id);
            Assert.Equal(contentIds[1], contents.ToList()[1].Id);

            contents.Should().NotContainNulls(i => i.Owner);
            contents.Should().NotContainNulls(i => i.ContentRights);

            contents.ToList().ForEach(content =>
                {
                    content.Audit.CreatedByUser.Should().BeResolved();
                    content.Audit.ModifiedByUser.Should().BeResolved();
                }
            );
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldTransferOwnershipMany()
        {
            // Arrange
            var randomContents = await _fixture.GetRandomContentsAsync(".jpg", 2).ConfigureAwait(false);
            var contentIds = randomContents.Results.Select(i => i.Id).ToList();

            // Act
            var previousContents = await _client.Content.GetManyAsync(contentIds).ConfigureAwait(false);
            var previousOwner = await _client.User.GetByOwnerTokenAsync(previousContents.ToList()[0].OwnerTokenId).ConfigureAwait(false);

            // Search user with ManageContent UserRight
            var searchResult = await _client.User.SearchAsync(new UserSearchRequest
            {
                Limit = 10,
                UserRightsFilter = new List<UserRight> { UserRight.ManageContent }
            }).ConfigureAwait(false);

            var newUser = searchResult.Results.FirstOrDefault(u => u.Id != previousOwner.Id);
            newUser.Should().NotBeNull($"expected to have more users with {UserRight.ManageContent} user right in the tested customer to test content ownership transfer");
            var manyRequest = new ContentOwnershipTransferManyRequest
            {
                Items = contentIds.Select(id => new ContentOwnershipTransferItem
                {
                    ContentId = id,
                    TransferUserId = newUser.Id
                }).ToList()
            };

            await _client.Content.TransferOwnershipManyAsync(manyRequest).ConfigureAwait(false);

            var newContents = await _client.Content.GetManyAsync(contentIds).ConfigureAwait(false);
            var newOwner1 = await _client.User.GetByOwnerTokenAsync(newContents.ToList()[0].OwnerTokenId).ConfigureAwait(false);
            var newOwner2 = await _client.User.GetByOwnerTokenAsync(newContents.ToList()[1].OwnerTokenId).ConfigureAwait(false);

            // Assert
            Assert.Equal(previousContents.ToList()[0].Id, newContents.ToList()[0].Id);
            Assert.Equal(previousContents.ToList()[1].Id, newContents.ToList()[1].Id);

            Assert.Equal(newOwner1.Id, newOwner2.Id);
            Assert.Equal(newUser.Id, newOwner1.Id);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateWithAggregators()
        {
            var request = new ContentAggregationRequest
            {
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Aggregator1", Field = "contentType", Size = 10 }
                }
            };

            // Second Aggregator
            var ranges = new List<NumericRangeForAggregator>
            {
                new NumericRangeForAggregator { From = null, To = 499, Names = new TranslatedStringDictionary { { "en", "Aggregator2a" } } },
                new NumericRangeForAggregator { From = 500, To = 5000, Names = new TranslatedStringDictionary { { "en", "Aggregator2b" } } }
            };

            var numRangeAggregator = new NumericRangeAggregator()
            {
                Name = "NumberAggregator",
                Field = "Original.Width",
                Ranges = ranges
            };

            request.Aggregators.Add(numRangeAggregator);
            await _client.Content.AggregateAsync(request).ConfigureAwait(false);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldSearchAndAggregateAllTogether()
        {
            var request = new ContentSearchRequest
            {
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Aggregator1", Field = "contentType", Size = 10 }
                }
            };

            // Second Aggregator
            var ranges = new List<NumericRangeForAggregator>
            {
                new NumericRangeForAggregator { From = null, To = 499, Names = new TranslatedStringDictionary { { "en", "Aggregator2a" } } },
                new NumericRangeForAggregator { From = 500, To = 5000, Names = new TranslatedStringDictionary { { "en", "Aggregator2b" } } }
            };

            var numRangeAggregator = new NumericRangeAggregator()
            {
                Name = "NumberAggregator",
                Field = "Original.Width",
                Ranges = ranges
            };

            request.Aggregators.Add(numRangeAggregator);
            var result = await _client.Content.SearchAsync(request).ConfigureAwait(false);
            result.Results.Should().HaveCountGreaterThan(0);
            result.AggregationResults.Should().HaveCount(2);
            foreach (var resultAggregationResult in result.AggregationResults)
            {
                resultAggregationResult.AggregationResultItems.Should().HaveCountGreaterThan(1);
            }
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateByChannel()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentAggregationRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty
            };

            // Act
            var result = await _client.Content.AggregateOnChannelAsync(request).ConfigureAwait(false);

            // Assert
            var originalWidthResults = result.AggregationResults
                .SingleOrDefault(i => i.Name == "Original Width");

            Assert.NotNull(originalWidthResults);
            Assert.True(originalWidthResults.AggregationResultItems.Count > 0);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateOnChannelWithTermsAggregator()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentAggregationRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Permissions", Field = "permissionSetIds", Size = 10 }
                }
            };

            // Act
            var result = await _client.Content.AggregateAsync(request).ConfigureAwait(false);

            // Assert
            var permissionSetResults = result.AggregationResults
                .SingleOrDefault(i => i.Name == "Permissions");

            Assert.NotNull(permissionSetResults);
            Assert.True(permissionSetResults.AggregationResultItems.Count > 0);
        }

        [Fact(Skip = "It must be re-enabled when url is accessible")]
        [Trait("Stack", "Contents")]
        public async Task ShouldSearchAndAggregateOnChannelWithTermsAggregator()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentSearchRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Permissions", Field = "permissionSetIds", Size = 10 }
                }
            };

            // Act
            var result = await _client.Content.SearchAsync(request).ConfigureAwait(false);

            // Assert
            result.Results.Should().HaveCountGreaterThan(0);
            var permissionSetAggregationResults = result.AggregationResults.SingleOrDefault(i => i.Name == "Permissions");
            permissionSetAggregationResults.Should().NotBeNull();
            permissionSetAggregationResults.AggregationResultItems.Should().HaveCountGreaterThan(0);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldCreateDownloadLinkForSingleFile()
        {
            // Arrange
            var contentId = await _fixture.GetRandomContentIdAsync("fileMetadata.fileExtension:.jpg", 50).ConfigureAwait(false);
            var createDownloadLinkRequest = new ContentDownloadLinkCreateRequest
            {
                Contents = new List<ContentDownloadRequestItem>
                {
                    new ContentDownloadRequestItem { ContentId = contentId, OutputFormatId = "Original" }
                }
            };

            // Act
            var result = await _client.Content.CreateDownloadLinkAsync(createDownloadLinkRequest).ConfigureAwait(false);
            Assert.NotNull(result.DownloadUrl);

            using (var httpClient = new HttpClient())
            using (var response = await httpClient.GetAsync(result.DownloadUrl).ConfigureAwait(false))
            {
                response.EnsureSuccessStatusCode();

                var fileName = response.Content.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
                Assert.EndsWith(".jpg", fileName);

                var filePath = Path.Combine(_fixture.TempDirectory, fileName);

                using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                using (var fileStream = File.Create(filePath))<commit_msg>PP9-9768 also skip download link for single file<commit_after>﻿using FluentAssertions;
using Newtonsoft.Json;
using Picturepark.SDK.V1.Contract;
using Picturepark.SDK.V1.Tests.Contracts;
using Picturepark.SDK.V1.Tests.Fixtures;
using Picturepark.SDK.V1.Tests.FluentAssertions;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;

namespace Picturepark.SDK.V1.Tests.Clients
{
    public class ContentTests : IClassFixture<ContentFixture>
    {
        private readonly ClientFixture _fixture;
        private readonly IPictureparkService _client;

        public ContentTests(ContentFixture fixture)
        {
            _fixture = fixture;
            _client = _fixture.Client;
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldTransferOwnership()
        {
            // Arrange
            var contentId = await _fixture.GetRandomContentIdAsync("fileMetadata.fileExtension:.jpg", 50).ConfigureAwait(false);

            // Act
            var previousContent = await _client.Content.GetAsync(contentId).ConfigureAwait(false);
            var previousOwner = await _client.User.GetByOwnerTokenAsync(previousContent.OwnerTokenId).ConfigureAwait(false);
            var searchResult = await _client.User.SearchAsync(new UserSearchRequest { Limit = 10, UserRightsFilter = new List<UserRight> { UserRight.ManageContent } }).ConfigureAwait(false);

            var newUser = searchResult.Results.First(u => u.Id != previousOwner.Id);
            var request = new ContentOwnershipTransferRequest
            {
                TransferUserId = newUser.Id
            };
            await _client.Content.TransferOwnershipAsync(contentId, request).ConfigureAwait(false);

            var newContent = await _client.Content.GetAsync(contentId).ConfigureAwait(false);
            var newOwner = await _client.User.GetByOwnerTokenAsync(newContent.OwnerTokenId).ConfigureAwait(false);

            // Assert
            Assert.Equal(previousContent.Id, newContent.Id);
            Assert.NotEqual(previousContent.OwnerTokenId, newContent.OwnerTokenId);
            Assert.NotEqual(previousOwner.Id, newOwner.Id);
            Assert.Equal(newUser.Id, newOwner.Id);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldGetMany()
        {
            // Arrange
            var randomContents = await _fixture.GetRandomContentsAsync(".jpg", 2).ConfigureAwait(false);
            var contentIds = randomContents.Results.Select(i => i.Id).ToList();

            // Act
            var contents = await _client.Content.GetManyAsync(contentIds, new[] { ContentResolveBehavior.Owner, ContentResolveBehavior.Permissions }).ConfigureAwait(false);

            // Assert
            Assert.Equal(2, contents.Count);
            Assert.Equal(contentIds[0], contents.ToList()[0].Id);
            Assert.Equal(contentIds[1], contents.ToList()[1].Id);

            contents.Should().NotContainNulls(i => i.Owner);
            contents.Should().NotContainNulls(i => i.ContentRights);

            contents.ToList().ForEach(content =>
                {
                    content.Audit.CreatedByUser.Should().BeResolved();
                    content.Audit.ModifiedByUser.Should().BeResolved();
                }
            );
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldTransferOwnershipMany()
        {
            // Arrange
            var randomContents = await _fixture.GetRandomContentsAsync(".jpg", 2).ConfigureAwait(false);
            var contentIds = randomContents.Results.Select(i => i.Id).ToList();

            // Act
            var previousContents = await _client.Content.GetManyAsync(contentIds).ConfigureAwait(false);
            var previousOwner = await _client.User.GetByOwnerTokenAsync(previousContents.ToList()[0].OwnerTokenId).ConfigureAwait(false);

            // Search user with ManageContent UserRight
            var searchResult = await _client.User.SearchAsync(new UserSearchRequest
            {
                Limit = 10,
                UserRightsFilter = new List<UserRight> { UserRight.ManageContent }
            }).ConfigureAwait(false);

            var newUser = searchResult.Results.FirstOrDefault(u => u.Id != previousOwner.Id);
            newUser.Should().NotBeNull($"expected to have more users with {UserRight.ManageContent} user right in the tested customer to test content ownership transfer");
            var manyRequest = new ContentOwnershipTransferManyRequest
            {
                Items = contentIds.Select(id => new ContentOwnershipTransferItem
                {
                    ContentId = id,
                    TransferUserId = newUser.Id
                }).ToList()
            };

            await _client.Content.TransferOwnershipManyAsync(manyRequest).ConfigureAwait(false);

            var newContents = await _client.Content.GetManyAsync(contentIds).ConfigureAwait(false);
            var newOwner1 = await _client.User.GetByOwnerTokenAsync(newContents.ToList()[0].OwnerTokenId).ConfigureAwait(false);
            var newOwner2 = await _client.User.GetByOwnerTokenAsync(newContents.ToList()[1].OwnerTokenId).ConfigureAwait(false);

            // Assert
            Assert.Equal(previousContents.ToList()[0].Id, newContents.ToList()[0].Id);
            Assert.Equal(previousContents.ToList()[1].Id, newContents.ToList()[1].Id);

            Assert.Equal(newOwner1.Id, newOwner2.Id);
            Assert.Equal(newUser.Id, newOwner1.Id);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateWithAggregators()
        {
            var request = new ContentAggregationRequest
            {
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Aggregator1", Field = "contentType", Size = 10 }
                }
            };

            // Second Aggregator
            var ranges = new List<NumericRangeForAggregator>
            {
                new NumericRangeForAggregator { From = null, To = 499, Names = new TranslatedStringDictionary { { "en", "Aggregator2a" } } },
                new NumericRangeForAggregator { From = 500, To = 5000, Names = new TranslatedStringDictionary { { "en", "Aggregator2b" } } }
            };

            var numRangeAggregator = new NumericRangeAggregator()
            {
                Name = "NumberAggregator",
                Field = "Original.Width",
                Ranges = ranges
            };

            request.Aggregators.Add(numRangeAggregator);
            await _client.Content.AggregateAsync(request).ConfigureAwait(false);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldSearchAndAggregateAllTogether()
        {
            var request = new ContentSearchRequest
            {
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Aggregator1", Field = "contentType", Size = 10 }
                }
            };

            // Second Aggregator
            var ranges = new List<NumericRangeForAggregator>
            {
                new NumericRangeForAggregator { From = null, To = 499, Names = new TranslatedStringDictionary { { "en", "Aggregator2a" } } },
                new NumericRangeForAggregator { From = 500, To = 5000, Names = new TranslatedStringDictionary { { "en", "Aggregator2b" } } }
            };

            var numRangeAggregator = new NumericRangeAggregator()
            {
                Name = "NumberAggregator",
                Field = "Original.Width",
                Ranges = ranges
            };

            request.Aggregators.Add(numRangeAggregator);
            var result = await _client.Content.SearchAsync(request).ConfigureAwait(false);
            result.Results.Should().HaveCountGreaterThan(0);
            result.AggregationResults.Should().HaveCount(2);
            foreach (var resultAggregationResult in result.AggregationResults)
            {
                resultAggregationResult.AggregationResultItems.Should().HaveCountGreaterThan(1);
            }
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateByChannel()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentAggregationRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty
            };

            // Act
            var result = await _client.Content.AggregateOnChannelAsync(request).ConfigureAwait(false);

            // Assert
            var originalWidthResults = result.AggregationResults
                .SingleOrDefault(i => i.Name == "Original Width");

            Assert.NotNull(originalWidthResults);
            Assert.True(originalWidthResults.AggregationResultItems.Count > 0);
        }

        [Fact]
        [Trait("Stack", "Contents")]
        public async Task ShouldAggregateOnChannelWithTermsAggregator()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentAggregationRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Permissions", Field = "permissionSetIds", Size = 10 }
                }
            };

            // Act
            var result = await _client.Content.AggregateAsync(request).ConfigureAwait(false);

            // Assert
            var permissionSetResults = result.AggregationResults
                .SingleOrDefault(i => i.Name == "Permissions");

            Assert.NotNull(permissionSetResults);
            Assert.True(permissionSetResults.AggregationResultItems.Count > 0);
        }

        [Fact(Skip = "It must be re-enabled when url is accessible")]
        [Trait("Stack", "Contents")]
        public async Task ShouldSearchAndAggregateOnChannelWithTermsAggregator()
        {
            // Arrange
            var channelId = "rootChannel";
            var request = new ContentSearchRequest
            {
                ChannelId = channelId,
                SearchString = string.Empty,
                Aggregators = new List<AggregatorBase>
                {
                    new TermsAggregator { Name = "Permissions", Field = "permissionSetIds", Size = 10 }
                }
            };

            // Act
            var result = await _client.Content.SearchAsync(request).ConfigureAwait(false);

            // Assert
            result.Results.Should().HaveCountGreaterThan(0);
            var permissionSetAggregationResults = result.AggregationResults.SingleOrDefault(i => i.Name == "Permissions");
            permissionSetAggregationResults.Should().NotBeNull();
            permissionSetAggregationResults.AggregationResultItems.Should().HaveCountGreaterThan(0);
        }

        [Fact(Skip = "It must be re-enabled when url is accessible")]
        [Trait("Stack", "Contents")]
        public async Task ShouldCreateDownloadLinkForSingleFile()
        {
            // Arrange
            var contentId = await _fixture.GetRandomContentIdAsync("fileMetadata.fileExtension:.jpg", 50).ConfigureAwait(false);
            var createDownloadLinkRequest = new ContentDownloadLinkCreateRequest
            {
                Contents = new List<ContentDownloadRequestItem>
                {
                    new ContentDownloadRequestItem { ContentId = contentId, OutputFormatId = "Original" }
                }
            };

            // Act
            var result = await _client.Content.CreateDownloadLinkAsync(createDownloadLinkRequest).ConfigureAwait(false);
            Assert.NotNull(result.DownloadUrl);

            using (var httpClient = new HttpClient())
            using (var response = await httpClient.GetAsync(result.DownloadUrl).ConfigureAwait(false))
            {
                response.EnsureSuccessStatusCode();

                var fileName = response.Content.Headers.ContentDisposition.FileName.Replace("\"", string.Empty);
                Assert.EndsWith(".jpg", fileName);

                var filePath = Path.Combine(_fixture.TempDirectory, fileName);

                using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
                using (var fileStream = File.Create(filePath))
{'fraction_non_alphanumeric': 0.09513883426413908, 'fraction_numerical': 0.005938802800283175, 'mean_word_length': 2.0631249247078665, 'pattern_counts': {'":': 0, '<': 23, '<?xml version=': 0, '>': 49, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 19, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4436234', 'n_tokens_mistral': 6496, 'n_tokens_neox': 6297, 'n_words': 1194}