using e_suite.Database.Audit.UnitTests.Helpers;
using e_suite.Database.Audit.UnitTests.Helpers.Tables;
using NUnit.Framework;

namespace e_suite.Database.Audit.UnitTests.AuditEngineCore;

[TestFixture]
public class AdvancedUnitTests : AuditEngineCoreTestBase
{
    [TestCase("")]
    [TestCase("Test Comment")]
    public async Task CreatingAuditRecord_WhenItemDoesNotHaveParentLoaded_ParentIsLoadedOnDemand(string auditComment)
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy McTester",
            Comment = auditComment
        };

        var rootSimpleTreeValue = new SimpleTreeValue
        {
            Name = "Leaf Level item",
            ParentId = null
        };

        testDBContext.SimpleTreeValues.Add(rootSimpleTreeValue);
        await testDBContext.NoAuditSaveChangesAsync();

        var level1SimpleTreeValue = new SimpleTreeValue
        {
            Name = "Level 1 item",
            ParentId = rootSimpleTreeValue.Id
        };

        testDBContext.SimpleTreeValues.Add(level1SimpleTreeValue);
        await testDBContext.NoAuditSaveChangesAsync();

        var level2SimpleTreeValue = new SimpleTreeValue
        {
            Name = "Leaf Level item",
            ParentId = level1SimpleTreeValue.Id
        };

        testDBContext.SimpleTreeValues.Add(level2SimpleTreeValue);
        await testDBContext.NoAuditSaveChangesAsync();

        //Act
        var secondDbContext = testDbContextFactory.CreateContext(_clockMock.Object);
        
        var itemUnderTest = secondDbContext.SimpleTreeValues
            .Single(x => x.Id == level2SimpleTreeValue.Id);
        itemUnderTest.Name = "A Change";

        Assert.That(itemUnderTest.Parent, Is.Null); //should be null

        await secondDbContext.SaveChangesAsync(auditUserDetails);

        //Assert
        Assert.That(itemUnderTest.Parent, Is.Not.Null);
        Assert.That(itemUnderTest.Parent.Id, Is.EqualTo(level1SimpleTreeValue.Id));

        Assert.That(itemUnderTest.Parent.Parent, Is.Not.Null);
        Assert.That(itemUnderTest.Parent.Parent.Id, Is.EqualTo(rootSimpleTreeValue.Id));

        Assert.That(itemUnderTest.Parent.Parent.Parent, Is.Null);
    }

    [Test]
    public async Task CreatingAuditRecord_WhenAuditNameNeedsForeignKeyResolved_ParentIsLoadedOnDemand()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserDisplayName = "Testy McTester",
            Comment = ""
        };

        var grandParentValue = new GrandParentValue
        {
            Name = "Grandparent Value",
            Id = 100
        };

        testDBContext.GrandParentValues.Add(grandParentValue);
        await testDBContext.NoAuditSaveChangesAsync();

        var linkedEntryWithName = new LinkedEntryWithName
        {
            Id = 50,
            LinkId = grandParentValue.Id
        };
        testDBContext.LinkedEntryWithName.Add(linkedEntryWithName);
        await testDBContext.NoAuditSaveChangesAsync();

        //Act
        var secondDbContext = testDbContextFactory.CreateContext(_clockMock.Object);

        var itemUnderTest = secondDbContext.LinkedEntryWithName
            .Single(x => x.Id == linkedEntryWithName.Id);
        
        Assert.That(itemUnderTest.GrandParentValue, Is.Null); //should be null

        itemUnderTest.SomethingToChange = "A new Value";

        await secondDbContext.SaveChangesAsync(auditUserDetails);

        //Assert
        Assert.That(itemUnderTest.GrandParentValue, Is.Not.Null);
        Assert.That(itemUnderTest.GrandParentValue.Id, Is.EqualTo(linkedEntryWithName.LinkId));
    }
}