import type { MarginPreset, PageId } from "../engine/geometry"; /** Page and template choices frozen with an invoice at issue (stored as JSON). */ export interface RenderPrefsV1 { version: 1; templateId: string; pageSize: PageId; margins: MarginPreset; logo?: { /** The logo already contains the business name, so a template drops its own name lockup. */ useWordmark?: boolean; /** Templates without a reference logo placeholder (Linea, ...) show the logo only when this is true. */ show?: boolean; }; } export const DEFAULT_PREFS: RenderPrefsV1 = { version: 1, templateId: "classic", pageSize: "A4", margins: "template", }; const PAGE_SIZE_IDS: readonly PageId[] = ["A4", "LETTER"]; const MARGIN_IDS: readonly MarginPreset[] = ["template", "narrow", "normal"]; /** Tolerant: anything unreadable or out of range falls back to the default for that field. */ export function parsePrefs(json: string | null | undefined): RenderPrefsV1 { if (!json) return { ...DEFAULT_PREFS }; let raw: unknown; try { raw = JSON.parse(json); } catch { return { ...DEFAULT_PREFS }; } if (typeof raw !== "object" || raw === null) return { ...DEFAULT_PREFS }; const o = raw as Record; const prefs: RenderPrefsV1 = { version: 1, templateId: typeof o.templateId === "string" && o.templateId ? o.templateId : DEFAULT_PREFS.templateId, pageSize: PAGE_SIZE_IDS.includes(o.pageSize as PageId) ? (o.pageSize as PageId) : DEFAULT_PREFS.pageSize, margins: MARGIN_IDS.includes(o.margins as MarginPreset) ? (o.margins as MarginPreset) : DEFAULT_PREFS.margins, }; const logo = o.logo; if (typeof logo === "object" && logo !== null) { const { useWordmark, show } = logo as { useWordmark?: unknown; show?: unknown }; const out: NonNullable = {}; if (typeof useWordmark === "boolean") out.useWordmark = useWordmark; if (typeof show === "boolean") out.show = show; if (Object.keys(out).length > 0) prefs.logo = out; } return prefs; } export const prefsToJson = (prefs: RenderPrefsV1): string => JSON.stringify(prefs);