using Xunit;
using FluentAssertions;
using IamService.Domain.AggregatesModel.GroupAggregate;

namespace IamService.UnitTests.Domain.Groups;

/// <summary>
/// EN: Unit tests for GroupRole enumeration (SmartEnum pattern).
/// VI: Kiểm thử đơn vị cho GroupRole enumeration (SmartEnum pattern).
/// </summary>
public class GroupRoleTests
{
    #region Static Values Tests

    [Fact]
    public void Member_HasCorrectIdAndName()
    {
        // Assert
        GroupRole.Member.Id.Should().Be(1);
        GroupRole.Member.Name.Should().Be("Member");
    }

    [Fact]
    public void Admin_HasCorrectIdAndName()
    {
        // Assert
        GroupRole.Admin.Id.Should().Be(2);
        GroupRole.Admin.Name.Should().Be("Admin");
    }

    [Fact]
    public void Owner_HasCorrectIdAndName()
    {
        // Assert
        GroupRole.Owner.Id.Should().Be(3);
        GroupRole.Owner.Name.Should().Be("Owner");
    }

    #endregion

    #region GetAll Tests

    [Fact]
    public void GetAll_ReturnsAllRoles()
    {
        // Act
        var allRoles = GroupRole.GetAll().ToList();

        // Assert
        allRoles.Should().HaveCount(3);
        allRoles.Should().Contain(GroupRole.Member);
        allRoles.Should().Contain(GroupRole.Admin);
        allRoles.Should().Contain(GroupRole.Owner);
    }

    #endregion

    #region FromId Tests

    [Theory]
    [InlineData(1, "Member")]
    [InlineData(2, "Admin")]
    [InlineData(3, "Owner")]
    public void FromId_ValidId_ReturnsCorrectRole(int id, string expectedName)
    {
        // Act
        var role = GroupRole.FromId(id);

        // Assert
        role.Should().NotBeNull();
        role!.Name.Should().Be(expectedName);
    }

    [Theory]
    [InlineData(0)]
    [InlineData(4)]
    [InlineData(-1)]
    [InlineData(100)]
    public void FromId_InvalidId_ReturnsNull(int id)
    {
        // Act
        var role = GroupRole.FromId(id);

        // Assert
        role.Should().BeNull();
    }

    #endregion

    #region HasPermissionOver Tests

    [Theory]
    [InlineData(3, 2, true)]  // Owner > Admin
    [InlineData(3, 1, true)]  // Owner > Member
    [InlineData(2, 1, true)]  // Admin > Member
    [InlineData(3, 3, true)]  // Owner = Owner
    [InlineData(2, 2, true)]  // Admin = Admin
    [InlineData(1, 1, true)]  // Member = Member
    [InlineData(1, 2, false)] // Member < Admin
    [InlineData(1, 3, false)] // Member < Owner
    [InlineData(2, 3, false)] // Admin < Owner
    public void HasPermissionOver_ComparesRolesCorrectly(int roleId, int otherRoleId, bool expected)
    {
        // Arrange
        var role = GroupRole.FromId(roleId)!;
        var otherRole = GroupRole.FromId(otherRoleId)!;

        // Act
        var result = role.HasPermissionOver(otherRole);

        // Assert
        result.Should().Be(expected);
    }

    #endregion

    #region Equality Tests

    [Fact]
    public void Equality_SameRole_AreEqual()
    {
        // Arrange
        var role1 = GroupRole.Member;
        var role2 = GroupRole.Member;

        // Assert
        role1.Should().Be(role2);
        (role1 == role2).Should().BeTrue();
    }

    [Fact]
    public void Equality_DifferentRoles_AreNotEqual()
    {
        // Arrange
        var role1 = GroupRole.Member;
        var role2 = GroupRole.Admin;

        // Assert
        role1.Should().NotBe(role2);
        (role1 != role2).Should().BeTrue();
    }

    #endregion
}
