using Moq;
using NUnit.Framework;

namespace e_suite.Database.Core.UnitTests;

[TestFixture]
public class RepositoryBaseUnitTests
{
    private Mock<IEsuiteDatabaseDbContext> _mockDatabaseContext = null!;

    private RepositoryBase repositoryBase = null!;

    [SetUp]
    public void Setup()
    {
        _mockDatabaseContext = new Mock<IEsuiteDatabaseDbContext>();

        repositoryBase = new RepositoryBase(_mockDatabaseContext.Object);
    }

    private bool taskHasBeenCalled;

    private Task Action()
    {
        taskHasBeenCalled = true;
        return Task.CompletedTask;
    }

    [Test]
    public async Task TransactionAsync_CalledWithAction_CallsTheVersionInTheDatabaseContext()
    {
        //Arrange
        taskHasBeenCalled = false;

        _mockDatabaseContext.Setup(x => x.TransactionAsync(It.IsAny<Task>)).Returns(Action());

        //Act
        await repositoryBase.TransactionAsync(Action);

        //Assert
        Assert.That(taskHasBeenCalled, Is.True);
        _mockDatabaseContext.Verify( x => x.TransactionAsync(It.IsAny<Func<Task>>()), Times.Once);
    }

    private bool funcHasBeenCalled;

    private Task<bool> Function()
    {
        funcHasBeenCalled = true;
        return Task.FromResult(true);
    }

    [Test]
    public async Task TransactionAsync_CalledWithFunction_CallsTheVersionInTheDatabaseContext()
    {
        //Arrange
        funcHasBeenCalled = false;

        _mockDatabaseContext.Setup(x => x.TransactionAsync<bool>(It.IsAny<Func<Task<bool>>>())).Returns(Function());

        //Act
        var result = await repositoryBase.TransactionAsync(Function);

        //Assert
        Assert.That(funcHasBeenCalled, Is.True);
        Assert.That(result, Is.True);
    }
}