import { businessConfig } from "@/lib/seo-config"; export type AdminPhoneCallTurn = { id: string; role: string; text: string; source?: string; kind?: string; createdAt: number; }; export type AdminPhoneCallDetail = { call: { id: string; roomName: string; participantIdentity: string; pathname?: string; pageUrl?: string; source?: string; startedAt: number; endedAt?: number; durationMs: number | null; callStatus: "started" | "completed" | "failed"; transcriptTurnCount: number; answered: boolean; agentAnsweredAt?: number; linkedLeadId?: string; leadOutcome: "none" | "contact" | "requestMachine"; handoffRequested: boolean; handoffReason?: string; summaryText?: string; notificationStatus: "pending" | "sent" | "failed" | "disabled"; notificationSentAt?: number; notificationError?: string; recordingStatus?: "pending" | "starting" | "recording" | "completed" | "failed"; recordingUrl?: string; recordingError?: string; }; linkedLead: null | { id: string; type: "contact" | "requestMachine"; status: "pending" | "delivered" | "failed"; firstName: string; lastName: string; email: string; phone: string; company?: string; intent?: string; message?: string; createdAt: number; }; turns: AdminPhoneCallTurn[]; }; export function formatPhoneCallTimestamp(timestamp?: number) { if (!timestamp) { return "—"; } return new Date(timestamp).toLocaleString("en-US", { year: "numeric", month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", }); } export function formatPhoneCallDuration(durationMs: number | null | undefined) { if (typeof durationMs !== "number" || durationMs <= 0) { return "—"; } const totalSeconds = Math.round(durationMs / 1000); const minutes = Math.floor(totalSeconds / 60); const seconds = totalSeconds % 60; return `${minutes}:${String(seconds).padStart(2, "0")}`; } export function normalizePhoneFromIdentity(identity?: string) { const digits = String(identity || "").replace(/\D/g, ""); if (!digits) { return ""; } if (digits.length === 10) { return `+1${digits}`; } if (digits.length === 11 && digits.startsWith("1")) { return `+${digits}`; } return `+${digits}`; } export function buildPhoneCallSummary(detail: Pick) { const answeredLabel = detail.call.answered ? "Jessica answered the call." : "Jessica did not fully answer the call."; const leadLabel = detail.call.leadOutcome === "none" ? "No lead was submitted." : detail.call.leadOutcome === "requestMachine" ? "A machine request lead was submitted." : "A contact lead was submitted."; const lastMeaningfulUserTurn = [...detail.turns] .reverse() .find((turn) => turn.role === "user" && turn.text.trim()); const leadMessage = detail.linkedLead?.message?.trim() || detail.linkedLead?.intent?.trim() || lastMeaningfulUserTurn?.text.trim() || ""; const callerNumber = normalizePhoneFromIdentity(detail.call.participantIdentity) || detail.call.participantIdentity; const parts = [ `Caller: ${callerNumber || "Unknown caller"}.`, answeredLabel, leadLabel, ]; if (detail.call.handoffRequested) { parts.push(`Human escalation requested${detail.call.handoffReason ? `: ${detail.call.handoffReason}.` : "."}`); } if (leadMessage) { parts.push(`Topic: ${leadMessage.replace(/\s+/g, " ").slice(0, 220)}.`); } return parts.join(" "); } export async function sendPhoneCallSummaryEmail(args: { detail: AdminPhoneCallDetail; adminUrl: string; }) { const resendApiKey = String(process.env.RESEND_API_KEY || "").trim(); const adminEmail = String(process.env.ADMIN_EMAIL || "").trim().toLowerCase(); const fromEmail = String(process.env.PHONE_CALL_SUMMARY_FROM_EMAIL || "").trim(); if (!adminEmail || !resendApiKey || !fromEmail) { const missing = [ !adminEmail ? "ADMIN_EMAIL" : null, !resendApiKey ? "RESEND_API_KEY" : null, !fromEmail ? "PHONE_CALL_SUMMARY_FROM_EMAIL" : null, ].filter(Boolean); return { status: "disabled" as const, error: `${missing.join(", ")} is not configured.`, }; } const callUrl = `${args.adminUrl.replace(/\/$/, "")}/admin/calls/${args.detail.call.id}`; const summaryText = buildPhoneCallSummary(args.detail); const callerNumber = normalizePhoneFromIdentity(args.detail.call.participantIdentity) || "Unknown caller"; const statusLabel = args.detail.call.callStatus.toUpperCase(); const text = [ `Rocky Mountain Vending phone call summary`, ``, `Caller: ${callerNumber}`, `Started: ${formatPhoneCallTimestamp(args.detail.call.startedAt)}`, `Duration: ${formatPhoneCallDuration(args.detail.call.durationMs)}`, `Call status: ${statusLabel}`, `Jessica answered: ${args.detail.call.answered ? "Yes" : "No"}`, `Lead outcome: ${args.detail.call.leadOutcome}`, `Handoff requested: ${args.detail.call.handoffRequested ? "Yes" : "No"}`, `Recording status: ${args.detail.call.recordingStatus || "Unavailable"}`, args.detail.call.recordingUrl ? `Recording URL: ${args.detail.call.recordingUrl}` : `Recording URL: Not available in RMV admin`, `Summary: ${summaryText}`, `Admin call detail: ${callUrl}`, args.detail.linkedLead?.id ? `Linked lead: ${args.detail.linkedLead.id}` : `Linked lead: None`, ``, `Recent transcript:`, ...args.detail.turns.slice(-6).map((turn) => `${turn.role}: ${turn.text}`), ].join("\n"); const response = await fetch("https://api.resend.com/emails", { method: "POST", headers: { Authorization: `Bearer ${resendApiKey}`, "Content-Type": "application/json", }, body: JSON.stringify({ from: fromEmail, to: [adminEmail], subject: `[RMV Phone] ${statusLabel} call from ${callerNumber}`, text, }), }); const body = (await response.json().catch(() => ({}))) as { message?: string; error?: unknown }; if (!response.ok) { const errorText = typeof body?.message === "string" ? body.message : typeof body?.error === "string" ? body.error : `Resend request failed with status ${response.status}.`; return { status: "failed" as const, error: errorText, }; } return { status: "sent" as const, error: undefined, }; } export function buildFallbackPhoneCallUrl(callId: string) { return `${businessConfig.website.replace(/\/$/, "")}/admin/calls/${callId}`; }