using e_suite.API.Common.exceptions;
using e_suite.API.Common.models;
using eSuite.Core.Miscellaneous;
using eSuite.Core.Sequences;
using NUnit.Framework;
using SequenceManager.UnitTests.Helpers;


namespace SequenceManager.UnitTests;

[TestFixture]
public class CreateSequenceUnitTests : SequenceManagerTestBase
{
    [SetUp]
    public override async Task Setup()
    {
        await base.Setup();
    }
    
    [Test]
    public async Task CreateSequence_EverythingCorrect_CreatesSequence()
    {
        // Arrange
        var sequence = new NewSequence
        {
            Guid = Guid.NewGuid(),
            Increment = 1,
            Name = $"Sequence name {Guid.NewGuid()}",
            Pattern = "Order-[000]",
            RolloverType = Rollover.Continuous,
            Seed = 1
        };


        // Act
        await SequenceManager.CreateSequence(AuditUserDetails, sequence, default);

        // Assert
        var createdSequence = await SequenceManagerRepository.GetSequenceByName(sequence.Name, default);
        Assert.That(createdSequence, Is.Not.Null);
        Assert.That(createdSequence.Name, Is.EqualTo(sequence.Name));
        Assert.That(createdSequence.Increment, Is.EqualTo(sequence.Increment));
        Assert.That(createdSequence.Guid, Is.EqualTo(sequence.Guid));
        Assert.That(createdSequence.Pattern, Is.EqualTo(sequence.Pattern));
        Assert.That(createdSequence.Seed, Is.EqualTo(sequence.Seed));
        Assert.That(createdSequence.Rollover, Is.EqualTo(sequence.RolloverType));
    }

    [Test]
    public void CreateSequence_SequenceNameAlreadyExists_ThrowsException()
    {
        // Arrange
        var guid = new Guid("{499D5186-3220-4940-80CD-36B531B6EBB7}");

        var sequence = new NewSequence
        {
            Guid = guid,
            Increment = 1,
            Name = "Sequence exists",
            Pattern = "Order [0000] from {DD}-{MM}-{YYYY}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

        SequenceManagerRepository.Sequences.Add( new e_suite.Database.Core.Tables.Sequences.Sequence()
        {
            Id = 1,
            Deleted = false,
            Seed = 1,
            Increment = 1,
            Guid = new Guid("{6B14CB6F-CDBA-4724-8F77-290F76E17E48}"),
            Name = sequence.Name,
            Pattern = "[0]",
            Rollover = Rollover.Continuous,
        });


        // Act & Assert
        Assert.ThrowsAsync<ExistsException>(async () =>
        {
            await SequenceManager.CreateSequence(AuditUserDetails, sequence, default);
        });
    }

    [Test]
    public void CreateSequence_GuidAlreadyExists_ThrowsException()
    {
        // Arrange
        var guid = new Guid("{499D5186-3220-4940-80CD-36B531B6EBB7}");

        var sequence = new NewSequence
        {
            Guid = guid,
            Increment = 1,
            Name = "Sequence exists",
            Pattern = "Order [0000] from {DD}-{MM}-{YYYY}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

        SequenceManagerRepository.Sequences.Add(new e_suite.Database.Core.Tables.Sequences.Sequence()
        {
            Id = 1,
            Deleted = false,
            Seed = 1,
            Increment = 1,
            Guid = guid,
            Name = "DuplicatedName",
            Pattern = "[0]",
            Rollover = Rollover.Continuous,
        });


        // Act & Assert
        Assert.ThrowsAsync<ExistsException>(async () =>
        {
            await SequenceManager.CreateSequence(AuditUserDetails, sequence, default);
        });
    }

    [Test]
    public async Task CreateSequence_DeletedSequence_UndeletesSequence()
    {
        //Arrange
        var guid = new Guid("{499D5186-3220-4940-80CD-36B531B6EBB7}");

        var sequence = new NewSequence
        {
            Guid = guid,
            Increment = 1,
            Name = "Sequence exists",
            Pattern = "Order [0000] from {DD}-{MM}-{YYYY}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

        SequenceManagerRepository.Sequences.Add(new e_suite.Database.Core.Tables.Sequences.Sequence()
        {
            Id = 1,
            Deleted = true,
            Seed = 1,
            Increment = 1,
            Guid = guid,
            Name = "Different Name",
            Pattern = "[0]",
            Rollover = Rollover.Continuous,
        });

        Assert.That(SequenceManagerRepository.Sequences.Count, Is.EqualTo(1));

        //Act
        await SequenceManager.CreateSequence(AuditUserDetails, sequence, default);

        //Assert
        var actualSequence = await SequenceManagerRepository.GetSequenceById(new GeneralIdRef() { Guid = guid }, default);

        Assert.That(SequenceManagerRepository.Sequences.Count, Is.EqualTo(1));

        Assert.That(actualSequence, Is.Not.Null);
        Assert.That(actualSequence.Deleted, Is.False);
        Assert.That(actualSequence.Name, Is.EqualTo(sequence.Name));
    }


    [Test]
    public async Task CreateSequence_UnDeletingSequenceUsingName_UndeletesSequence()
    {
        //Arrange
        var guid = new Guid("{499D5186-3220-4940-80CD-36B531B6EBB7}");

        var sequence = new NewSequence
        {
            Increment = 1,
            Name = "Sequence exists",
            Pattern = "Order [0000] from {DD}-{MM}-{YYYY}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

        SequenceManagerRepository.Sequences.Add(new e_suite.Database.Core.Tables.Sequences.Sequence()
        {
            Id = 1,
            Deleted = true,
            Seed = 1,
            Increment = 1,
            Guid = guid,
            Name = sequence.Name,
            Pattern = "[0]",
            Rollover = Rollover.Continuous,
        });

        Assert.That(SequenceManagerRepository.Sequences.Count, Is.EqualTo(1));

        //Act
        await SequenceManager.CreateSequence(AuditUserDetails, sequence, default);

        //Assert
        var actualSequence = await SequenceManagerRepository.GetSequenceById(new GeneralIdRef() { Guid = guid }, default);

        Assert.That(SequenceManagerRepository.Sequences.Count, Is.EqualTo(1));

        Assert.That(actualSequence, Is.Not.Null);
        Assert.That(actualSequence.Deleted, Is.False);
        Assert.That(actualSequence.Name, Is.EqualTo(sequence.Name));
    }
}