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

    [Test]
    public void EditSequence_SequenceNotFound_ThrowsException()
    {
        // Arrange
        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Guid = Guid.NewGuid() },
            Increment = 1,
            Name = "Sequence name",
            Pattern = "{DD}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

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

    [Test]
    public void EditSequence_SequenceDeleted_ThrowsException()
    {
        // Arrange
        SequenceManagerRepository.Sequences.Add(
            new e_suite.Database.Core.Tables.Sequences.Sequence
            {
                Id = 2,
                Guid = new Guid("{BCD24EAE-6232-4E07-B7FB-230E3DD8A463}"),
                Increment = 1,
                Name = "Existing sequence",
                Pattern = "[0]",
                Seed = 1,
                Rollover = Rollover.Continuous,
                Deleted = true
            });

        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Guid = new Guid("{BCD24EAE-6232-4E07-B7FB-230E3DD8A463}") },
            Increment = 1,
            Name = "Sequence name",
            Pattern = "{DD}",
            RolloverType = Rollover.Day,
            Seed = 1
        };


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

    [Test]
    public void EditSequence_SequenceNameAlreadyUsed_ThrowException()
    {
        // Arrange
        SequenceManagerRepository.Sequences.Add(
            new e_suite.Database.Core.Tables.Sequences.Sequence
            {
                Id = 1,
                Guid = Guid.NewGuid(),
                Increment = 1,
                Name = "Test sequence",
                Pattern = "[0]",
                Seed = 1,
                Rollover = Rollover.Continuous
            });

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

        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Id = 1 },
            Increment = 1,
            Name = "Existing sequence",
            Pattern = "{DD}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

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

    [Test]
    public async Task EditSequence_EverythingOK_SequenceIsEdited()
    {
        // Arrange
        SequenceManagerRepository.Sequences.Add(new e_suite.Database.Core.Tables.Sequences.Sequence
        {
            Id = 999,
            Guid = Guid.NewGuid(),
            Increment = 1,
            Name = "Test sequence",
            Pattern = "{DD}",
            Rollover = Rollover.Day,
            Seed = 1
        });

        var editSequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Id = 999 },
            Increment = 2,
            Name = "Edited sequence name",
            Pattern = "{MM}",
            RolloverType = Rollover.Month,
            Seed = 1
        };

        // Act
        await SequenceManager.EditSequence(AuditUserDetails, editSequence, default);

        // Assert
        var result = await SequenceManagerRepository.GetSequenceById(new GeneralIdRef { Id = 999 }, default);
        Assert.Multiple(() =>
        {
            Assert.That(result, Is.Not.Null);
            Assert.That(result?.Name, Is.EqualTo(editSequence.Name));
            Assert.That(result?.Pattern, Is.EqualTo(editSequence.Pattern));
            Assert.That(result?.Rollover, Is.EqualTo(editSequence.RolloverType));
        });
    }
}