using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using e_suite.Database.Audit;
using e_suite.Database.Core.Tables.Forms;
using e_suite.Database.Core.Tables.Printer;
using e_suite.Modules.SpecificationManager.UnitTests.Helpers;
using eSuite.Core.Miscellaneous;
using Moq;
using NUnit.Framework;

namespace e_suite.Modules.SpecificationManager.UnitTests;

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

    [Test]
    public void EditSpecification_WhenSpecificationNotFound_ThrowsNotFoundException()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 2345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };

        var edit = new EditSpecification
        {
            Id = new GeneralIdRef
            {
                Guid = new Guid("f3bdf80c-0ce7-47f9-8793-368637f88338")
            }
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await SpecificationManager.EditSpecification(auditUserDetails, edit, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("Specification not found"));
    }

    [Test]
    public void EditSpecification_WhenSiteNotFound_ThrowsNotFoundException()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 2345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };

        var formInstance = new FormInstance
        {
            Guid = new Guid("ea9f447d-4318-4a1d-8f51-fc4894392110"),
            Id = 23985476
        };
        FormRepository.FormInstances.Add(formInstance);

        var site = new Site
        {
            Guid = new Guid("532c5a1d-78dd-42e9-9d44-2a60950d1657"),
            Id = 123521345
        };
        SiteManagerRepository.Sites.Add(site);

        var specification = new Specification
        {
            Guid = new Guid("ff34b451-5459-4200-8e72-897e50e18a0e"),
            Id = 12341,
            FormInstanceId = formInstance.Id,
            Site = site,
            SiteId = site.Id
        };
        SpecificationManagerRepository.Specifications.Add(specification);

        var edit = new EditSpecification
        {
            Id = new GeneralIdRef
            {
                Guid = specification.Guid
            },
            Site = new GeneralIdRef
            {
                Guid = new Guid("5c890f1b-3c2c-482f-876a-cdcb1fbbfcd7")
            },
            FormInstanceId = new GeneralIdRef(){ Id = formInstance.Id },
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await SpecificationManager.EditSpecification(auditUserDetails, edit, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("Site not found"));
    }

    [Test]
    public void EditSpecification_WhenFormInstanceNotFound_ThrowsNotFoundException()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 2345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };

        var specification = new Specification
        {
            Guid = new Guid("ff34b451-5459-4200-8e72-897e50e18a0e"),
            Id = 12341
        };
        SpecificationManagerRepository.Specifications.Add(specification);

        var site = new Site
        {
            Guid = new Guid("532c5a1d-78dd-42e9-9d44-2a60950d1657"),
            Id = 123521345
        };
        SiteManagerRepository.Sites.Add(site);

        var edit = new EditSpecification
        {
            Id = new GeneralIdRef
            {
                Guid = specification.Guid
            },
            Site = new GeneralIdRef
            {
                Guid = site.Guid
            },
            FormInstanceId = new GeneralIdRef
            {
                Guid = new Guid("223584da-3303-4fc4-b72c-8ebf692e02fa")
            }
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await SpecificationManager.EditSpecification(auditUserDetails, edit, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("Form instance not found"));
    }

    [Test]
    public async Task EditSpecification_WhenEverythingFound_EditsSite()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 2345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };

        var formInstance = new FormInstance
        {
            Guid = new Guid("ea9f447d-4318-4a1d-8f51-fc4894392110"),
            Id = 23985476
        };
        FormRepository.FormInstances.Add(formInstance);

        var site = new Site
        {
            Guid = new Guid("532c5a1d-78dd-42e9-9d44-2a60950d1657"),
            Id = 123521345
        };
        SiteManagerRepository.Sites.Add(site);

        var specification = new Specification
        {
            Guid = new Guid("ff34b451-5459-4200-8e72-897e50e18a0e"),
            Id = 12341,
            FormInstanceId = formInstance.Id,
            Site = site,
            SiteId = site.Id
        };
        SpecificationManagerRepository.Specifications.Add(specification);

        var edit = new EditSpecification
        {
            Id = new GeneralIdRef
            {
                Guid = specification.Guid
            },
            Site = new GeneralIdRef
            {
                Guid = site.Guid
            },
            FormInstanceId = new GeneralIdRef
            {
                Guid = formInstance.Guid
            }
        };

        //Act
        await SpecificationManager.EditSpecification(auditUserDetails, edit, true, CancellationToken.None);

        //Assert
        Assert.That(SpecificationManagerRepository.EditedSpecification, Is.Not.Null);
        Assert.That(SpecificationManagerRepository.EditedSpecification!.Id, Is.EqualTo(specification.Id));
        Assert.That(SpecificationManagerRepository.EditedSpecification.Site, Is.EqualTo(site));
        Assert.That(SpecificationManagerRepository.EditedSpecification.FormInstanceId, Is.EqualTo(formInstance.Id));
        EFlowSyncMessageSenderMock.Verify(x => x.SyncEFlowPrinterCategories(), Times.Once);
    }

    [Test]
    public async Task EditSpecification_WhenSiteChanged_EditsSite()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 2345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };

        var formInstance = new FormInstance
        {
            Guid = new Guid("ea9f447d-4318-4a1d-8f51-fc4894392110"),
            Id = 23985476
        };
        FormRepository.FormInstances.Add(formInstance);

        var site = new Site
        {
            Guid = new Guid("532c5a1d-78dd-42e9-9d44-2a60950d1657"),
            Id = 123521345
        };
        SiteManagerRepository.Sites.Add(site);

        var specification = new Specification
        {
            Guid = new Guid("ff34b451-5459-4200-8e72-897e50e18a0e"),
            Id = 12341,
            FormInstanceId = formInstance.Id,
            Site = site,
            SiteId = site.Id
        };
        SpecificationManagerRepository.Specifications.Add(specification);

        var newSite = new Site
        {
            Guid = new Guid("8B8418A3-7DD0-4539-BA1A-76A8D381DA5C"),
            Id = 123521346
        };
        SiteManagerRepository.Sites.Add(newSite);

        var edit = new EditSpecification
        {
            Id = new GeneralIdRef
            {
                Guid = specification.Guid
            },
            Site = new GeneralIdRef
            {
                Guid = newSite.Guid
            },
            FormInstanceId = new GeneralIdRef
            {
                Guid = formInstance.Guid
            }
        };

        //Act
        await SpecificationManager.EditSpecification(auditUserDetails, edit, true, CancellationToken.None);

        //Assert
        Assert.That(SpecificationManagerRepository.EditedSpecification, Is.Not.Null);
        Assert.That(SpecificationManagerRepository.EditedSpecification!.Id, Is.EqualTo(specification.Id));
        Assert.That(SpecificationManagerRepository.EditedSpecification.Site, Is.EqualTo(newSite));
        Assert.That(SpecificationManagerRepository.EditedSpecification.FormInstanceId, Is.EqualTo(formInstance.Id));
        EFlowSyncMessageSenderMock.Verify(x => x.SyncEFlowPrinterCategories(), Times.Once);
    }
}