import type { RecordType } from "../api/types";
/** REC-3: limits per check. Files go straight to storage, so nginx's 11 MB cap does not apply. */
export const RECORD_LIMITS = { perCheck: 20, pagesPerDocument: 20, bytesPerFile: 15 * 1024 * 1024 };
export const ACCEPTED: Record<string, string> = {
"text/plain": "TXT",
"application/pdf": "PDF",
"image/jpeg": "JPG",
"image/png": "PNG",
"image/heic": "HEIC",
"image/heif": "HEIC",
};
const byExtension: Record<string, string> = { txt: "text/plain", pdf: "application/pdf", jpg: "image/jpeg", jpeg: "image/jpeg", png: "image/png", heic: "image/heic", heif: "image/heic" };
export const recordTypes: Record<RecordType, string> = {
prescription: "Prescription",
lab_result: "Lab result",
discharge_summary: "Discharge summary",
clinic_note: "Clinic note",
other: "Other",
};
/** Some browsers give HEIC and TXT files no type; fall back to the extension. */
export function contentTypeOf(file: { name: string; type: string }): string {
if (file.type && ACCEPTED[file.type]) return file.type === "image/heif" ? "image/heic" : file.type;
return byExtension[file.name.split(".").pop()?.toLowerCase() ?? ""] ?? file.type ?? "";
}
const mb = (bytes: number) => (bytes / 1024 / 1024).toFixed(1);
/** The message names the file and says by how much it is over (REC-3). */
export function fileProblem(file: { name: string; type: string; size: number }): string | null {
if (!ACCEPTED[contentTypeOf(file)]) return `${file.name} is not a file Context reads. Use TXT, PDF, JPG, PNG or HEIC.`;
if (file.size === 0) return `${file.name} is empty.`;
if (file.size > RECORD_LIMITS.bytesPerFile)
return `${file.name} is ${mb(file.size)} MB, ${mb(file.size - RECORD_LIMITS.bytesPerFile)} MB over the 15 MB limit per file.`;
return null;
}
/** How many of the chosen files fit, and the message when some do not. */
export function roomFor(existing: number, adding: number): { fits: number; message: string | null } {
const room = Math.max(0, RECORD_LIMITS.perCheck - existing);
if (adding <= room) return { fits: adding, message: null };
return {
fits: room,
message: `A check can use up to ${RECORD_LIMITS.perCheck} records. This patient has ${existing}, so ${adding - room} of these ${adding === 1 ? "is" : "are"} left out.`,
};
}
/** "01-clinic_prescription.pdf" becomes "Clinic prescription" (REC-4: from the file name, editable). */
export function titleFromFile(name: string): string {
const title = name
.replace(/\.[a-z0-9]{2,5}$/i, "")
.replace(/^\d+(?=[\s._-])/, "")
.replace(/[-_.]+/g, " ")
.replace(/\s+/g, " ")
.trim()
.slice(0, 120);
return title ? title[0].toUpperCase() + title.slice(1) : "Untitled record";
}
export function guessType(name: string): RecordType {
const n = name.toLowerCase();
if (/lab|egfr|blood|chemistry|result|e\/?u\/?cr|urea|creatinine/.test(n)) return "lab_result";
if (/prescri|\brx\b|medic/.test(n)) return "prescription";
if (/discharge|hospital|summary/.test(n)) return "discharge_summary";
if (/note|clinic|consult/.test(n)) return "clinic_note";
return "other";
}