using System;
using System.Text;
using ClaudeDo.Ui.Services;
using Xunit;

namespace ClaudeDo.Ui.Tests.Services;

public class ZitadelTokenInspectorTests
{
    // Builds a fake JWT (header.payload.signature) carrying the given JSON payload.
    private static string MakeToken(string payloadJson)
    {
        static string B64Url(string s)
        {
            var bytes = Encoding.UTF8.GetBytes(s);
            return Convert.ToBase64String(bytes).TrimEnd('=').Replace('+', '-').Replace('/', '_');
        }
        return $"{B64Url("{\"alg\":\"RS256\"}")}.{B64Url(payloadJson)}.sig";
    }

    [Fact]
    public void HasUserRole_True_ForGenericRolesClaim()
    {
        var token = MakeToken(
            "{\"urn:zitadel:iam:org:project:roles\":{\"user\":{\"org1\":\"example.com\"}}}");
        Assert.True(ZitadelTokenInspector.HasUserRole(token));
    }

    [Fact]
    public void HasUserRole_True_ForProjectScopedRolesClaim()
    {
        var token = MakeToken(
            "{\"urn:zitadel:iam:org:project:376787351902355727:roles\":{\"user\":{\"org1\":\"example.com\"}}}");
        Assert.True(ZitadelTokenInspector.HasUserRole(token));
    }

    [Fact]
    public void HasUserRole_False_WhenRoleMissing()
    {
        var token = MakeToken(
            "{\"urn:zitadel:iam:org:project:roles\":{\"admin\":{\"org1\":\"example.com\"}}}");
        Assert.False(ZitadelTokenInspector.HasUserRole(token));
    }

    [Fact]
    public void HasUserRole_False_WhenNoRolesClaim()
    {
        var token = MakeToken("{\"sub\":\"123\",\"email\":\"a@b.c\"}");
        Assert.False(ZitadelTokenInspector.HasUserRole(token));
    }

    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("not-a-jwt")]
    [InlineData("only.two")]
    public void HasUserRole_FailsOpen_ForUnparseableInput(string? token)
    {
        // Cannot decide -> fail open (server remains the source of truth).
        Assert.True(ZitadelTokenInspector.HasUserRole(token));
    }
}
