package config import ( "fmt" "os" "strconv" "strings" ) type Config struct { AppEnv string Port string DatabaseURL string FrontendURL string JWTSecret string NeonAuthURL string SMTPHost string SMTPPort int SMTPUsername string SMTPPassword string EmailFrom string GoogleClientID string GoogleClientSecret string GoogleRedirectURL string StripeSecretKey string StripeWebhookSecret string StripePriceIDs map[string]string } func Load() (*Config, error) { port := getEnv("PORT", "8081") dbURL := getEnv("DATABASE_URL", "") if dbURL == "" { return nil, fmt.Errorf("DATABASE_URL is required") } smtpPort, _ := strconv.Atoi(getEnv("SMTP_PORT", "465")) return &Config{ AppEnv: getEnv("APP_ENV", "development"), Port: port, DatabaseURL: dbURL, FrontendURL: getEnv("FRONTEND_URL", "http://localhost:3000"), JWTSecret: getEnv("JWT_SECRET", "change-me-in-production"), NeonAuthURL: getEnv("NEON_AUTH_URL", ""), SMTPHost: getEnv("SMTP_HOST", "smtp.purelymail.com"), SMTPPort: smtpPort, SMTPUsername: getEnvAllowEmpty("SMTP_USERNAME", "noreply@tdvorak.dev"), SMTPPassword: getEnv("SMTP_PASSWORD", ""), EmailFrom: getEnv("EMAIL_FROM", "noreply@tdvorak.dev"), GoogleClientID: getEnv("GOOGLE_CLIENT_ID", ""), GoogleClientSecret: getEnv("GOOGLE_CLIENT_SECRET", ""), GoogleRedirectURL: getEnv("GOOGLE_REDIRECT_URL", ""), StripeSecretKey: getEnv("STRIPE_SECRET_KEY", ""), StripeWebhookSecret: getEnv("STRIPE_WEBHOOK_SECRET", ""), StripePriceIDs: map[string]string{ "monthly": getEnv("STRIPE_PRICE_ID", ""), "starter": getEnv("STRIPE_STARTER_PRICE_ID", ""), "growth": getEnv("STRIPE_GROWTH_PRICE_ID", ""), "multi-location": getEnv("STRIPE_MULTI_LOCATION_PRICE_ID", ""), "pro": getEnv("STRIPE_PRO_PRICE_ID", ""), "business": getEnv("STRIPE_BUSINESS_PRICE_ID", ""), "starter:czk": getEnv("STRIPE_STARTER_CZK_PRICE_ID", ""), "starter:usd": getEnv("STRIPE_STARTER_USD_PRICE_ID", ""), "pro:czk": getEnv("STRIPE_PRO_CZK_PRICE_ID", ""), "pro:usd": getEnv("STRIPE_PRO_USD_PRICE_ID", ""), "business:czk": getEnv("STRIPE_BUSINESS_CZK_PRICE_ID", ""), "business:usd": getEnv("STRIPE_BUSINESS_USD_PRICE_ID", ""), }, }, nil } func getEnv(key, defaultVal string) string { if v := os.Getenv(key); v != "" { return v } return defaultVal } func getEnvAllowEmpty(key, defaultVal string) string { if v, ok := os.LookupEnv(key); ok { return v } return defaultVal } func (cfg *Config) StripeSecretConfigured() bool { return strings.TrimSpace(cfg.StripeSecretKey) != "" } func (cfg *Config) StripeWebhookConfigured() bool { return strings.TrimSpace(cfg.StripeWebhookSecret) != "" } func (cfg *Config) StripeHasAnyPriceConfigured() bool { for _, priceID := range cfg.StripePriceIDs { if strings.TrimSpace(priceID) != "" { return true } } return false } func (cfg *Config) StripeCheckoutReady() bool { return cfg.StripeSecretConfigured() && cfg.StripeHasAnyPriceConfigured() }