package client import ( "context" "fmt" "log" "apskel-pos-be/config" firebase "firebase.google.com/go/v4" "firebase.google.com/go/v4/messaging" "google.golang.org/api/option" ) type FcmClient interface { SendMulticastNotification(ctx context.Context, tokens []string, title string, body string) error } type fcmClient struct { messagingClient *messaging.Client } func NewFcmClient(cfg *config.Firebase) FcmClient { if cfg == nil || cfg.GetCredentialsFile() == "" { log.Println("FCM: credentials file not configured, FCM client is disabled") return &fcmClient{messagingClient: nil} } opt := option.WithCredentialsFile(cfg.GetCredentialsFile()) app, err := firebase.NewApp(context.Background(), nil, opt) if err != nil { log.Printf("FCM: failed to initialize Firebase app: %v", err) return &fcmClient{messagingClient: nil} } client, err := app.Messaging(context.Background()) if err != nil { log.Printf("FCM: failed to create messaging client: %v", err) return &fcmClient{messagingClient: nil} } log.Println("FCM: client initialized successfully") return &fcmClient{messagingClient: client} } func (c *fcmClient) SendMulticastNotification(ctx context.Context, tokens []string, title string, body string) error { if c.messagingClient == nil { log.Println("FCM: client not initialized, skipping notification") return nil } if len(tokens) == 0 { return nil } message := &messaging.MulticastMessage{ Notification: &messaging.Notification{ Title: title, Body: body, }, Tokens: tokens, Android: &messaging.AndroidConfig{ Priority: "high", }, } response, err := c.messagingClient.SendMulticast(ctx, message) if err != nil { return fmt.Errorf("FCM: failed to send multicast notification: %w", err) } if response.FailureCount > 0 { log.Printf("FCM: %d tokens failed out of %d", response.FailureCount, len(tokens)) for i, resp := range response.Responses { if !resp.Success { log.Printf("FCM: token[%d] failed: %v", i, resp.Error) } } } log.Printf("FCM: sent %d/%d notifications successfully", response.SuccessCount, len(tokens)) return nil }