import { GHLClient } from '../client'; import { GHLConversation, GHLMessage, SendMessageDTO, GHLPaginatedResponse } from '@/types/ghl'; export interface ConversationSearchParams { locationId?: string; contactId?: string; limit?: number; startAfterId?: string; status?: 'all' | 'read' | 'unread' | 'starred'; } export interface SendSMSParams { contactId: string; message: string; fromNumber?: string; } export interface SendEmailParams { contactId: string; subject: string; htmlBody: string; fromEmail?: string; fromName?: string; replyTo?: string; cc?: string[]; bcc?: string[]; attachments?: { url: string; name: string }[]; } export class ConversationsService { constructor(private client: GHLClient) {} // Get all conversations async getAll(params?: ConversationSearchParams): Promise> { const searchParams: Record = { locationId: params?.locationId || this.client.locationID, }; if (params?.limit) searchParams.limit = String(params.limit); if (params?.startAfterId) searchParams.startAfterId = params.startAfterId; if (params?.contactId) searchParams.contactId = params.contactId; if (params?.status) searchParams.status = params.status; // v2 API returns { conversations: [...] } - normalize to { data: [...] } const response = await this.client.get<{ conversations: GHLConversation[]; total?: number }>('/conversations/search', searchParams); return { data: response.conversations || [], meta: { total: response.total || response.conversations?.length || 0, currentPage: 1 }, }; } // Get a single conversation by ID async getById(conversationId: string): Promise { return this.client.get(`/conversations/${conversationId}`); } // Get conversation by contact ID async getByContactId(contactId: string): Promise { const result = await this.getAll({ contactId, limit: 1 }); return result.data?.[0] || null; } // Get messages in a conversation async getMessages(conversationId: string, params?: { limit?: number; startAfterId?: string; }): Promise> { const searchParams: Record = {}; if (params?.limit) searchParams.limit = String(params.limit); if (params?.startAfterId) searchParams.startAfterId = params.startAfterId; // v2 API returns { messages: [...] } - normalize to { data: [...] } const response = await this.client.get<{ messages: GHLMessage[]; total?: number }>(`/conversations/${conversationId}/messages`, searchParams); return { data: response.messages || [], meta: { total: response.total || response.messages?.length || 0, currentPage: 1 }, }; } // Send an SMS message async sendSMS(params: SendSMSParams): Promise { return this.client.post('/conversations/messages', { type: 'SMS', contactId: params.contactId, message: params.message, ...(params.fromNumber && { fromNumber: params.fromNumber }), }); } // Send an email message async sendEmail(params: SendEmailParams): Promise { return this.client.post('/conversations/messages', { type: 'Email', contactId: params.contactId, subject: params.subject, html: params.htmlBody, ...(params.fromEmail && { from: params.fromEmail }), ...(params.fromName && { fromName: params.fromName }), ...(params.replyTo && { replyTo: params.replyTo }), ...(params.cc?.length && { cc: params.cc }), ...(params.bcc?.length && { bcc: params.bcc }), ...(params.attachments?.length && { attachments: params.attachments }), }); } // Generic send message (SMS or Email) async send(params: SendMessageDTO): Promise { if (params.type === 'SMS') { return this.sendSMS({ contactId: params.contactId, message: params.message || '', }); } else { return this.sendEmail({ contactId: params.contactId, subject: params.subject || '', htmlBody: params.message || '', }); } } // Mark conversation as read async markAsRead(conversationId: string): Promise { await this.client.put(`/conversations/${conversationId}/status`, { status: 'read', }); } // Mark conversation as unread async markAsUnread(conversationId: string): Promise { await this.client.put(`/conversations/${conversationId}/status`, { status: 'unread', }); } // Star a conversation async star(conversationId: string): Promise { await this.client.put(`/conversations/${conversationId}/status`, { starred: true, }); } // Unstar a conversation async unstar(conversationId: string): Promise { await this.client.put(`/conversations/${conversationId}/status`, { starred: false, }); } // Delete a conversation (archive) async delete(conversationId: string): Promise { await this.client.delete(`/conversations/${conversationId}`); } // Get unread count async getUnreadCount(): Promise { const result = await this.getAll({ status: 'unread', limit: 1 }); return result.meta?.total || 0; } // Schedule a message (if supported) async scheduleMessage(params: SendMessageDTO & { scheduledAt: Date }): Promise { return this.client.post('/conversations/messages', { type: params.type, contactId: params.contactId, message: params.message, ...(params.subject && { subject: params.subject }), scheduledTimestamp: params.scheduledAt.toISOString(), }); } // Cancel a scheduled message async cancelScheduledMessage(messageId: string): Promise { await this.client.delete(`/conversations/messages/${messageId}/schedule`); } }