using System.Text.Json.Nodes;

namespace Nexus.Api.Services;

internal static class OpenClawPayloadSanitizer
{
    private static readonly string[] SensitiveKeys =
    [
        "accesstoken",
        "apikey",
        "authorization",
        "cookie",
        "credential",
        "devicetoken",
        "password",
        "privatekey",
        "refreshtoken",
        "secret",
        "token"
    ];

    public static JsonNode? Redact(JsonNode? value)
    {
        if (value is null)
            return null;

        var clone = value.DeepClone();
        RedactInPlace(clone);
        return clone;
    }

    private static void RedactInPlace(JsonNode node)
    {
        if (node is JsonObject obj)
        {
            foreach (var property in obj.ToList())
            {
                var normalized = property.Key
                    .Replace("-", string.Empty, StringComparison.Ordinal)
                    .Replace("_", string.Empty, StringComparison.Ordinal)
                    .ToLowerInvariant();

                var tokenLikeSecret = !normalized.EndsWith("configured", StringComparison.Ordinal)
                                      && (normalized.Contains("accesstoken", StringComparison.Ordinal)
                                          || normalized.Contains("apitoken", StringComparison.Ordinal)
                                          || normalized.Contains("authtoken", StringComparison.Ordinal)
                                          || normalized.Contains("bearertoken", StringComparison.Ordinal)
                                          || normalized.Contains("devicetoken", StringComparison.Ordinal)
                                          || normalized.Contains("refreshtoken", StringComparison.Ordinal));

                if (SensitiveKeys.Contains(normalized, StringComparer.Ordinal)
                    || tokenLikeSecret
                    || normalized.EndsWith("password", StringComparison.Ordinal)
                    || normalized.EndsWith("privatekey", StringComparison.Ordinal)
                    || normalized.EndsWith("secret", StringComparison.Ordinal)
                    || normalized.EndsWith("credential", StringComparison.Ordinal)
                    || (normalized.EndsWith("token", StringComparison.Ordinal)
                        && !normalized.EndsWith("inputtoken", StringComparison.Ordinal)
                        && !normalized.EndsWith("outputtoken", StringComparison.Ordinal)
                        && !normalized.EndsWith("totaltoken", StringComparison.Ordinal)
                        && !normalized.EndsWith("contexttoken", StringComparison.Ordinal)
                        && !normalized.EndsWith("maxtoken", StringComparison.Ordinal)))
                {
                    obj[property.Key] = "[redacted]";
                    continue;
                }

                if (property.Value is not null)
                    RedactInPlace(property.Value);
            }

            return;
        }

        if (node is JsonArray array)
        {
            foreach (var item in array)
            {
                if (item is not null)
                    RedactInPlace(item);
            }
        }
    }
}
