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 CreateSpecificationUnitTests : SpecificationManagerTestBase
{
    [SetUp]
    public override async Task Setup()
    {
        await base.Setup();
    }

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

        var createSpecification = new CreateSpecification
        {
            Site = new GeneralIdRef()
        };

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

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

        var site = new Site
        {
            Guid = new Guid("fbbaa30c-aaa8-4d21-8d00-898bbfdd6b74"),
            Id = 235,
            Name = "Bun Fight Factory"
        };
        SiteManagerRepository.Sites.Add( site);

        var createSpecification = new CreateSpecification
        {
            Site = new GeneralIdRef
            {
                Guid = site.Guid
            },
            FormInstanceId = new GeneralIdRef()
        };

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

    }

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

        var site = new Site
        {
            Guid = new Guid("fbbaa30c-aaa8-4d21-8d00-898bbfdd6b74"),
            Id = 235,
            Name = "Bun Fight Factory"
        };
        SiteManagerRepository.Sites.Add(site);

        var formInstance = new FormInstance
        {
            Guid = new Guid("cb3a91c8-9419-4815-9d52-d0f82946e5ef"),
            Id = 321412433
        };
        FormRepository.FormInstances.Add(formInstance);

        var createSpecification = new CreateSpecification
        {
            Guid = new Guid("e2f0165d-64b0-4bf7-a06a-a9c268cbb72e"),
            Name = "My new specification",
            Site = new GeneralIdRef
            {
                Guid = site.Guid
            },
            FormInstanceId = new GeneralIdRef
            {
                Guid = formInstance.Guid
            }
        };
        
        //Act
        await SpecificationManager.CreateSpecification(auditUserDetails, createSpecification, true, CancellationToken.None);

        //Assert
        Assert.Multiple(() =>
        {
            Assert.That(SpecificationManagerRepository.Specifications.Count, Is.EqualTo(1));
            var actualResult = SpecificationManagerRepository.Specifications[0];
            Assert.That(actualResult.Guid, Is.EqualTo(createSpecification.Guid));
            Assert.That(actualResult.Name, Is.EqualTo(createSpecification.Name));
            Assert.That(actualResult.Site.Guid, Is.EqualTo(site.Guid));
            Assert.That(actualResult.Site.Id, Is.EqualTo(site.Id));
            Assert.That(actualResult.FormInstanceId, Is.EqualTo(formInstance.Id));
            Assert.That(actualResult.Deleted, Is.False);
            EFlowSyncMessageSenderMock.Verify(x => x.SyncEFlowPrinterCategories(), Times.Once);
        });
    }
}