using System.Globalization;
using System.Text;
using BigRegister.Api.Contracts;
using BigRegister.Api.Data;
namespace BigRegister.Domain.Letters;
///
/// Server-rendered letter HTML — the archived, "what is sent" artifact.
/// Mirrors the FE letter canvas' class vocabulary exactly (public/letter.css,
/// the FE⇄BE contract; LetterHtmlTests' class-parity test is the fence against drift).
///
/// Unlike the canvas, placeholders resolve to real text rather than a live editor
/// widget: an auto-resolvable key pulls from seed/case data (there is no per-brief
/// resolved value stored anywhere else in the domain — see BriefEntity's own "does
/// not interpret it" posture), an unresolved manual key renders literally as
/// "[NOG IN TE VULLEN: label]" (PRD Brief v2 §8) — the preview works despite this,
/// only send blocks on it (FE-authoritative linting).
///
/// ponytail: HTML today, a headless-Chromium PDF render slots in behind this same
/// route if the POC ever needs real PDF bytes — see the preview endpoints.
///
public static class LetterHtml
{
private static readonly string Css = File.ReadAllText(FindLetterCss());
public static string Render(BriefEntity brief, OrgTemplateDto template, string at, bool watermark)
{
var defs = brief.Placeholders.ToDictionary(p => p.Key);
var sb = new StringBuilder();
sb.Append("
");
// --- letterhead ---
sb.Append("
");
if (template.LogoDocumentId is { } logoId && DocumentStore.Get(logoId) is { } logo)
{
sb.Append("
.Append(logo.ContentType))
");
}
sb.Append("
").Append(Enc(template.OrgName)).Append("
");
sb.Append("
").Append(EncLines(template.ReturnAddress)).Append("");
sb.Append("
").Append(EncLines(RecipientPlaceholder)).Append("");
sb.Append("
");
sb.Append("- Ons kenmerk
- ").Append(Enc(brief.BriefId)).Append("
");
sb.Append("- Datum
- ").Append(Enc(FormatDatumNl(at))).Append("
");
sb.Append("
");
// --- body: the case-type template's sections ---
sb.Append("
");
foreach (var section in brief.Sections)
{
sb.Append("").Append(Enc(section.Title)).Append("
");
foreach (var block in section.Blocks)
RenderParagraphs(sb, block.Content.Paragraphs, defs, at);
sb.Append("");
}
sb.Append("
");
// --- signature ---
sb.Append("
");
sb.Append("
").Append(Enc(template.SignatureClosing)).Append("
");
sb.Append("
").Append(Enc(template.SignatureName)).Append("
");
sb.Append("
").Append(Enc(template.SignatureRole)).Append("
");
sb.Append("
");
// --- footer ---
sb.Append("");
if (watermark) sb.Append("
VOORBEELD
");
sb.Append("
");
return sb.ToString();
}
/// Exposed so LetterHtmlTests can assert every `letter`-prefixed class this
/// renderer emits also exists in the shared contract file — the fence against drift.
public static string StyleSheet => Css;
// No recipient address is tracked anywhere in this POC's brief domain (BRP lookup
// is out of scope here) — the canvas shows the same static placeholder text.
private const string RecipientPlaceholder = "Adres van de geadresseerde\n(wordt ingevuld bij verzending)";
private static void RenderParagraphs(
StringBuilder sb, IReadOnlyList