using SSPCTester.Logic.Models; using System.Text.Json; using System.Text.Json.Serialization; namespace SSPCTester.Logic.Report; public enum ReportOutputFormat { Pdf, Word, Both } public static class ReportFileHelper { public const string DefaultTemplate = "report_{yyyyMMdd_HHmmss}.pdf"; private static readonly JsonSerializerOptions JsonOptions = new() { WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull }; public static string ResolveFileName(Project project, DateTime now) => ResolveFileName(project, now, ".pdf"); public static string ResolveFileName(Project project, DateTime now, string extension) { string template = string.IsNullOrWhiteSpace(project.Report.FileName) ? DefaultTemplate : project.Report.FileName.Trim(); extension = NormalizeExtension(extension); string date = now.ToString("yyyyMMdd"); string dateTime = now.ToString("yyyyMMdd_HHmmss"); string value = template .Replace("{ProjectName}", project.Name ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{ProductName}", project.Dut.ProductName ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{Model}", project.Dut.Model ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{SerialNumber}", project.Dut.SerialNumber ?? "", StringComparison.OrdinalIgnoreCase) .Replace("{yyyyMMdd_HHmmss}", dateTime, StringComparison.OrdinalIgnoreCase) .Replace("{DateTime}", dateTime, StringComparison.OrdinalIgnoreCase) .Replace("{yyyyMMdd}", date, StringComparison.OrdinalIgnoreCase) .Replace("{Date}", date, StringComparison.OrdinalIgnoreCase); value = MakeSafeFileName(value); if (string.IsNullOrWhiteSpace(value)) value = $"report_{dateTime}{extension}"; value = Path.ChangeExtension(value, extension); return value; } public static ReportOutputFormat ParseFormat(string? value) { if (Enum.TryParse(value, ignoreCase: true, out var format)) return format; return ReportOutputFormat.Pdf; } public static IReadOnlyList EnumerateReportFiles( string? directory, ReportOutputFormat format) { if (string.IsNullOrWhiteSpace(directory) || !Directory.Exists(directory)) return Array.Empty(); string[] patterns = format switch { ReportOutputFormat.Word => new[] { "*.docx" }, ReportOutputFormat.Both => new[] { "*.pdf", "*.docx" }, _ => new[] { "*.pdf" } }; return patterns .SelectMany(pattern => Directory.EnumerateFiles(directory, pattern, SearchOption.TopDirectoryOnly)) .Select(path => new FileInfo(path)) .OrderByDescending(file => file.LastWriteTime) .Select(file => new ReportFileDescriptor( file.FullName, file.Name, file.LastWriteTime, file.Extension.Equals(".pdf", StringComparison.OrdinalIgnoreCase) ? ReportFileKind.Pdf : ReportFileKind.Word)) .ToArray(); } public static IReadOnlyList EnumeratePdfFiles(string? directory) { return EnumerateReportFiles(directory, ReportOutputFormat.Pdf); } public static string BuildInfoPath(string outputPath) => Path.Combine( Path.GetDirectoryName(outputPath) ?? "", Path.GetFileNameWithoutExtension(outputPath) + ".reportinfo.json"); public static void SaveInfo(ReportInfo info, string infoPath) { Directory.CreateDirectory(Path.GetDirectoryName(infoPath)!); File.WriteAllText(infoPath, JsonSerializer.Serialize(info, JsonOptions)); } public static ReportInfo? LoadInfoForReport(string reportPath) { string infoPath = BuildInfoPath(reportPath); if (!File.Exists(infoPath)) return null; return JsonSerializer.Deserialize(File.ReadAllText(infoPath), JsonOptions); } private static string MakeSafeFileName(string value) { var invalid = Path.GetInvalidFileNameChars(); var chars = value .Select(c => invalid.Contains(c) ? '_' : c) .ToArray(); return new string(chars).Trim(' ', '.'); } private static string NormalizeExtension(string extension) { if (string.IsNullOrWhiteSpace(extension)) return ".pdf"; extension = extension.Trim(); return extension.StartsWith('.') ? extension : "." + extension; } } public enum ReportFileKind { Pdf, Word } public sealed record ReportFileDescriptor( string FullPath, string DisplayName, DateTime LastWriteTime, ReportFileKind Kind = ReportFileKind.Pdf) { public bool IsPdf => Kind == ReportFileKind.Pdf; public bool IsWord => Kind == ReportFileKind.Word; } public sealed class ReportInfo { public string ProjectName { get; set; } = ""; public string ProductName { get; set; } = ""; public string Model { get; set; } = ""; public string SerialNumber { get; set; } = ""; public DateTime GeneratedAt { get; set; } public string Format { get; set; } = ""; public string? PdfPath { get; set; } public string? WordPath { get; set; } public string OverallStatus { get; set; } = ""; public ReportSectionInfo Sections { get; set; } = new(); } public sealed class ReportSectionInfo { public bool Cover { get; set; } public bool Basic { get; set; } public bool Curve { get; set; } public bool Power { get; set; } public bool Protect { get; set; } }