import { loadSystemConfig } from "./system-config"; export type CalendarEvent = { summary: string; description: string; startTime: Date; endTime: Date; location?: string; attendees?: string[]; }; /** * Generate ICS file content for calendar invitation */ export function generateIcsFile(event: CalendarEvent): string { const formatDate = (date: Date): string => { return date .toISOString() .replace(/[-:]/g, "") .replace(/\.\d{3}/, ""); }; const startDateStr = formatDate(event.startTime); const endDateStr = formatDate(event.endTime); const now = formatDate(new Date()); const uid = `${now}@estate-platform.com`; // Escape special characters in text const escape = (text: string) => { return text .replace(/\\/g, "\\\\") .replace(/;/g, "\\;") .replace(/,/g, "\\,") .replace(/\n/g, "\\n"); }; let icsContent = [ "BEGIN:VCALENDAR", "VERSION:2.0", "PRODID:-//Estate Platform//Webinar Calendar//EN", "CALSCALE:GREGORIAN", "METHOD:REQUEST", "BEGIN:VEVENT", `UID:${uid}`, `DTSTAMP:${now}`, `DTSTART:${startDateStr}`, `DTEND:${endDateStr}`, `SUMMARY:${escape(event.summary)}`, `DESCRIPTION:${escape(event.description)}`, ]; if (event.location) { icsContent.push(`LOCATION:${escape(event.location)}`); } // Add organizer icsContent.push("ORGANIZER;CN=Estate Platform:mailto:noreply@estate-platform.com"); // Add attendees if (event.attendees && event.attendees.length > 0) { event.attendees.forEach((email) => { icsContent.push( `ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=NEEDS-ACTION;RSVP=TRUE:mailto:${email}` ); }); } icsContent.push( "STATUS:CONFIRMED", "SEQUENCE:0", "BEGIN:VALARM", "TRIGGER:-PT15M", "ACTION:DISPLAY", "DESCRIPTION:Reminder: Webinar starts in 15 minutes", "END:VALARM", "END:VEVENT", "END:VCALENDAR", ); return icsContent.join("\r\n"); } /** * Create a Google Calendar event (if service account is configured) */ export async function createGoogleCalendarEvent( event: CalendarEvent ): Promise<{ success: boolean; eventId?: string; error?: string }> { try { const config = await loadSystemConfig(); const calendarConfig = config.googleCalendar; if (!calendarConfig?.enabled) { return { success: false, error: "Google Calendar is not enabled", }; } if ( !calendarConfig.serviceAccountEmail || !calendarConfig.serviceAccountKey || !calendarConfig.calendarId ) { return { success: false, error: "Google Calendar credentials are not configured", }; } // In a real implementation, you would use the googleapis library // to create the event using service account credentials // For now, we'll just return a mock success // TODO: Implement actual Google Calendar API integration console.log("[CALENDAR] Would create event:", event); return { success: true, eventId: `mock-event-${Date.now()}`, }; } catch (error) { console.error("[CALENDAR] Error creating event:", error); return { success: false, error: error instanceof Error ? error.message : "Failed to create calendar event", }; } } /** * Helper to calculate end time based on duration in minutes */ export function calculateEndTime(startTime: Date, durationMinutes: number): Date { return new Date(startTime.getTime() + durationMinutes * 60 * 1000); } /** * Create a calendar event for a webinar registration */ export async function createWebinarCalendarEvent( webinar: { title: string; description: string; startAt: Date; duration: number; meetingInfo: any; }, attendeeEmail: string ): Promise<{ icsContent: string; googleEventId?: string }> { const endTime = calculateEndTime(webinar.startAt, webinar.duration); const meetingLink = webinar.meetingInfo?.meetingLink || "TBD"; const description = `${webinar.description}\n\nJoin Link: ${meetingLink}`; const event: CalendarEvent = { summary: webinar.title, description, startTime: webinar.startAt, endTime, location: meetingLink, attendees: [attendeeEmail], }; // Generate ICS file const icsContent = generateIcsFile(event); // Optionally create Google Calendar event const googleResult = await createGoogleCalendarEvent(event); return { icsContent, googleEventId: googleResult.success ? googleResult.eventId : undefined, }; }