package sms import ( "context" "fmt" "strings" "bookra/apps/backend/internal/config" "bookra/apps/backend/internal/db" "github.com/stripe/stripe-go/v81" "github.com/stripe/stripe-go/v81/invoiceitem" ) type BillingService struct { cfg config.Config repo db.Repository smsPriceIDs map[string]string // currency -> price ID } func NewBillingService(cfg config.Config, repo db.Repository) *BillingService { return &BillingService{ cfg: cfg, repo: repo, smsPriceIDs: cfg.StripeSMSPriceMatrix, } } // PriceIDForCurrency returns the Stripe price ID for SMS in the given currency func (b *BillingService) PriceIDForCurrency(currency string) string { c := strings.ToLower(strings.TrimSpace(currency)) if c == "" { c = "czk" } if id := b.smsPriceIDs[c]; id != "" { return id } // Fallback to CZK return b.smsPriceIDs["czk"] } // CreateMonthlyInvoiceItem creates a Stripe InvoiceItem for the total SMS usage of a month. // This adds a line item to the customer's next invoice — charging all messages together. func (b *BillingService) CreateMonthlyInvoiceItem(ctx context.Context, customerID string, currency string, yearMonth string, messageCount int, totalCents int) (string, error) { if customerID == "" { return "", fmt.Errorf("customer id is empty") } priceID := b.PriceIDForCurrency(currency) c := strings.ToLower(strings.TrimSpace(currency)) if c == "" { c = "czk" } // If a Stripe price is configured, use Price + Quantity for a clean invoice line if priceID != "" { item, err := invoiceitem.New(&stripe.InvoiceItemParams{ Customer: stripe.String(customerID), Price: stripe.String(priceID), Quantity: stripe.Int64(int64(messageCount)), Description: stripe.String(fmt.Sprintf("SMS Messages (%s) — %d messages", yearMonth, messageCount)), }) if err != nil { return "", fmt.Errorf("failed to create invoice item: %w", err) } return item.ID, nil } // Fallback: explicit amount (for dev/testing when no price configured yet) item, err := invoiceitem.New(&stripe.InvoiceItemParams{ Customer: stripe.String(customerID), Amount: stripe.Int64(int64(totalCents)), Currency: stripe.String(c), Description: stripe.String(fmt.Sprintf("SMS Messages (%s) — %d messages", yearMonth, messageCount)), }) if err != nil { return "", fmt.Errorf("failed to create invoice item: %w", err) } return item.ID, nil }