// In-memory store for per-patient AI handoff toggle, conversation stage, // and per-user after-hours handoff toggle. // Conversation key: `${userId}:${patientId}` export type ConversationStage = | "initial" // default — no active conversation | "reminder_initial" // office sent a reminder, waiting for first patient reply | "greeted" // reminder intro sent, waiting for yes/no | "done" // conversation complete | "new_patient_greeted" // new-patient greeting sent, waiting for patient intent | "asked_new_or_existing" // AI asked "new or existing patient?" | "asked_new_patient_insurance" // AI asked new patient about insurance | "asked_existing_insurance" // AI asked existing patient about same insurance | "asked_appointment_time" // AI asked when they'd like to come | "awaiting_masshealth_info" // AI asked for Member ID + DOB, waiting for reply | "asked_appointment_preference" // Selenium: ACTIVE — AI asked check-up vs problem | "asked_self_pay" // Selenium: INACTIVE — AI asked if self-pay exam | "asked_reschedule_confirm" // AI asked "Would you like to reschedule?" | "asked_reschedule_preference" // AI asked ASAP vs next week | "asked_reschedule_asap" // AI asked "Can you come tomorrow?" | "asked_reschedule_next_week" // AI offered Mon/Tue/Wed next week | "asked_reschedule_time"; // Day confirmed — AI asked morning or afternoon const handoffStore = new Map(); const stageStore = new Map(); const afterHoursStore = new Map(); // keyed by userId function convKey(userId: number, patientId: number): string { return `${userId}:${patientId}`; } // ── Per-patient handoff toggle (default ON) ─────────────────────────────────── export function getHandoff(userId: number, patientId: number): boolean { const k = convKey(userId, patientId); return handoffStore.has(k) ? handoffStore.get(k)! : true; } export function setHandoff(userId: number, patientId: number, enabled: boolean): void { handoffStore.set(convKey(userId, patientId), enabled); } // ── Per-user after-hours handoff toggle (default ON) ───────────────────────── export function getAfterHoursHandoff(userId: number): boolean { return afterHoursStore.has(userId) ? afterHoursStore.get(userId)! : true; } export function setAfterHoursHandoff(userId: number, enabled: boolean): void { afterHoursStore.set(userId, enabled); } // ── Conversation stage ──────────────────────────────────────────────────────── export function getStage(userId: number, patientId: number): ConversationStage { return stageStore.get(convKey(userId, patientId)) ?? "initial"; } export function setStage(userId: number, patientId: number, stage: ConversationStage): void { stageStore.set(convKey(userId, patientId), stage); } // Called when office sends an outbound reminder — marks next patient reply // as the start of a reminder conversation. export function resetConversation(userId: number, patientId: number): void { stageStore.set(convKey(userId, patientId), "reminder_initial"); } // Called when office sends the new-patient greeting — marks next patient reply // as the start of the new-patient conversation flow. export function startNewPatientConversation(userId: number, patientId: number): void { stageStore.set(convKey(userId, patientId), "new_patient_greeted"); } // ── Pending reschedule data ─────────────────────────────────────────────────── // Holds the confirmed new date while AI waits for a time-slot answer. interface PendingReschedule { newDate: Date; // JS Date for the new appointment day (midnight UTC) dayLabel: string; // human-readable, e.g. "Tuesday, May 19" } const pendingRescheduleStore = new Map(); export function setPendingReschedule(userId: number, patientId: number, data: PendingReschedule): void { pendingRescheduleStore.set(convKey(userId, patientId), data); } export function getPendingReschedule(userId: number, patientId: number): PendingReschedule | undefined { return pendingRescheduleStore.get(convKey(userId, patientId)); } export function clearPendingReschedule(userId: number, patientId: number): void { pendingRescheduleStore.delete(convKey(userId, patientId)); }