package config

import (
	"bufio"
	"log"
	"os"
	"strconv"
	"strings"
)

type Config struct {
	DatabaseURL    string
	JWTSecret      string
	RedisAddr      string
	ServerPort     string
	Env            string
	BaseURL        string
	CORSOrigins    []string
	RateLimitRPS   float64
	RateLimitBurst int
}

func Load() *Config {
	loadEnvFile(".env")

	port := getEnv("SERVER_PORT", "8080")
	jwtSecret := getEnv("JWT_SECRET", "dev-secret-change-me")
	env := getEnv("ENV", "development")

	if env == "production" && (jwtSecret == "" || jwtSecret == "dev-secret-change-me") {
		log.Fatal("JWT_SECRET must be set to a secure value in production")
	}

	corsOrigins := parseCORSOrigins(getEnv("CORS_ORIGINS", "http://localhost:5173,http://127.0.0.1:5173"))
	rateRPS := parseFloat(getEnv("RATE_LIMIT_RPS", "100"), 100)
	rateBurst := parseInt(getEnv("RATE_LIMIT_BURST", "200"), 200)

	return &Config{
		DatabaseURL:    getEnv("DATABASE_URL", "postgres://postgres:postgres@localhost:5432/calendarapi?sslmode=disable"),
		JWTSecret:      jwtSecret,
		RedisAddr:      os.Getenv("REDIS_ADDR"),
		ServerPort:     port,
		Env:            env,
		BaseURL:        getEnv("BASE_URL", "http://localhost:"+port),
		CORSOrigins:    corsOrigins,
		RateLimitRPS:   rateRPS,
		RateLimitBurst: rateBurst,
	}
}

func parseCORSOrigins(s string) []string {
	if s == "" {
		return []string{}
	}
	parts := strings.Split(s, ",")
	out := make([]string, 0, len(parts))
	for _, p := range parts {
		p = strings.TrimSpace(p)
		if p != "" {
			out = append(out, p)
		}
	}
	if len(out) == 0 {
		return []string{"http://localhost:5173", "http://127.0.0.1:5173"}
	}
	return out
}

func parseFloat(s string, def float64) float64 {
	v, err := strconv.ParseFloat(s, 64)
	if err != nil {
		return def
	}
	return v
}

func parseInt(s string, def int) int {
	v, err := strconv.Atoi(s)
	if err != nil {
		return def
	}
	return v
}

func loadEnvFile(path string) {
	f, err := os.Open(path)
	if err != nil {
		return
	}
	defer f.Close()

	scanner := bufio.NewScanner(f)
	for scanner.Scan() {
		line := strings.TrimSpace(scanner.Text())
		if line == "" || strings.HasPrefix(line, "#") {
			continue
		}
		k, v, ok := strings.Cut(line, "=")
		if !ok {
			continue
		}
		k = strings.TrimSpace(k)
		v = strings.TrimSpace(v)
		if os.Getenv(k) == "" {
			os.Setenv(k, v)
		}
	}
}

func getEnv(key, fallback string) string {
	if v := os.Getenv(key); v != "" {
		return v
	}
	return fallback
}
