package iam

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

type Config struct {
	AccessSecret      string
	RefreshSecret     string
	RefreshPepper     string
	AccessTTL         time.Duration
	RefreshTTL        time.Duration
	SessionTTL        time.Duration
	RefreshCookieName string
	CookieSecure      bool
	CookieDomain      string
	CookiePath        string
	CookieSameSite    string
	RedisAddr         string
	RedisPassword     string
	RedisDB           int
}

func LoadConfig() Config {
	cfg := Config{
		AccessSecret:      firstNonEmpty(strings.TrimSpace(os.Getenv("ACCESS_SECRET")), strings.TrimSpace(os.Getenv("AUTH_SECRET")), "dev-access-secret-change-me"),
		RefreshSecret:     firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_SECRET")), strings.TrimSpace(os.Getenv("AUTH_SECRET")), "dev-refresh-secret-change-me"),
		RefreshPepper:     firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_PEPPER")), "dev-refresh-pepper-change-me"),
		AccessTTL:         parseDuration("ACCESS_TTL", 60*time.Minute),
		RefreshTTL:        parseDuration("REFRESH_TTL", 7*24*time.Hour),
		RefreshCookieName: firstNonEmpty(strings.TrimSpace(os.Getenv("REFRESH_COOKIE_NAME")), "rt"),
		CookieSecure:      parseBool("COOKIE_SECURE", isProduction()),
		CookieDomain:      strings.TrimSpace(os.Getenv("COOKIE_DOMAIN")),
		CookiePath:        firstNonEmpty(strings.TrimSpace(os.Getenv("COOKIE_PATH")), "/"),
		CookieSameSite:    firstNonEmpty(strings.TrimSpace(os.Getenv("COOKIE_SAMESITE")), "Lax"),
		RedisAddr:         strings.TrimSpace(os.Getenv("REDIS_ADDR")),
		RedisPassword:     os.Getenv("REDIS_PASSWORD"),
		RedisDB:           parseInt("REDIS_DB", 0),
	}
	cfg.SessionTTL = parseDuration("SESSION_TTL", cfg.RefreshTTL)
	return cfg
}

func parseDuration(key string, fallback time.Duration) time.Duration {
	value := strings.TrimSpace(os.Getenv(key))
	if value == "" {
		return fallback
	}
	d, err := time.ParseDuration(value)
	if err != nil || d <= 0 {
		return fallback
	}
	return d
}

func parseBool(key string, fallback bool) bool {
	value := strings.TrimSpace(os.Getenv(key))
	if value == "" {
		return fallback
	}
	parsed, err := strconv.ParseBool(value)
	if err != nil {
		return fallback
	}
	return parsed
}

func parseInt(key string, fallback int) int {
	value := strings.TrimSpace(os.Getenv(key))
	if value == "" {
		return fallback
	}
	parsed, err := strconv.Atoi(value)
	if err != nil {
		return fallback
	}
	return parsed
}

func isProduction() bool {
	env := strings.ToLower(strings.TrimSpace(os.Getenv("APP_ENV")))
	return env == "prod" || env == "production"
}

func firstNonEmpty(values ...string) string {
	for _, v := range values {
		if strings.TrimSpace(v) != "" {
			return v
		}
	}
	return ""
}
