package config

import (
	"fmt"
	"os"
	"strconv"
	"strings"
	"time"
)

// Config centralizes runtime configuration loaded from the environment.
type Config struct {
	AppName               string
	Port                  string
	DatabaseURL           string
	MaxOpenConns          int
	MaxIdleConns          int
	ConnMaxIdle           time.Duration
	MercadoPagoBaseURL    string
	MarketplaceCommission float64
	JWTSecret             string
	JWTExpiresIn          time.Duration
	PasswordPepper        string
	CORSOrigins           []string
}

// Load reads configuration from environment variables and applies sane defaults
// for local development.
func Load() Config {
	cfg := Config{
		AppName:               getEnv("APP_NAME", "saveinmed-performance-core"),
		Port:                  getEnv("PORT", "8214"),
		DatabaseURL:           getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/saveinmed?sslmode=disable"),
		MaxOpenConns:          getEnvInt("DB_MAX_OPEN_CONNS", 15),
		MaxIdleConns:          getEnvInt("DB_MAX_IDLE_CONNS", 5),
		ConnMaxIdle:           getEnvDuration("DB_CONN_MAX_IDLE", 5*time.Minute),
		MercadoPagoBaseURL:    getEnv("MERCADOPAGO_BASE_URL", "https://api.mercadopago.com"),
		MarketplaceCommission: getEnvFloat("MARKETPLACE_COMMISSION", 2.5),
		JWTSecret:             getEnv("JWT_SECRET", "dev-secret"),
		JWTExpiresIn:          getEnvDuration("JWT_EXPIRES_IN", 24*time.Hour),
		PasswordPepper:        getEnv("PASSWORD_PEPPER", ""),
		CORSOrigins:           getEnvStringSlice("CORS_ORIGINS", []string{"*"}),
	}

	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
}
