using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Hosting; using Oqtane.Shared; using Oqtane.Enums; using Oqtane.Infrastructure; using Oqtane.Controllers; using SZUAbsolventenverein.Module.HallOfFame.Services; using System.Linq; using System.Threading.Tasks; using QuestPDF.Fluent; using QuestPDF.Helpers; using QuestPDF.Infrastructure; namespace SZUAbsolventenverein.Module.HallOfFame.Controllers { [Route(ControllerRoutes.ApiRoute)] public class HallOfFamePdfController : ModuleControllerBase { private readonly IHallOfFameService _hallOfFameService; private readonly IWebHostEnvironment _environment; public HallOfFamePdfController(IHallOfFameService hallOfFameService, ILogManager logger, IHttpContextAccessor accessor, IWebHostEnvironment environment) : base(logger, accessor) { _hallOfFameService = hallOfFameService; _environment = environment; } // GET: api/?moduleid=x&download=true/false [HttpGet] [Authorize(Policy = PolicyNames.ViewModule)] public async Task Get(string moduleid, bool download = false) { int ModuleId; if (int.TryParse(moduleid, out ModuleId) && IsAuthorizedEntityId(EntityNames.Module, ModuleId)) { var entries = await _hallOfFameService.GetHallOfFamesAsync(ModuleId); var publishedEntries = entries.Where(e => e.Status == "Published").ToList(); var document = Document.Create(container => { foreach (var entry in publishedEntries) { // Bild laden falls vorhanden byte[] imageBytes = null; if (!string.IsNullOrEmpty(entry.Image)) { try { var fullImagePath = System.IO.Path.Combine( _environment.WebRootPath, entry.Image.TrimStart('/')); if (System.IO.File.Exists(fullImagePath)) imageBytes = System.IO.File.ReadAllBytes(fullImagePath); } catch { } } container.Page(page => { page.Size(PageSizes.A4); page.Margin(0); page.Content().Layers(layers => { // ── Hintergrundbild (Edge-to-Edge) ── if (imageBytes != null) { layers.Layer().Image(imageBytes).FitUnproportionally(); } else { layers.Layer().Background("#1A1A2E"); } // ── Inhalt (PrimaryLayer) ── layers.PrimaryLayer() .Padding(40) .Column(column => { // ═══ TITELKARTE (oben) ═══ column.Item() .Border(5f).BorderColor("#20000000") .CornerRadius(24) .Border(3f).BorderColor("#33000000") .CornerRadius(22) .Border(1f).BorderColor("#44FFFFFF") .Background("#CC1A1A2E") .CornerRadius(20) .PaddingVertical(28) .PaddingHorizontal(36) .Column(inner => { // Name: groß, dominant, Uppercase inner.Item() .PaddingBottom(6) .Text(entry.Name.ToUpper()) .FontSize(36) .ExtraBold() .FontColor(Colors.White) .LetterSpacing(0.5f); // Trennlinie inner.Item() .PaddingVertical(8) .Height(1.5f) .Background("#55FFFFFF"); // Jahr: sekundär, elegant inner.Item() .PaddingTop(4) .Text($"Jahrgang {entry.Year}") .FontSize(15) .FontColor("#CCFFFFFF") .LetterSpacing(1.5f); }); // ═══ BESCHREIBUNGSKARTE (unten) ═══ var description = entry.Description ?? ""; var sections = description.Split('\n') .Select(s => s.Trim()) .Where(s => !string.IsNullOrEmpty(s)) .ToArray(); column.Item().ExtendVertical().AlignBottom() .Border(5f).BorderColor("#20000000") .CornerRadius(20) .Border(3f).BorderColor("#33000000") .CornerRadius(18) .Border(1f).BorderColor("#33FFFFFF") .Background("#CC1A1A2E") .CornerRadius(16) .PaddingVertical(24) .PaddingHorizontal(32) .Column(descColumn => { if (sections.Length > 0) { // Überschrift descColumn.Item() .PaddingBottom(12) .Text("Beschreibung") .FontSize(14) .SemiBold() .FontColor("#B0FFFFFF") .LetterSpacing(2f); // Trennlinie descColumn.Item() .PaddingBottom(14) .Height(1f) .Background("#33FFFFFF"); // Text foreach (var line in sections) { descColumn.Item() .PaddingBottom(8) .Text(line) .FontSize(11) .FontColor("#E8FFFFFF") .LineHeight(1.5f); } } }); }); }); }); } }); byte[] pdfBytes = document.GeneratePdf(); if (download) { return File(pdfBytes, "application/pdf", "HallOfFame.pdf"); } // Inline: PDF wird im Browser angezeigt (Vorschau) return File(pdfBytes, "application/pdf"); } else { _logger.Log(LogLevel.Error, this, LogFunction.Security, "Unauthorized HallOfFame PDF Get Attempt {ModuleId}", moduleid); return Forbid(); } } } }