using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using e_suite.Database.Audit;
using e_suite.Database.Core.Tables.Glossaries;
using eSuite.Core.Miscellaneous;
using GlossariesManager.UnitTests.Helpers;
using NUnit.Framework;

namespace GlossariesManager.UnitTests;

[TestFixture]
public class GetGlossaryUnitTest : GlossariesManagerTestBase
{
    [SetUp]
    public override async Task Setup()
    {
        await base.Setup();
    }

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

        var glossaryItem = new NewGlossaryItem
        {
            Guid = new Guid("01293627-166f-4e10-9967-4a9215aefd2c"),
            Name = "LithoSpec",
            ChildCustomFieldDefinition = new List<GeneralIdRef>
            {
                new()
                {
                    Guid = new Guid("{AA4D6C9C-EFE5-495B-993E-97C977EDF9D7}")
                },
                new()
                {
                    Guid = new Guid("{67E85B6D-B25D-4AA7-8148-0B52BA694967}")
                }
            }
        };

        await GlossariesManager.AddGlossaryItem(auditUserDetails, glossaryItem, default);

        // Act
        var glossary = await GlossariesManager.GetGlossaryItem(auditUserDetails, new GeneralIdRef { Guid = glossaryItem.Guid }, default);

        // Assert
        Assert.Multiple(() =>
        {
            Assert.That(glossary, Is.Not.Null);
            Assert.That(glossary?.Name, Is.EqualTo(glossaryItem.Name));
        });
    }

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

        var glossaryItem = new NewGlossaryItem
        {
            Guid = new Guid("54952d68-5702-4f93-9b1b-23b49df80bcc"),
            Name = "LithoSpec",
            ChildCustomFieldDefinition = new List<GeneralIdRef>
            {
                new()
                {
                    Guid = new Guid("{AA4D6C9C-EFE5-495B-993E-97C977EDF9D7}")
                },
                new()
                {
                    Guid = new Guid("{67E85B6D-B25D-4AA7-8148-0B52BA694967}")
                }
            }
        };

        await GlossariesManager.AddGlossaryItem(auditUserDetails, glossaryItem, default);

        
        // Assert
        Assert.ThrowsAsync<NotFoundException>(
            // Act
            async () => await GlossariesManager.GetGlossaryItem(auditUserDetails, new GeneralIdRef
            {
                Guid = new Guid("2d2bacf4-0945-4f42-ba07-e436d2e559e5")
            }, default));
    }

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

        var glossaryItem = new NewGlossaryItem
        {
            Guid = new Guid("051cf552-65a6-494a-b4dd-4b671f8b1de1"),
            Name = "ParemtItem",
        };
        await GlossariesManager.AddGlossaryItem(auditUserDetails, glossaryItem, default);

        var childGlossaryItem = new NewGlossaryItem
        {
            Guid = new Guid("d792480c-9f22-42d5-b8eb-c6da1c664ed7"),
            Name = "Child Item",
            Parent = new GeneralIdRef
            {
                Guid = glossaryItem.Guid,
            }
        };
        await GlossariesManager.AddGlossaryItem(auditUserDetails, childGlossaryItem, default);

        //Act
        var glossary = await GlossariesManager.GetGlossaryItem(auditUserDetails, new GeneralIdRef { Guid = glossaryItem.Guid }, default);

        //Assert
        Assert.Multiple(() =>
        {
            Assert.That(glossary, Is.Not.Null);
            Assert.That(glossary!.Guid, Is.EqualTo(glossaryItem.Guid));
            Assert.That(glossary!.Children, Is.Not.Null);
            Assert.That(glossary!.Children!.Count, Is.EqualTo(1));
            Assert.That(glossary!.Children![0].Guid, Is.EqualTo(childGlossaryItem.Guid));
        });
    }

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

        GlossariesManagerRepository.Glossaries.Add(new Glossary
        {
            Id = 1,
            Guid = new Guid("{FA6566F8-B4B0-48C5-9985-336C9284796E}"),
            Name = "System"
        });

        GlossariesManagerRepository.Glossaries.Add( new Glossary
        {
            Id = 3,
            Guid = new Guid("2d2bacf4-0945-4f42-ba07-e436d2e559e5"),
            Name = "Categories",
            ParentId = 1
        } );

        GlossariesManagerRepository.Glossaries.Add(new Glossary
        {
            Id = 4,
            Guid = new Guid("51fb0e6a-6855-495e-bc9f-8d11036f3b7d"),
            Name = "Star Wars Vehicles",
            ParentId = 3
        });

        GlossariesManagerRepository.Glossaries.Add(new Glossary
        {
            Id = 5,
            Guid = new Guid("ff9fcd3c-c644-4a13-a704-03f940275e77"),
            Name = "Rebel Alliance",
            ParentId = 4
        });

        GlossariesManagerRepository.Glossaries.Add(new Glossary
        {
            Id = 6,
            Guid = new Guid("45317c71-a13c-471d-8fe3-70c331cbebf2"),
            Name = "Star Fighers",
            ParentId = 5
        });

        var xWingGuid = new Guid("02f2800a-b5d5-45a2-b573-186595c56e5c");
        GlossariesManagerRepository.Glossaries.Add(new Glossary
        {
            Id = 7,
            Guid = xWingGuid,
            Name = "X-Wing",
            ParentId = 6
        });

        //Act
        var glossary = await GlossariesManager.GetGlossaryItem(auditUserDetails, new GeneralIdRef { Guid = xWingGuid }, default);

        //Assert
        var parentChain = new List<long>
        {
            7,
            6,
            5,
            4,
            3,
            1
        };

        Assert.That(glossary, Is.Not.Null);

        var glossaryToCheck = glossary;
        foreach (var item in parentChain)
        {
            Assert.That(glossaryToCheck, Is.Not.Null);
            Assert.That(glossaryToCheck!.Id, Is.EqualTo(item));
            glossaryToCheck = glossaryToCheck.Parent;
        }
    }
}