using System.ComponentModel.DataAnnotations;
using e_suite.API.Common.models;
using eSuite.Core.Miscellaneous;
using eSuite.Core.Sequences;
using NUnit.Framework;

namespace e_suite.API.Common.UnitTests;

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

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Assert
        Assert.That(results.Count, Is.EqualTo(1));
        Assert.That(results[0].MemberNames.Count(), Is.EqualTo(1));
        Assert.That(results[0].MemberNames.ToList()[0], Is.EqualTo(nameof(Sequence.Pattern)));
        Assert.That(results[0].ErrorMessage, Is.EqualTo("At minimum all patterns must contain one numeric value (i.e. [0])"));
    }

    [Test]
    public void Validate_MissingYearPlaceholder_FailValidation()
    {
        // Arrange
        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Guid = Guid.NewGuid() },
            Increment = 1,
            Name = "Sequence name",
            Pattern = "Order-[000]",
            RolloverType = Rollover.Year,
            Seed = 1
        };

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Asserts
        Assert.That(results.Count, Is.EqualTo(1));
        Assert.That(results[0].MemberNames.Count(), Is.EqualTo(1));
        Assert.That(results[0].MemberNames.ToList()[0], Is.EqualTo(nameof(Sequence.Pattern)));
        Assert.That(results[0].ErrorMessage, Is.EqualTo("When the rollover type is set to 'Annual', then the pattern must include either a {YY} or {YYYY} placeholder"));
    }

    [Test]
    public void Validate_MissingMonthPlaceholder_FailValidation()
    {
        // Arrange
        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Guid = Guid.NewGuid() },
            Increment = 1,
            Name = "Sequence name",
            Pattern = "Order-[000]",
            RolloverType = Rollover.Month,
            Seed = 1
        };

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Asserts
        Assert.That(results.Count, Is.EqualTo(1));
        Assert.That(results[0].MemberNames.Count(), Is.EqualTo(1));
        Assert.That(results[0].MemberNames.ToList()[0], Is.EqualTo(nameof(Sequence.Pattern)));
        Assert.That(results[0].ErrorMessage, Is.EqualTo("When the rollover type is set to 'Monthly', then the pattern must include either a {MM} placeholder"));
    }

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

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Asserts
        Assert.That(results.Count, Is.EqualTo(1));
        Assert.That(results[0].MemberNames.Count(), Is.EqualTo(1));
        Assert.That(results[0].MemberNames.ToList()[0], Is.EqualTo(nameof(Sequence.Pattern)));
        Assert.That(results[0].ErrorMessage, Is.EqualTo("When the rollover type is set to 'Daily', then the pattern must include either a {DD} placeholder"));
    }

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

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Assert
        Assert.That(results.Count, Is.EqualTo(0));
    }

    [Test]
    public void Validate_Increment0_Fails()
    {
        // Arrange
        var sequence = new Sequence
        {
            GeneralIdRef = new GeneralIdRef { Guid = Guid.NewGuid() },
            Increment = 0,
            Name = "Sequence name",
            Pattern = "Order [0000] from {DD}-{MM}-{YYYY}",
            RolloverType = Rollover.Day,
            Seed = 1
        };

        var context = new ValidationContext(sequence);

        // Act
        var results = sequence.Validate(context).ToList();

        // Assert
        Assert.That(results.Count, Is.EqualTo(1));
        Assert.That(results[0].MemberNames.Count(), Is.EqualTo(1));
        Assert.That(results[0].MemberNames.ToList()[0], Is.EqualTo(nameof(Sequence.Increment)));
        Assert.That(results[0].ErrorMessage, Is.EqualTo("Increment can not be 0"));
    }
}