using System.Text.Json; using Backend.Common; using Backend.Domain; using Backend.Repositories; namespace Backend.Services; public sealed class RiskFlagService( IRiskFlagRepository riskFlagRepository, IRiskRuleService riskRuleService) : IRiskFlagService { public async Task AddIfMissingAsync( int? seasonId, string? twitchUserId, string source, string type, string severity, string summary, RequestMetadata requestMetadata, object? metadata = null, CancellationToken cancellationToken = default) { var rule = await riskRuleService.GetRuleAsync(type, cancellationToken); if (!rule.Enabled) { return; } var threshold = DateTimeOffset.UtcNow.AddMinutes(-rule.WindowMinutes); var exists = await riskFlagRepository.ExistsOpenRecentAsync( seasonId, twitchUserId, source, type, requestMetadata.ClientIp, threshold, cancellationToken); if (exists) { return; } riskFlagRepository.Add(new RiskFlag { SeasonId = seasonId, TwitchUserId = twitchUserId, Source = source, Type = type, Severity = severity, Status = "open", Summary = summary, CreatedFromIp = requestMetadata.ClientIp, UserAgent = requestMetadata.UserAgent, MetadataJson = JsonSerializer.Serialize(metadata ?? new { }), CreatedAt = DateTimeOffset.UtcNow, }); } }