using System.Text.Json;

namespace ClaudeDo.Worker.Online;

/// <summary>
/// Minimal, dependency-free reader for a JWT access token's payload claims. Used to resolve the
/// current user's Zitadel subject (<c>sub</c>) so sync payloads can be stamped with an owner.
/// Never throws — returns null when the token is absent or cannot be parsed.
/// </summary>
public static class JwtClaims
{
    /// <summary>
    /// Returns the <c>sub</c> claim of the JWT, or null if the token is absent/unparseable or
    /// carries no subject.
    /// </summary>
    public static string? GetSubject(string? jwt)
    {
        if (string.IsNullOrWhiteSpace(jwt))
            return null;

        var parts = jwt.Split('.');
        if (parts.Length < 2)
            return null;

        try
        {
            using var doc = JsonDocument.Parse(Base64UrlDecode(parts[1]));
            if (doc.RootElement.TryGetProperty("sub", out var sub) &&
                sub.ValueKind == JsonValueKind.String)
                return sub.GetString();
            return null;
        }
        catch
        {
            return null;
        }
    }

    private static byte[] Base64UrlDecode(string input)
    {
        var s = input.Replace('-', '+').Replace('_', '/');
        switch (s.Length % 4)
        {
            case 2: s += "=="; break;
            case 3: s += "="; break;
        }
        return Convert.FromBase64String(s);
    }
}
