import type { TFunction } from "i18next";
import type { Patient } from "@/lib/patients";
// Build and print a clean, one-page clinical summary for a patient. We render an
// isolated HTML document in a new window and trigger the browser's print dialog
// (where the user picks "Save as PDF") — no PDF library needed, and the output
// follows the user's locale via the passed `t`.
function esc(value: unknown): string {
return String(value ?? "")
.replace(/&/g, "&")
.replace(//g, ">");
}
function rows(items: { label: string; value: string }[]): string {
return items
.filter((r) => r.value)
.map(
(r) =>
`
| ${esc(r.label)} | ${esc(r.value)} |
`,
)
.join("");
}
export function printPatientSummary(patient: Patient, t: TFunction): void {
const sexLabel = t(`patientCard.sex.${patient.sex}`);
const generated = new Date().toLocaleString();
const section = (title: string, body: string, empty: string): string =>
`${esc(title)}
${body || `${esc(empty)}
`}`;
const list = (items: string[]): string =>
items.length
? `${items.map((i) => `- ${esc(i)}
`).join("")}
`
: "";
const html = `
${esc(patient.name)} — ${esc(t("patientCard.pdf.title"))}
${esc(patient.name)}
${esc(`${patient.age} · ${sexLabel} · ${t("patientCard.summary.mrn")} ${patient.fileNumber}`)}
${esc(t("patientCard.pdf.generated", { date: generated }))}
${section(
t("patientCard.overview"),
`${rows([
{ label: t("patientCard.summary.primaryCare"), value: patient.pcp },
{ label: t("patientCard.summary.lastSeen"), value: patient.encounters[0]?.date ?? "" },
{ label: t("patientCard.summary.status"), value: t(`patients.status.${patient.status}`) },
])}
`,
"",
)}
${section(
t("patientCard.allergies.title"),
list(
patient.allergies.map((a) =>
[a.substance, a.reaction, t(`patientCard.severity.${a.severity}`)]
.filter(Boolean)
.join(" — "),
),
),
t("patientCard.allergies.none"),
)}
${section(
t("patientCard.problems.title"),
list(
patient.problems.map((p) =>
p.since ? `${p.label} (${p.since})` : p.label,
),
),
t("patientCard.problems.empty"),
)}
${section(
t("patientCard.medications.title"),
list(
patient.medications.map((m) =>
[m.name, m.dose, m.frequency].filter(Boolean).join(" · "),
),
),
t("patientCard.medications.empty"),
)}
${section(
t("patientCard.vitals.title"),
`${rows([
{ label: t("patientCard.vitals.bp"), value: patient.vitals.bp },
{ label: t("patientCard.vitals.hr"), value: patient.vitals.hr },
{ label: t("patientCard.vitals.temp"), value: patient.vitals.temp },
{ label: t("patientCard.vitals.spo2"), value: patient.vitals.spo2 },
])}
`,
"",
)}
${section(
t("patientCard.labs.title"),
list(
patient.labs.map((l) =>
`${l.name}: ${l.value} (${t(`patientCard.labFlag.${l.flag}`)})`,
),
),
t("patientCard.labs.empty"),
)}
${section(
t("patientCard.visits.title"),
patient.encounters
.map(
(e) =>
`${esc(e.type)} ${esc(e.date)} ${esc(e.provider)}
${esc(e.summary)}
`,
)
.join(""),
t("patientCard.visits.empty"),
)}
`;
const win = window.open("", "_blank", "width=820,height=1000");
if (!win) return;
win.document.open();
win.document.write(html);
win.document.close();
win.focus();
// Let layout settle before invoking print.
win.setTimeout(() => win.print(), 250);
}