namespace PlanTempusAdmin.Models; public class BackupLog { public int Id { get; set; } // Timing public DateTime StartedAt { get; set; } public DateTime? CompletedAt { get; set; } public int? DurationMs { get; set; } // Identifikation public string BackupType { get; set; } = string.Empty; // 'forgejo_repos', 'postgres_db', etc. public string SourceName { get; set; } = string.Empty; // repo navn eller db navn public string? SourcePath { get; set; } // /var/lib/forgejo/repositories/user/repo.git // Destination public string Destination { get; set; } = string.Empty; // 'azure_blob', 's3', 'local', 'sftp' public string? RemotePath { get; set; } // azure:container/backups/2024-01-31/repo.tar.gz // Resultat public string Status { get; set; } = string.Empty; // 'running', 'success', 'failed', 'partial' public long? SizeBytes { get; set; } public int? FileCount { get; set; } // antal filer i backup // Fejlhåndtering public string? ErrorMessage { get; set; } public string? ErrorCode { get; set; } // 'AZURE_UPLOAD_FAILED', 'DISK_FULL', 'TAR_FAILED', etc. public int RetryCount { get; set; } // Metadata public string? Hostname { get; set; } // hvilken server kørte backup public string? ScriptVersion { get; set; } // version af backup script public string? Checksum { get; set; } // SHA256 af backup fil public DateTime CreatedAt { get; set; } // Legacy compatibility properties for existing pages public DateTime Timestamp => StartedAt; public string Database => SourceName; public TimeSpan? Duration => DurationMs.HasValue ? TimeSpan.FromMilliseconds(DurationMs.Value) : null; public string? FilePath => RemotePath ?? SourcePath; } public class BackupSummary { public int TotalBackups { get; set; } public int SuccessfulBackups { get; set; } public int FailedBackups { get; set; } public DateTime? LastBackup { get; set; } public DateTime? LastSuccessfulBackup { get; set; } public long TotalSizeBytes { get; set; } } public class RepositorySummary { public string SourceName { get; set; } = string.Empty; public string BackupType { get; set; } = string.Empty; public int TotalBackups { get; set; } public int SuccessfulBackups { get; set; } public int FailedBackups { get; set; } public DateTime? LastBackup { get; set; } public DateTime? LastSuccessfulBackup { get; set; } public long TotalSizeBytes { get; set; } public long? LastBackupSizeBytes { get; set; } public long? PreviousBackupSizeBytes { get; set; } public string SizeTrend { get { if (!LastBackupSizeBytes.HasValue || !PreviousBackupSizeBytes.HasValue) return "unknown"; if (LastBackupSizeBytes > PreviousBackupSizeBytes * 1.1m) return "growing"; if (LastBackupSizeBytes < PreviousBackupSizeBytes * 0.9m) return "shrinking"; return "stable"; } } } public class BackupDashboard { // Overall stats public int TotalBackups { get; set; } public int SuccessfulBackups { get; set; } public int FailedBackups { get; set; } public int RunningBackups { get; set; } public long TotalSizeBytes { get; set; } public double SuccessRate => TotalBackups > 0 ? (double)SuccessfulBackups / TotalBackups * 100 : 0; // Time-based public DateTime? LastBackup { get; set; } public DateTime? LastSuccessfulBackup { get; set; } public int BackupsLast24Hours { get; set; } public int BackupsLast7Days { get; set; } public long SizeLast24Hours { get; set; } public long SizeLast7Days { get; set; } // Grouped stats public List ByType { get; set; } = new(); public List ByDestination { get; set; } = new(); public List ByHost { get; set; } = new(); public List TopErrors { get; set; } = new(); public List DailyStats { get; set; } = new(); // Recent activity public List RunningNow { get; set; } = new(); public List RecentSuccesses { get; set; } = new(); public List RecentFailures { get; set; } = new(); } public class BackupTypeStat { public string BackupType { get; set; } = string.Empty; public int Total { get; set; } public int Successful { get; set; } public int Failed { get; set; } public int Running { get; set; } public long TotalSize { get; set; } public DateTime? LastBackup { get; set; } public double SuccessRate => Total > 0 ? (double)Successful / Total * 100 : 0; } public class DestinationStat { public string Destination { get; set; } = string.Empty; public int Total { get; set; } public int Successful { get; set; } public int Failed { get; set; } public long TotalSize { get; set; } public DateTime? LastBackup { get; set; } } public class HostStat { public string Hostname { get; set; } = string.Empty; public int Total { get; set; } public int Successful { get; set; } public int Failed { get; set; } public int Running { get; set; } public DateTime? LastBackup { get; set; } public string? ScriptVersion { get; set; } } public class ErrorStat { public string ErrorCode { get; set; } = string.Empty; public int Count { get; set; } public DateTime? LastOccurrence { get; set; } public string? LastMessage { get; set; } } public class DailyStat { public DateTime Date { get; set; } public int Total { get; set; } public int Successful { get; set; } public int Failed { get; set; } public long TotalSize { get; set; } }