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

namespace AsbCloudWebApi.Tests.ServicesTests;

public class HelpPageServiceTest
{
    private static Dictionary<string, string> configSettings = new (){
        {"DirectoryNameHelpPageFiles", "helpPages"}
    };

    private static List<HelpPageDto> HelpPages = new()
    {
        new()
        {
            Id = 123,
            IdCategory = 20000,
            Name = "Справка1.pdf",
            Size = 54000,
            UrlPage = "test"
        },
        new()
        {
            Id = 134,
            IdCategory = 20000,
            Name = "Справка2.pdf",
            Size = 51000,
            UrlPage = "test1"
        },
        new()
        {
            Id = 178,
            IdCategory = 10000,
            Name = "Справка3.pdf",
            Size = 49000,
            UrlPage = "test2"
        }
    };

    private readonly Mock<IHelpPageRepository> helpPageRepository = new();
    private readonly Mock<IFileStorageRepository> fileStorageRepository = new();

    private readonly IHelpPageService helpPageService;

    public HelpPageServiceTest()
    {
        IConfiguration configuration = new ConfigurationBuilder()
            .AddInMemoryCollection(configSettings)
            .Build();
        
        helpPageService = new HelpPageService(helpPageRepository.Object,
            fileStorageRepository.Object,
            configuration);
    }

    [Fact]
    public async Task AddOrUpdateAsync_ShouldReturn_NewHelpPage()
    {
        //arrange
        int idHelpPage = new Random().Next(1, 100);
        string urlPage = "test";
        int idCategory = 20000;
        string fileName = "test.pdf";
        MemoryStream fileStream = new MemoryStream(Array.Empty<byte>());

        helpPageRepository.Setup(x => x.GetOrDefaultByUrlPageAndIdCategoryAsync(It.IsAny<string>(),
            It.IsAny<int>(), It.IsAny<CancellationToken>()))
            .Returns(() =>
            {
                var helpPage = HelpPages.FirstOrDefault(x =>
                    x.UrlPage == urlPage &&
                    x.IdCategory == idCategory);

                return Task.FromResult(helpPage);
            });

        helpPageRepository.Setup(x => x.InsertAsync(It.IsAny<HelpPageDto>(),
                It.IsAny<CancellationToken>()))
            .Returns(() => Task.FromResult(idHelpPage));

        fileStorageRepository.Setup(x => x.SaveFileAsync(It.IsAny<string>(),
            It.IsAny<Stream>(),
            It.IsAny<CancellationToken>()));
        
        //act
        int result = await helpPageService.AddOrUpdateAsync(urlPage,
            idCategory,
            fileName,
            fileStream,
            CancellationToken.None);

        //assert
        Assert.True(result > 0);
    }


    [Fact]
    public async Task UpdateAsync_ShouldReturn_UpdatedHelpPage()
    {
        //arrange
        int idHelpPage = new Random().Next(1, 100);
        string urlPage = "test";
        int newIdCategory = 20000;
        string newFileName = "test.pdf";
        MemoryStream newFileStream = new MemoryStream(Array.Empty<byte>());
        HelpPageDto existingHelpPage = HelpPages.First(x =>
            x.UrlPage == urlPage &&
            x.IdCategory == newIdCategory);

        helpPageRepository.Setup(x => x.GetOrDefaultByUrlPageAndIdCategoryAsync(It.IsAny<string>(),
            It.IsAny<int>(), It.IsAny<CancellationToken>()))
            .Returns(() => Task.FromResult(existingHelpPage)!);

        helpPageRepository.Setup(x => x.InsertAsync(It.IsAny<HelpPageDto>(),
                It.IsAny<CancellationToken>()))
            .Returns(() => Task.FromResult(idHelpPage));

        fileStorageRepository.Setup(x => x.SaveFileAsync(It.IsAny<string>(),
            It.IsAny<Stream>(),
            It.IsAny<CancellationToken>()));

        //act
        await helpPageService.AddOrUpdateAsync(urlPage,
            newIdCategory,
            newFileName,
            newFileStream,
            CancellationToken.None);

        //assert
        Assert.Equal(newFileName, existingHelpPage.Name);
        Assert.Equal(newIdCategory, existingHelpPage.IdCategory);
        Assert.Equal(newFileStream.Length, existingHelpPage.Size);
    }
}