using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Repositories;
using AsbCloudInfrastructure.Services;
using Microsoft.Extensions.Configuration;
using NSubstitute;
using Xunit;

namespace AsbCloudWebApi.Tests.UnitTests.Services;

public class HelpPageServiceTest
{
	private const string urlPage = "test";
	private const string fileName = "Справка_для_страницы_test.pdf";
	private const int idCategory = 20000;
	
	private static Dictionary<string, string> configSettings = new()
	{
		{ "DirectoryNameHelpPageFiles", "helpPages" }
	};
	
	private static readonly MemoryStream fileStream = new(Array.Empty<byte>());

	private static readonly HelpPageDto existingHelpPage = new()
	{
		Id = 178,
		IdCategory = idCategory,
		UrlPage = "test2",
		Name = "Справка_для_страницы_test2.pdf"
	};

	private readonly IHelpPageRepository helpPageRepositoryMock = Substitute.For<IHelpPageRepository>();
	private readonly IFileStorageRepository fileStorageRepositoryMock = Substitute.For<IFileStorageRepository>();

	private readonly HelpPageService helpPageService;

	public HelpPageServiceTest()
	{
		IConfiguration configuration = new ConfigurationBuilder()
			.AddInMemoryCollection(configSettings)
			.Build();

		helpPageRepositoryMock.GetOrDefaultByUrlPageAndIdCategoryAsync(existingHelpPage.UrlPage, existingHelpPage.IdCategory, Arg.Any<CancellationToken>())
			.Returns(existingHelpPage);

		helpPageRepositoryMock.InsertAsync(Arg.Any<HelpPageDto>(), Arg.Any<CancellationToken>())
			.ReturnsForAnyArgs(1);

		fileStorageRepositoryMock.SaveFileAsync(Arg.Any<string>(), Arg.Any<Stream>(), Arg.Any<CancellationToken>());

		helpPageService = new HelpPageService(helpPageRepositoryMock,
			fileStorageRepositoryMock,
			configuration);
	}

	[Fact]
	public async Task AddOrUpdateAsync_ShouldReturn_AddedHelpPage()
	{
		//act
		var result = await helpPageService.AddOrUpdateAsync(urlPage,
			idCategory,
			fileName,
			fileStream,
			CancellationToken.None);

		//assert
		await helpPageRepositoryMock.Received().InsertAsync(Arg.Any<HelpPageDto>(), Arg.Any<CancellationToken>());
		await fileStorageRepositoryMock.Received().SaveFileAsync(Arg.Any<string>(), Arg.Any<Stream>(), Arg.Any<CancellationToken>());
		
		Assert.NotEqual(existingHelpPage.Id, result);
		Assert.NotEqual(urlPage, existingHelpPage.UrlPage);
		Assert.NotEqual(fileName, existingHelpPage.Name);
		Assert.Equal(idCategory, existingHelpPage.IdCategory);
	}


	[Fact]
	public async Task UpdateAsync_ShouldReturn_UpdatedHelpPage()
	{
		//act
		var result = await helpPageService.AddOrUpdateAsync(existingHelpPage.UrlPage,
			existingHelpPage.IdCategory,
			existingHelpPage.Name,
			fileStream,
			CancellationToken.None);

		//assert
		await helpPageRepositoryMock.Received().UpdateAsync(Arg.Any<HelpPageDto>(), Arg.Any<CancellationToken>());
		await fileStorageRepositoryMock.Received().SaveFileAsync(Arg.Any<string>(), Arg.Any<Stream>(), Arg.Any<CancellationToken>());
		
		Assert.Equal(existingHelpPage.Id, result);
	}
}