namespace ClawdDotNet.Tools.DirectAPI;

/// <summary>
/// Entfernt Zugangsdaten aus URLs, bevor diese das Tool verlassen.
///
/// Hintergrund: Die abgerufene URL wurde als "source" an das Modell zurückgegeben —
/// samt "apikey=" im Query-String. Damit landete der Schlüssel im Konversationskontext,
/// wurde bei jedem Folgeschritt erneut an den Anbieter gesendet, in ChatContext.json
/// auf die Platte geschrieben und in die Logs übernommen.
/// </summary>
public static class UrlSanitizer
{
    private static readonly string[] SensitiveParameters =
    [
        "apikey", "api_key", "key", "token", "access_token", "apitoken",
        "secret", "password", "auth", "signature", "sig"
    ];

    private const string Mask = "***";

    /// <summary>
    /// Ersetzt die Werte sicherheitsrelevanter Query-Parameter durch eine Maske.
    /// Der Rest der URL bleibt lesbar, damit die Herkunft der Daten nachvollziehbar ist.
    /// </summary>
    public static string Sanitize(string? url)
    {
        if (string.IsNullOrWhiteSpace(url))
            return url ?? "";

        var queryStart = url.IndexOf('?');
        if (queryStart < 0)
            return url;

        var baseUrl = url[..queryStart];
        var query = url[(queryStart + 1)..];

        // Fragment abtrennen, damit es hinten wieder angehängt werden kann.
        var fragment = "";
        var fragmentStart = query.IndexOf('#');
        if (fragmentStart >= 0)
        {
            fragment = query[fragmentStart..];
            query = query[..fragmentStart];
        }

        var parts = query.Split('&');
        for (var i = 0; i < parts.Length; i++)
        {
            var separator = parts[i].IndexOf('=');
            if (separator < 0)
                continue;

            var name = parts[i][..separator];
            if (IsSensitive(name))
                parts[i] = name + "=" + Mask;
        }

        return baseUrl + "?" + string.Join("&", parts) + fragment;
    }

    private static bool IsSensitive(string parameterName)
        => SensitiveParameters.Contains(parameterName.Trim().ToLowerInvariant());
}
