using SharepointToolbox.Core.Helpers;

namespace SharepointToolbox.Tests.Services;

/// <summary>
/// Tests for PERM-03: external user detection, permission-level filtering,
/// and SharePoint system-group classification (Limited Access / SharingLinks).
/// Pure static logic — runs immediately without stubs.
/// </summary>
public class PermissionEntryClassificationTests
{
    // ── IsExternalUser ─────────────────────────────────────────────────────────

    [Fact]
    public void IsExternalUser_WithExtHashInLoginName_ReturnsTrue()
    {
        Assert.True(PermissionEntryHelper.IsExternalUser("ext_user_domain.com#EXT#@contoso.onmicrosoft.com"));
    }

    [Fact]
    public void IsExternalUser_WithNormalLoginName_ReturnsFalse()
    {
        Assert.False(PermissionEntryHelper.IsExternalUser("i:0#.f|membership|alice@contoso.com"));
    }

    // ── FilterPermissionLevels ─────────────────────────────────────────────────

    [Fact]
    public void PermissionEntry_FiltersOutLimitedAccess_WhenOnlyPermissionIsLimitedAccess()
    {
        var result = PermissionEntryHelper.FilterPermissionLevels(new[] { "Limited Access" });
        Assert.Empty(result);
    }

    [Fact]
    public void FilterPermissionLevels_RetainsOtherLevels_WhenMixedWithLimitedAccess()
    {
        var result = PermissionEntryHelper.FilterPermissionLevels(new[] { "Limited Access", "Contribute" });
        Assert.Equal(new[] { "Contribute" }, result);
    }

    // ── IsBareLimitedAccessSystemGroup ─────────────────────────────────────────

    [Fact]
    public void IsBareLimitedAccessSystemGroup_WithExactMatch_ReturnsTrue()
    {
        Assert.True(PermissionEntryHelper.IsBareLimitedAccessSystemGroup("Limited Access System Group"));
    }

    [Fact]
    public void IsBareLimitedAccessSystemGroup_WithForWebVariant_ReturnsFalse()
    {
        // The "For Web {guid}" variant is enriched, not filtered.
        Assert.False(PermissionEntryHelper.IsBareLimitedAccessSystemGroup(
            "Limited Access System Group For Web e55a4f7a-b132-4baa-bd96-c63d8dc1fc80"));
    }

    [Fact]
    public void IsBareLimitedAccessSystemGroup_WithNormalGroup_ReturnsFalse()
    {
        Assert.False(PermissionEntryHelper.IsBareLimitedAccessSystemGroup("Owners"));
    }

    // ── Classify ───────────────────────────────────────────────────────────────

    [Fact]
    public void Classify_WithNormalGroupTitle_ReturnsNone()
    {
        var c = PermissionEntryHelper.Classify("Site Owners");
        Assert.Equal(SystemGroupKind.None, c.Kind);
    }

    [Fact]
    public void Classify_WithBareLimitedAccess_ReturnsLimitedAccessBare()
    {
        var c = PermissionEntryHelper.Classify("Limited Access System Group");
        Assert.Equal(SystemGroupKind.LimitedAccessBare, c.Kind);
    }

    [Fact]
    public void Classify_WithLimitedAccessForWeb_ExtractsWebId()
    {
        var c = PermissionEntryHelper.Classify(
            "Limited Access System Group For Web e55a4f7a-b132-4baa-bd96-c63d8dc1fc80");
        Assert.Equal(SystemGroupKind.LimitedAccessWeb, c.Kind);
        Assert.Equal(Guid.Parse("e55a4f7a-b132-4baa-bd96-c63d8dc1fc80"), c.WebId);
        Assert.Null(c.ListId);
        Assert.Null(c.ItemUniqueId);
    }

    [Fact]
    public void Classify_WithLimitedAccessForList_ExtractsListId()
    {
        var c = PermissionEntryHelper.Classify(
            "Limited Access System Group For List b20e3b22-2b09-4c99-9ba4-37b42f3a12dc");
        Assert.Equal(SystemGroupKind.LimitedAccessList, c.Kind);
        Assert.Equal(Guid.Parse("b20e3b22-2b09-4c99-9ba4-37b42f3a12dc"), c.ListId);
        Assert.Null(c.WebId);
        Assert.Null(c.ItemUniqueId);
    }

    [Fact]
    public void Classify_WithSharingLink_ExtractsItemAndShareId()
    {
        var c = PermissionEntryHelper.Classify(
            "SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.OrganizationEdit.64c27910-66ea-421d-b0f0-8f0f72dcfaf6");
        Assert.Equal(SystemGroupKind.SharingLink, c.Kind);
        Assert.Equal(Guid.Parse("e686221e-d1cb-43c5-8c68-04aa7f90f329"), c.ItemUniqueId);
        Assert.Equal(Guid.Parse("64c27910-66ea-421d-b0f0-8f0f72dcfaf6"), c.ShareId);
        Assert.Equal("OrganizationEdit", c.LinkType);
    }

    [Theory]
    [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.AnonymousView.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "AnonymousView")]
    [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.Flexible.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "Flexible")]
    [InlineData("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.OrganizationView.64c27910-66ea-421d-b0f0-8f0f72dcfaf6", "OrganizationView")]
    public void Classify_WithVariousSharingLinkTypes_PreservesLinkType(string title, string expected)
    {
        var c = PermissionEntryHelper.Classify(title);
        Assert.Equal(SystemGroupKind.SharingLink, c.Kind);
        Assert.Equal(expected, c.LinkType);
    }

    [Fact]
    public void Classify_WithMalformedSharingLink_ReturnsNone()
    {
        // Missing share GUID at the end
        var c = PermissionEntryHelper.Classify("SharingLinks.e686221e-d1cb-43c5-8c68-04aa7f90f329.Edit");
        Assert.Equal(SystemGroupKind.None, c.Kind);
    }

    [Fact]
    public void Classify_WithEmptyString_ReturnsNone()
    {
        var c = PermissionEntryHelper.Classify("");
        Assert.Equal(SystemGroupKind.None, c.Kind);
    }
}
