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

namespace e_suite.Modules.SiteManager.UnitTests;

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

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

        var site = new Site
        {
            Guid = new Guid("3bc0da7a-342f-48cf-883c-26a95c285bc6")
        };
        SiteManagerRepository.Sites.Add(site);

        var createSite = new CreateSite
        {
            Guid = site.Guid
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<ExistsException>(async () =>
        {
            //Act
            await SiteManager.CreateSite(auditUserDetails, createSite, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("A site with this guid already exists"));
    }

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

        var organisation = new Organisation
        {
            Guid = new Guid("5da7a65a-b2e7-44d3-99b8-53608d731193"),
            Id = 324652,
            Name = "Testing Org"
        };
        OrganisationManagerRepository.Organisations.Add(organisation);

        var site = new Site
        {
            Guid = new Guid("3bc0da7a-342f-48cf-883c-26a95c285bc6"),
            Name = "My Site",
            Organisation = organisation,
            OrganisationId = organisation.Id
        };
        SiteManagerRepository.Sites.Add(site);
        

        var createSite = new CreateSite
        {
            Guid = new Guid("b459780e-e5ca-4631-ae28-4b4c177de7ab"),
            Name = site.Name,
            OrganisationId = new GeneralIdRef()
                {Guid = organisation.Guid}
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<ExistsException>(async () =>
        {
            //Act
            await SiteManager.CreateSite(auditUserDetails, createSite, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("A site with this name already exists"));
    }

    [Test]
    public void CreateSite_OrganisationNotFound_ThrowsException()
    {
        //Arrange
        var auditUserDetails = new AuditUserDetails
        {
            UserId = 21345,
            UserDisplayName = "Testy McTester",
            Comment = string.Empty
        };
        
        var createSite = new CreateSite
        {
            Guid = new Guid("2607c6f4-6d2e-41b7-a173-468c664530ee"),
            OrganisationId = new GeneralIdRef
            {
                Guid = new Guid("60d672ef-85b0-4c86-b190-8fd24489b04e")
            }
        };

        //Assert
        var actualResult = Assert.ThrowsAsync<NotFoundException>(async () =>
        {
            //Act
            await SiteManager.CreateSite(auditUserDetails, createSite, true, CancellationToken.None);
        });
        Assert.That(actualResult!.Message, Is.EqualTo("Organisation not found"));
    }

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

        var organisation = new Organisation
        {
            Guid = new Guid("6c06d1b2-8abe-40a2-b6ba-d5bb80ae27f7"),
            Id = 2356,
            Name = "Bubba Gump Shrimp Company"
        };
        OrganisationManagerRepository.Organisations.Add(organisation);
        
        var createSite = new CreateSite
        {
            Guid = new Guid("2607c6f4-6d2e-41b7-a173-468c664530ee"),
            OrganisationId = new GeneralIdRef
            {
                Guid = organisation.Guid
            },
            Name = "South Carolina Dock",
            Address = "End of the pier, next to the sea",
            Status = OrganisationStatus.Active
        };
        
        //Act
        await SiteManager.CreateSite(auditUserDetails, createSite, true, CancellationToken.None);

        //Assert
        Assert.That(SiteManagerRepository.Sites.Count, Is.EqualTo(1));

        var actualSite = SiteManagerRepository.Sites[0];
        Assert.That(actualSite.Guid, Is.EqualTo(createSite.Guid));
        Assert.That(actualSite.OrganisationId, Is.EqualTo(organisation.Id));
        Assert.That(actualSite.Name, Is.EqualTo(createSite.Name));
        Assert.That(actualSite.Address, Is.EqualTo(createSite.Address));
        Assert.That(actualSite.Status, Is.EqualTo(createSite.Status));
        EFlowSyncMessageSenderMock.Verify( x => x.SyncEFlowPrinterCategories(), Times.Once);
    }

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

        var organisation = new Organisation
        {
            Guid = new Guid("6c06d1b2-8abe-40a2-b6ba-d5bb80ae27f7"),
            Id = 2356,
            Name = "Bubba Gump Shrimp Company"
        };
        OrganisationManagerRepository.Organisations.Add(organisation);

        var organisation2 = new Organisation
        {
            Guid = new Guid("fd15a215-2503-476b-92ac-5ac5e52173c1"),
            Id = 9283475,
            Name = "Pro Shrimp UK"
        };
        OrganisationManagerRepository.Organisations.Add(organisation2);

        var createSite = new CreateSite
        {
            Guid = new Guid("2607c6f4-6d2e-41b7-a173-468c664530ee"),
            OrganisationId = new GeneralIdRef
            {
                Guid = organisation.Guid
            },
            Name = "South Carolina Dock",
            Address = "End of the pier, next to the sea",
            Status = OrganisationStatus.Active
        };

        var createSite2 = new CreateSite
        {
            Guid = new Guid("8b58c30c-873b-448a-abaa-e2e7d0d60fa7"),
            OrganisationId = new GeneralIdRef
            {
                Guid = organisation2.Guid
            },
            Name = "South Carolina Dock",
            Address = "End of the pier, next to the sea, Next to Bubba Gump",
            Status = OrganisationStatus.Active
        };

        await SiteManager.CreateSite(auditUserDetails, createSite, true, CancellationToken.None);

        //Act
        await SiteManager.CreateSite(auditUserDetails, createSite2, true, CancellationToken.None);

        //Assert
        Assert.That(SiteManagerRepository.Sites.Count, Is.EqualTo(2));

        var actualSite = SiteManagerRepository.Sites[1];
        Assert.That(actualSite.Guid, Is.EqualTo(createSite2.Guid));
        Assert.That(actualSite.OrganisationId, Is.EqualTo(organisation2.Id));
        Assert.That(actualSite.Name, Is.EqualTo(createSite2.Name));
        Assert.That(actualSite.Address, Is.EqualTo(createSite2.Address));
        Assert.That(actualSite.Status, Is.EqualTo(createSite2.Status));
        EFlowSyncMessageSenderMock.Verify(x => x.SyncEFlowPrinterCategories(), Times.Exactly(2));
    }
}