package services import ( "crypto/rand" "encoding/hex" "fmt" "log" "time" "attune-heart-therapy/internal/config" ) // jitsiService implements the JitsiService interface type jitsiService struct { config *config.JitsiConfig } // NewJitsiService creates a new instance of JitsiService func NewJitsiService(cfg *config.JitsiConfig) JitsiService { return &jitsiService{ config: cfg, } } // CreateMeeting creates a new Jitsi meeting room for a booking func (j *jitsiService) CreateMeeting(bookingID uint, scheduledAt time.Time) (*JitsiMeeting, error) { // Generate a unique room ID roomID, err := j.generateRoomID(bookingID) if err != nil { log.Printf("Failed to generate room ID for booking %d: %v", bookingID, err) return nil, fmt.Errorf("failed to generate room ID: %w", err) } // Generate the meeting URL roomURL := j.GetMeetingURL(roomID) meeting := &JitsiMeeting{ RoomID: roomID, RoomURL: roomURL, } log.Printf("Created Jitsi meeting for booking %d: Room ID %s", bookingID, roomID) return meeting, nil } // GetMeetingURL generates the full Jitsi meeting URL for a given room ID func (j *jitsiService) GetMeetingURL(roomID string) string { baseURL := j.config.BaseURL if baseURL == "" { // Default to meet.jit.si if no base URL is configured baseURL = "https://meet.jit.si" } // Ensure the base URL doesn't end with a slash if baseURL[len(baseURL)-1] == '/' { baseURL = baseURL[:len(baseURL)-1] } return fmt.Sprintf("%s/%s", baseURL, roomID) } // DeleteMeeting handles cleanup of a Jitsi meeting room // Note: Jitsi Meet doesn't require explicit room deletion as rooms are ephemeral // This method is implemented for interface compliance and future extensibility func (j *jitsiService) DeleteMeeting(roomID string) error { // Jitsi Meet rooms are ephemeral and don't require explicit deletion // However, we can log the deletion for audit purposes log.Printf("Meeting room %s marked for cleanup", roomID) // In the future, if using Jitsi as a Service (JaaS) or custom deployment, // this method could make API calls to clean up resources return nil } // generateRoomID creates a unique room identifier for the meeting func (j *jitsiService) generateRoomID(bookingID uint) (string, error) { // Generate a random component for uniqueness randomBytes := make([]byte, 8) _, err := rand.Read(randomBytes) if err != nil { return "", fmt.Errorf("failed to generate random bytes: %w", err) } randomHex := hex.EncodeToString(randomBytes) // Create a room ID that includes the booking ID and timestamp for uniqueness timestamp := time.Now().Unix() roomID := fmt.Sprintf("booking-%d-%d-%s", bookingID, timestamp, randomHex) return roomID, nil }