using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; using Microsoft.Extensions.Logging; using TransmissionRssManager.Core; namespace TransmissionRssManager.Services { public interface ILoggingService { void Configure(UserPreferences preferences); Task> GetLogsAsync(LogFilterOptions options); Task ClearLogsAsync(DateTime? olderThan = null); Task ExportLogsAsync(LogFilterOptions options); void Log(LogLevel level, string message, string context = null, Dictionary properties = null); } public class LogFilterOptions { public string Level { get; set; } = "All"; public string Search { get; set; } = ""; public DateTime? StartDate { get; set; } public DateTime? EndDate { get; set; } public string Context { get; set; } = ""; public int Limit { get; set; } = 100; public int Offset { get; set; } = 0; } public class LoggingService : ILoggingService { private readonly ILogger _logger; private readonly string _logFilePath; private readonly object _logLock = new object(); private List _inMemoryLogs = new List(); private readonly int _maxLogEntries = 1000; public LoggingService(ILogger logger) { _logger = logger; // Prepare log directory and file var logsDirectory = Path.Combine(AppContext.BaseDirectory, "logs"); Directory.CreateDirectory(logsDirectory); _logFilePath = Path.Combine(logsDirectory, "application_logs.json"); // Initialize log file if it doesn't exist if (!File.Exists(_logFilePath)) { File.WriteAllText(_logFilePath, "[]"); } // Load existing logs into memory try { var json = File.ReadAllText(_logFilePath); _inMemoryLogs = JsonSerializer.Deserialize>(json) ?? new List(); } catch (Exception ex) { _logger.LogError(ex, "Failed to load logs from file"); _inMemoryLogs = new List(); } } public void Configure(UserPreferences preferences) { // No-op in simplified version } public Task> GetLogsAsync(LogFilterOptions options) { var filteredLogs = _inMemoryLogs.AsEnumerable(); // Apply filters if (!string.IsNullOrEmpty(options.Level) && options.Level != "All") { filteredLogs = filteredLogs.Where(l => l.Level == options.Level); } if (!string.IsNullOrEmpty(options.Search)) { filteredLogs = filteredLogs.Where(l => l.Message.Contains(options.Search, StringComparison.OrdinalIgnoreCase)); } if (options.StartDate.HasValue) { filteredLogs = filteredLogs.Where(l => l.Timestamp >= options.StartDate.Value); } if (options.EndDate.HasValue) { filteredLogs = filteredLogs.Where(l => l.Timestamp <= options.EndDate.Value); } if (!string.IsNullOrEmpty(options.Context)) { filteredLogs = filteredLogs.Where(l => l.Context == options.Context); } // Sort, paginate and return return Task.FromResult( filteredLogs .OrderByDescending(l => l.Timestamp) .Skip(options.Offset) .Take(options.Limit) .ToList() ); } public Task ClearLogsAsync(DateTime? olderThan = null) { lock (_logLock) { if (olderThan.HasValue) { _inMemoryLogs.RemoveAll(l => l.Timestamp < olderThan.Value); } else { _inMemoryLogs.Clear(); } SaveLogs(); } return Task.CompletedTask; } public async Task ExportLogsAsync(LogFilterOptions options) { var logs = await GetLogsAsync(options); var json = JsonSerializer.Serialize(logs, new JsonSerializerOptions { WriteIndented = true }); return Encoding.UTF8.GetBytes(json); } public void Log(LogLevel level, string message, string context = null, Dictionary properties = null) { var levelString = level.ToString(); // Log to standard logger _logger.Log(level, message); // Store in our custom log system var entry = new LogEntry { Id = _inMemoryLogs.Count > 0 ? _inMemoryLogs.Max(l => l.Id) + 1 : 1, Timestamp = DateTime.UtcNow, Level = levelString, Message = message, Context = context ?? "System", Properties = properties != null ? JsonSerializer.Serialize(properties) : "{}" }; lock (_logLock) { _inMemoryLogs.Add(entry); // Keep log size under control if (_inMemoryLogs.Count > _maxLogEntries) { _inMemoryLogs = _inMemoryLogs .OrderByDescending(l => l.Timestamp) .Take(_maxLogEntries) .ToList(); } SaveLogs(); } } private void SaveLogs() { try { var json = JsonSerializer.Serialize(_inMemoryLogs); File.WriteAllText(_logFilePath, json); } catch (Exception ex) { _logger.LogError(ex, "Failed to save logs to file"); } } } }