using ApplicationLayer.GeneralExceptions;
using Domains.Users;
using FluentAssertions;
using Infrastructure.Database;
using Infrastructure.Database.Generic;
namespace VisaApi.Database.Repositories.Generic;
public class GenericRepositoryTests
{
    ///  Returns  
    ///  Database context 
    /// Repository
    private static GenericRepository GetRepository(DbContext context) => new TestGenericRepository(context, context);
    ///  Test for  method that should return empty collection if nothing added 
    [Fact]
    public async Task GetAllForEmptyShouldReturnEmpty()
    {
        await using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        var result = await repository.GetAllAsync(CancellationToken.None);
        result.Should().BeEmpty();
    }
    ///  Test for  method that should return collection with added entities 
    [Fact]
    public async Task GetAllForNotEmptyShouldReturnEntities()
    {
        await 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)
        {
            await repository.AddAsync(user, CancellationToken.None);
        }
        await context.SaveChangesAsync();
        var result = await repository.GetAllAsync(CancellationToken.None);
        result.Should().OnlyContain(user => users.Contains(user));
    }
    ///  Test for  method that should return existing entity 
    [Fact]
    public async Task GetByIdForExistingShouldReturnEntity()
    {
        await using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        var user = new User { Email = "nasrudin@mail.ru", Password = "12345", Role = Role.Admin };
        await repository.AddAsync(user, CancellationToken.None);
        await context.SaveChangesAsync();
        var result = await repository.GetByIdAsync(user.Id, CancellationToken.None);
        result.Should().Be(user);
    }
    ///  Test for  method that should throw exception for not found entity 
    [Fact]
    public async Task GetByIdForNotExistingShouldThrow()
    {
        await using var context = InMemoryContextProvider.GetDbContext();
        var repository = GetRepository(context);
        await context.SaveChangesAsync();
        EntityNotFoundByIdException? result = null;
        try
        {
            await repository.GetByIdAsync(Guid.NewGuid(), CancellationToken.None);
        }
        catch (Exception e)
        {
            result = e as EntityNotFoundByIdException;
        }
        result.Should().NotBeNull();
    }
}