package config import ( "fmt" "os" "strconv" "strings" "time" "github.com/joho/godotenv" ) // Config centralizes runtime configuration loaded from the environment. type Config struct { AppName string Port string DatabaseURL string MercadoPagoBaseURL string MarketplaceCommission float64 BuyerFeeRate float64 // Fee rate applied to buyer prices (e.g., 0.12 = 12%) JWTSecret string JWTExpiresIn time.Duration PasswordPepper string CORSOrigins []string BackendHost string SwaggerSchemes []string AdminName string AdminUsername string AdminEmail string AdminPassword string } // Load reads configuration from environment variables and applies sane defaults // for local development. func Load() Config { _ = godotenv.Load() // Load from .env if present cfg := Config{ AppName: getEnv("APP_NAME", "saveinmed-performance-core"), Port: getEnv("BACKEND_PORT", "8214"), DatabaseURL: getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/saveinmed?sslmode=disable"), MercadoPagoBaseURL: getEnv("MERCADOPAGO_BASE_URL", "https://api.mercadopago.com"), MarketplaceCommission: getEnvFloat("MARKETPLACE_COMMISSION", 2.5), BuyerFeeRate: getEnvFloat("BUYER_FEE_RATE", 0.12), // 12% invisible fee JWTSecret: getEnv("JWT_SECRET", "dev-secret"), JWTExpiresIn: getEnvDuration("JWT_EXPIRES_IN", 24*time.Hour), PasswordPepper: getEnv("PASSWORD_PEPPER", ""), CORSOrigins: getEnvStringSlice("CORS_ORIGINS", []string{"*"}), BackendHost: getEnv("BACKEND_HOST", ""), SwaggerSchemes: getEnvStringSlice("SWAGGER_SCHEMES", []string{"http"}), AdminName: getEnv("ADMIN_NAME", "Administrator"), AdminUsername: getEnv("ADMIN_USERNAME", "admin"), AdminEmail: getEnv("ADMIN_EMAIL", "admin@saveinmed.com"), AdminPassword: getEnv("ADMIN_PASSWORD", "admin123"), } return cfg } // Addr returns the address binding for the HTTP server. func (c Config) Addr() string { return fmt.Sprintf(":%s", c.Port) } func getEnv(key, fallback string) string { if value := os.Getenv(key); value != "" { return value } return fallback } func getEnvInt(key string, fallback int) int { if value := os.Getenv(key); value != "" { if parsed, err := strconv.Atoi(value); err == nil { return parsed } } return fallback } func getEnvDuration(key string, fallback time.Duration) time.Duration { if value := os.Getenv(key); value != "" { if parsed, err := time.ParseDuration(value); err == nil { return parsed } } return fallback } func getEnvFloat(key string, fallback float64) float64 { if value := os.Getenv(key); value != "" { if parsed, err := strconv.ParseFloat(value, 64); err == nil { return parsed } } return fallback } func getEnvStringSlice(key string, fallback []string) []string { if value := os.Getenv(key); value != "" { parts := strings.Split(value, ",") result := make([]string, 0, len(parts)) for _, p := range parts { if trimmed := strings.TrimSpace(p); trimmed != "" { result = append(result, trimmed) } } if len(result) > 0 { return result } } return fallback }