using System.Text.Json; using LiveRecorder.Domain.Enums; namespace LiveRecorder.Domain.Entities; public class CleanupOperation { private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web); private CleanupOperation() { } public CleanupOperation( CleanupOperationKind kind, bool deleteFiles, string? filtersJson, DateTimeOffset createdAt) { Id = Guid.NewGuid(); Kind = kind; Status = CleanupOperationStatus.Queued; DeleteFiles = deleteFiles; FiltersJson = string.IsNullOrWhiteSpace(filtersJson) ? "{}" : filtersJson; WarningsJson = "[]"; CreatedAt = createdAt; } public Guid Id { get; private set; } public CleanupOperationKind Kind { get; private set; } public CleanupOperationStatus Status { get; private set; } public bool DeleteFiles { get; private set; } public string FiltersJson { get; private set; } = "{}"; public DateTimeOffset CreatedAt { get; private set; } public DateTimeOffset? StartedAt { get; private set; } public DateTimeOffset? CompletedAt { get; private set; } public int TotalSessionCount { get; private set; } public int ProcessedSessionCount { get; private set; } public int DeletedSessionCount { get; private set; } public int DeletedTaskCount { get; private set; } public int DeletedResultCount { get; private set; } public int DeletedLogCount { get; private set; } public int DeletedFileCount { get; private set; } public int DeletedDanmakuFileCount { get; private set; } public string WarningsJson { get; private set; } = "[]"; public string? ErrorMessage { get; private set; } public void MarkRunning(DateTimeOffset startedAt) { Status = CleanupOperationStatus.Running; StartedAt = startedAt; CompletedAt = null; ErrorMessage = null; } public void SetTotalSessionCount(int totalSessionCount) { TotalSessionCount = Math.Max(0, totalSessionCount); if (ProcessedSessionCount > TotalSessionCount) { ProcessedSessionCount = TotalSessionCount; } } public void MarkCompleted(DateTimeOffset completedAt) { Status = CleanupOperationStatus.Completed; CompletedAt = completedAt; ErrorMessage = null; } public void MarkFailed(string errorMessage, DateTimeOffset completedAt) { Status = CleanupOperationStatus.Failed; CompletedAt = completedAt; ErrorMessage = string.IsNullOrWhiteSpace(errorMessage) ? "Cleanup operation failed." : errorMessage.Trim(); } public void Requeue(string warning) { Status = CleanupOperationStatus.Queued; StartedAt = null; CompletedAt = null; ErrorMessage = null; AppendWarnings([warning]); } public void ApplyBatchProgress( int processedSessionCount, int deletedSessionCount, int deletedTaskCount, int deletedResultCount, int deletedLogCount, int deletedFileCount, int deletedDanmakuFileCount, IReadOnlyCollection? warnings = null) { ProcessedSessionCount += Math.Max(0, processedSessionCount); DeletedSessionCount += Math.Max(0, deletedSessionCount); DeletedTaskCount += Math.Max(0, deletedTaskCount); DeletedResultCount += Math.Max(0, deletedResultCount); DeletedLogCount += Math.Max(0, deletedLogCount); DeletedFileCount += Math.Max(0, deletedFileCount); DeletedDanmakuFileCount += Math.Max(0, deletedDanmakuFileCount); if (ProcessedSessionCount > TotalSessionCount) { ProcessedSessionCount = TotalSessionCount; } if (warnings is { Count: > 0 }) { AppendWarnings(warnings); } } public IReadOnlyList GetWarnings() { if (string.IsNullOrWhiteSpace(WarningsJson)) { return []; } try { return JsonSerializer.Deserialize>(WarningsJson, JsonOptions) ?? []; } catch { return []; } } private void AppendWarnings(IReadOnlyCollection warnings) { if (warnings.Count == 0) { return; } var merged = GetWarnings().Concat(warnings.Where(static item => !string.IsNullOrWhiteSpace(item))) .Select(static item => item.Trim()) .ToList(); WarningsJson = JsonSerializer.Serialize(merged, JsonOptions); } }