using e_suite.Database.Core.Extensions;
using e_suite.Database.Core.Extensions.Exceptions;
using e_suite.Database.Core.UnitTests.Models;
using eSuite.Core.Miscellaneous;
using NUnit.Framework;

namespace e_suite.Database.Core.UnitTests;

[TestFixture]
public class QueryableExtensionsIEnumerableUnitTests
{
    [Test]
    public void FindByGeneralIdRef_IdNotFound_ReturnsNull()
    {
        //Arrange
        var items = new List<TestCargo>
        {
            new()
            {
                Id = 1,
                Guid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}"),
                Name = "Test Item"
            }
        }.AsQueryable();

        //Act
        var generalIdRef = new GeneralIdRef
        {
            Id = 100
        };

        var list = new List<IGeneralIdRef>
        {
            generalIdRef
        };

        var result = items.FindByGeneralIdRef(list).ToArray();

        //Assert
        Assert.That(result.Length, Is.Zero);
    }

    [Test]
    public void FindByGeneralIdRef_IdFound_ReturnsExpectedValue()
    {
        //Arrange
        var keyId = 1;
        var keyGuid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}");

        var testItem = new TestCargo()
        {
            Id = keyId,
            Guid = keyGuid,
            Name = "Test Item"
        };

        var items = new List<TestCargo>
        {
            testItem
        }.AsQueryable();

        //Act
        var generalIdRef = new GeneralIdRef
        {
            Id = keyId
        };

        var list = new List<IGeneralIdRef>
        {
            generalIdRef
        };

        var result = items.FindByGeneralIdRef(list).ToArray();

        //Assert
        Assert.That(result.Length, Is.EqualTo(1));
        Assert.That(result.First(), Is.EqualTo(testItem));
    }

    [Test]
    public void FindByGeneralIdRef_GuidFound_ReturnsExpectedValue()
    {
        //Arrange
        var keyId = 1;
        var keyGuid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}");

        var testItem = new TestCargo()
        {
            Id = keyId,
            Guid = keyGuid,
            Name = "Test Item"
        };

        var items = new List<TestCargo>
        {
            testItem
        }.AsQueryable();

        //Act
        var generalIdRef = new GeneralIdRef
        {
            Guid = keyGuid
        };

        var list = new List<GeneralIdRef>
        {
            generalIdRef
        };

        var result = items.FindByGeneralIdRef(list).ToArray();

        //Assert
        Assert.That(result.Length, Is.EqualTo(1));
        Assert.That(result.First(), Is.EqualTo(testItem));
    }

    [Test]
    public void FindByGeneralIdRef_IdAndGuid_ReturnsExpectedValue()
    {
        //Arrange
        var keyId = 1;
        var keyGuid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}");

        var testItem = new TestCargo()
        {
            Id = keyId,
            Guid = keyGuid,
            Name = "Test Item"
        };

        var items = new List<TestCargo>
        {
            testItem
        }.AsQueryable();

        //Act
        var generalIdRef = new GeneralIdRef
        {
            Id = keyId,
            Guid = keyGuid
        };

        var list = new List<GeneralIdRef>
        {
            generalIdRef
        };

        var result = items.FindByGeneralIdRef(list).ToArray();

        //Assert
        Assert.That(result.Length, Is.EqualTo(1));
        Assert.That(result.First(), Is.EqualTo(testItem));
    }

    [Test]
    public void FindByGeneralIdRef_WrongIdAndCorrectGuid_ReturnsNullWhenIdDoesNotExist()
    {
        //Arrange
        var keyId = 1;
        var keyGuid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}");

        var testItem = new TestCargo()
        {
            Id = keyId,
            Guid = keyGuid,
            Name = "Test Item"
        };

        var items = new List<TestCargo>
        {
            testItem
        }.AsQueryable();

        var generalIdRef = new GeneralIdRef
        {
            Id = keyId + 1,
            Guid = keyGuid
        };

        var list = new List<GeneralIdRef>
        {
            generalIdRef
        };

        //Act & Assert
        Assert.Throws<IdMismatchException>(() => { var result = items.FindByGeneralIdRef(list).ToArray(); });
    }

    [Test]
    public void FindByGeneralIdRef_CorrectIdAndWrongGuid_ThrowsExpectedException()
    {
        //Arrange
        var keyId = 1;
        var keyGuid = new Guid("{F81F58DB-ACB0-404E-B5DB-C480DE3F2016}");
        var wrongGuid = new Guid("{C3BC5BAC-39F9-40B8-A191-0F25CD366FE4}");

        var testItem = new TestCargo
        {
            Id = keyId,
            Guid = keyGuid,
            Name = "Test Item"
        };

        var items = new List<TestCargo>
        {
            testItem
        }.AsQueryable();

        //Act and Assert
        var generalIdRef = new GeneralIdRef
        {
            Id = keyId,
            Guid = wrongGuid
        };

        var list = new List<GeneralIdRef>
        {
            generalIdRef
        };

        var result = Assert.Throws<GuidMismatchException>(() => { items.FindByGeneralIdRef(list).ToArray(); });

        Assert.That(result?.Message, Is.EqualTo($"The retrieved guid {keyGuid} does not match the expected guid {wrongGuid}"));
    }
}