﻿/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#nullable disable

namespace DotPulsar.Tests
{
    using DotPulsar;
    using FluentAssertions;
    using Xunit;

    public class MessageIdTests
    {
        [Fact]
        public void CompareTo_GivenTheSameValues_ShouldBeEqual()
        {
            var m1 = new MessageId(1, 2, 3, 4);
            var m2 = new MessageId(1, 2, 3, 4);

            m1.CompareTo(m2).Should().Be(0);
            (m1 < m2).Should().BeFalse();
            (m1 > m2).Should().BeFalse();
            (m1 >= m2).Should().BeTrue();
            (m1 <= m2).Should().BeTrue();
        }

        [Fact]
        public void CompareTo_GivenAllNull_ShouldBeEqual()
        {
            MessageId m1 = null;
            MessageId m2 = null;

            (m1 < m2).Should().BeFalse();
            (m1 > m2).Should().BeFalse();
            (m1 <= m2).Should().BeTrue();
            (m1 >= m2).Should().BeTrue();
        }

        [Fact]
        public void CompareTo_GivenOneNull_ShouldFollowNull()
        {
            var m1 = new MessageId(1, 2, 3, 4);
            MessageId m2 = null;

            m1.CompareTo(m2).Should().BePositive();
            (m1 < m2).Should().BeFalse();
            (m1 > m2).Should().BeTrue();
            (m1 <= m2).Should().BeFalse();
            (m1 >= m2).Should().BeTrue();

            (m2 < m1).Should().BeTrue();
            (m2 > m1).Should().BeFalse();
            (m2 <= m1).Should().BeTrue();
            (m2 >= m1).Should().BeFalse();
        }

        [Theory]
        [InlineData(2, 2, 3, 4)] // LegderId is greater
        [InlineData(1, 3, 3, 4)] // EntryId is greater
        [InlineData(1, 2, 4, 4)] // Partition is greater
        [InlineData(1, 2, 3, 5)] // BatchIndex is greater
        public void CompareTo_GivenCurrentFollowsArgument_ShouldReturnPositive(ulong ledgerId, ulong entryId, int partition, int batchIndex)
        {
            var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
            var m2 = new MessageId(1, 2, 3, 4);

            m1.CompareTo(m2).Should().BePositive();
            (m1 > m2).Should().BeTrue();
            (m1 < m2).Should().BeFalse();
        }

        [Theory]
        [InlineData(0, 2, 3, 4)] // LegderId is less
        [InlineData(1, 1, 3, 4)] // EntryId is less
        [InlineData(1, 2, 2, 4)] // Partition is less
        [InlineData(1, 2, 3, 3)] // BatchIndex is less
        public void CompareTo_GivenCurrentPrecedesArgument_ShouldReturnNegative(ulong ledgerId, ulong entryId, int partition, int batchIndex)
        {
            var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
            var m2 = new MessageId(1, 2, 3, 4);

            m1.CompareTo(m2).Should().BeNegative();
            (m1 < m2).Should().BeTrue();
            (m1 > m2).Should().BeFalse();
        }

        [Fact]
        public void Equals_GivenTheSameObject_ShouldBeEqual()
        {
            var m1 = new MessageId(1, 2, 3, 4);
            var m2 = m1;

            m1.Equals(m2).Should().BeTrue();
            (m1 == m2).Should().BeTrue();
            (m1 != m2).Should().BeFalse();
        }

        [Fact]
        public void Equals_GivenTheSameValues_ShouldBeEqual()
        {
            var m1 = new MessageId(1, 2, 3, 4);
            var m2 = new MessageId(1, 2, 3, 4);

            m1.Equals(m2).Should().BeTrue();
            (m1 == m2).Should().BeTrue();
            (m1 != m2).Should().BeFalse();
        }

        [Theory]
        [InlineData(0, 2, 3, 4)] // LegerId not the same
        [InlineData(1, 0, 3, 4)] // EntryId not the same
        [InlineData(1, 2, 0, 4)] // Partition not the same
        [InlineData(1, 2, 3, 0)] // BatchIndex not the same
        public void Equals_GivenDifferentValues_ShouldNotBeEqual(ulong ledgerId, ulong entryId, int partition, int batchIndex)
        {
            var m1 = new MessageId(ledgerId, entryId, partition, batchIndex);
            var m2 = new MessageId(1, 2, 3, 4);

            m1.Equals(m2).Should().BeFalse();
            (m1 == m2).Should().BeFalse();
            (m1 != m2).Should().BeTrue();
        }

        [Fact]
        public void Equals_GivenAllNull_ShouldBeEqual()
        {
            MessageId m1 = null;
            MessageId m2 = null;

            (m1 == m2).Should().BeTrue();
            (m1 is null).Should().BeTrue();
            (m1 != m2).Should().BeFalse();
        }

        [Fact]
        public void Equals_GivenOneNull_ShouldNotBeEqual()
        {
            var m1 = new MessageId(1, 2, 3, 4);
            MessageId m2 = null;

            (m1 is null).Should().BeFalse();
            (m1 == m2).Should().BeFalse();
            m1.Equals(m2).Should().BeFalse();
            (m1 != m2).Should().BeTrue();
        }
    }
}

#nullable enable
