using System.Collections.Concurrent;
using System.Text.RegularExpressions;

namespace Nexus.Api.Services;

public static class AgentActivityText
{
    private static readonly (Regex Pattern, string Replacement)[] InlineRedactions =
    [
        (new Regex(@"(?i)(authorization\s*:\s*bearer)\s+\S+", RegexOptions.CultureInvariant), "$1 [redacted]"),
        (new Regex(@"(?i)(x-nexus-api-key\s*:\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(api[_-]?key\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(token\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(password\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(secret\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(jwt\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]"),
        (new Regex(@"(?i)(private[_-]?key\s*[:=]\s*)\S+", RegexOptions.CultureInvariant), "$1[redacted]")
    ];

    private static readonly Regex[] ResidualSensitivePatterns =
    [
        new(@"(?i)bearer\s+(?!\[redacted\])\S+", RegexOptions.CultureInvariant),
        new(@"(?i)x-nexus-api-key\s*:\s*(?!\[redacted\])\S+", RegexOptions.CultureInvariant),
        new(@"(?i)private[_-]?key\s*[:=]\s*(?!\[redacted\])\S+", RegexOptions.CultureInvariant)
    ];

    private static readonly string[] KnownActorIds =
    [
        .. AgentIdentityCatalog.DefaultConfiguredAgentIds,
        "bao",
        "nexus-system"
    ];

    public static string RedactForDisplay(string? content)
    {
        if (string.IsNullOrWhiteSpace(content))
            return content ?? string.Empty;

        var lines = content.Split('\n');
        for (var i = 0; i < lines.Length; i++)
        {
            var sanitized = lines[i];
            foreach (var (pattern, replacement) in InlineRedactions)
            {
                sanitized = pattern.Replace(sanitized, replacement);
            }

            if (ResidualSensitivePatterns.Any(pattern => pattern.IsMatch(sanitized)))
                sanitized = "[redacted sensitive line]";

            lines[i] = sanitized;
        }

        return string.Join('\n', lines).Trim();
    }

    public static bool MatchesAgent(string? content, string agentId)
    {
        if (string.IsNullOrWhiteSpace(agentId))
            return false;

        var normalized = agentId.Trim().ToLowerInvariant();
        return ExtractAgentIds(content).Contains(normalized, StringComparer.OrdinalIgnoreCase);
    }

    public static string[] ExtractAgentIds(string? content)
    {
        if (string.IsNullOrWhiteSpace(content))
            return [];

        var matches = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
        foreach (var actorId in KnownActorIds)
        {
            if (BuildActorRegex(actorId).IsMatch(content))
                matches.Add(actorId);
        }

        return matches
            .Select(actorId => actorId.ToLowerInvariant())
            .OrderBy(actorId => actorId, StringComparer.Ordinal)
            .ToArray();
    }

    private static Regex BuildActorRegex(string actorId)
        => ActorPatternCache.GetOrAdd(actorId, static key =>
            new Regex($@"(?<![a-z0-9]){Regex.Escape(key)}(?![a-z0-9])", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant));

    private static readonly ConcurrentDictionary<string, Regex> ActorPatternCache = new(StringComparer.OrdinalIgnoreCase);
}
