export type MessageDelayUnit = 'minutes' | 'hours' | 'days' | 'weeks' | 'months'; export const MESSAGE_AUTOMATION_TRIGGERS = [ 'person_created', 'lead_submitted', 'deal_created', 'deal_stage_changed', 'deal_won', 'deal_lost', 'ticket_created', 'ticket_resolved', 'invoice_issued', 'invoice_paid', 'activity_created', 'activity_done', 'sms_link_clicked', ] as const; export const MAX_MESSAGE_REPEAT = 10; export const MAX_MESSAGE_SMS = 160; export function delayMs(value: number, unit: MessageDelayUnit): number { const n = Math.max(0, Math.trunc(Number(value) || 0)); if (unit === 'minutes') return n * 60_000; if (unit === 'hours') return n * 3_600_000; if (unit === 'days') return n * 86_400_000; if (unit === 'weeks') return n * 7 * 86_400_000; return n * 30 * 86_400_000; } export function addDelay( from: Date, value: number, unit: MessageDelayUnit, ): Date { const n = Math.max(0, Math.trunc(Number(value) || 0)); if (unit === 'months') { const next = new Date(from.getTime()); next.setMonth(next.getMonth() + n); return next; } return new Date(from.getTime() + delayMs(n, unit)); } export function buildSendAts( now: Date, startValue: number, startUnit: MessageDelayUnit, repeatCount: number, intervalValue: number, intervalUnit: MessageDelayUnit, ): Date[] { const count = Math.min( MAX_MESSAGE_REPEAT, Math.max(1, Math.trunc(Number(repeatCount) || 1)), ); const first = addDelay(now, startValue, startUnit); const times = [first]; let cursor = first; for (let i = 1; i < count; i += 1) { cursor = addDelay(cursor, Math.max(1, intervalValue), intervalUnit); times.push(cursor); } return times; } export function applyMessageTemplate( text: string, vars: { title?: string; name?: string; phone?: string; date?: string; company?: string; }, ): string { const map: Record = { title: vars.title ?? '', عنوان: vars.title ?? '', نام: vars.name ?? '', name: vars.name ?? '', شماره: vars.phone ?? '', phone: vars.phone ?? '', تاریخ: vars.date ?? '', date: vars.date ?? '', شرکت: vars.company ?? '', company: vars.company ?? '', }; return text.replace(/\{([^}]+)\}/g, (full, key: string) => { const next = map[key.trim()]; return next === undefined ? full : next; }); } export function clipSms(text: string): string { const trimmed = text.trim(); if (trimmed.length <= MAX_MESSAGE_SMS) return trimmed; return `${trimmed.slice(0, MAX_MESSAGE_SMS - 1)}…`; } /** When this event happens, cancel leftover messages of these earlier triggers. */ export function cancelTriggersFor( trigger: (typeof MESSAGE_AUTOMATION_TRIGGERS)[number], ): (typeof MESSAGE_AUTOMATION_TRIGGERS)[number][] { if (trigger === 'invoice_paid') return ['invoice_issued']; if (trigger === 'ticket_resolved') return ['ticket_created']; if (trigger === 'deal_won' || trigger === 'deal_lost') { return ['deal_created', 'deal_stage_changed']; } if (trigger === 'activity_done') return ['activity_created']; return []; }