using ApplicationLayer.GeneralExceptions;
using Domains.Users;
using FluentAssertions;
using Infrastructure.Database;
using Infrastructure.Database.Generic;
using Xunit;
namespace VisaApi.Tests.Infrastructure.Database.Repositories.Generic;
[Collection(Collections.ContextUsingTestCollection)]
public class GenericRepositoryTests
{
    ///  Returns  
    ///  Database context 
    /// Repository
    private static GenericRepository GetRepository(DatabaseContext context) => new TestGenericRepository(context, context);
    ///  Test for  method that should return empty collection if nothing added 
    [Fact]
    public void GetAllForEmptyShouldReturnEmpty()
    {
        using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        var result = repository.GetAllAsync(CancellationToken.None).Result;
        result.Should().BeEmpty();
    }
    ///  Test for  method that should return collection with added entities 
    [Fact]
    public void GetAllForNotEmptyShouldReturnEntities()
    {
        using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        User[] users =
        [
            new() { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin },
            new() { Email = "bruh@mail.ru", Password = "123", Role = Role.Applicant }
        ];
        foreach (var user in users)
        {
            repository.AddAsync(user, CancellationToken.None).Wait();
        }
        context.SaveChanges();
        var result = repository.GetAllAsync(CancellationToken.None).Result;
        result.Should().Contain(users).And.HaveSameCount(users);
    }
    ///  Test for  method that should return existing entity 
    [Fact]
    public void GetByIdForExistingShouldReturnEntity()
    {
        using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        var user = new User { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin };
        repository.AddAsync(user, CancellationToken.None).Wait();
        context.SaveChanges();
        var result = repository.GetByIdAsync(user.Id, CancellationToken.None).Result;
        result.Should().Be(user);
    }
    ///  Test for  method that should throw exception for not found entity 
    [Fact]
    public void GetByIdForNotExistingShouldThrow()
    {
        using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        context.SaveChanges();
        EntityNotFoundByIdException? result = null;
        try
        {
            repository.GetByIdAsync(Guid.NewGuid(), CancellationToken.None).Wait();
        }
        catch (AggregateException e)
        {
            result = e.InnerException as EntityNotFoundByIdException;
        }
        result.Should().NotBeNull();
    }
}