package config

import (
	"log"
	"os"
	"strconv"
	"strings"

	"github.com/joho/godotenv"
)

type Config struct {
	DBType      string
	DBDSN       string
	JWTSecret   string
	CSRFSecret  string
	AppPort     string
	Environment string

	AutoKillPortOnStartup bool
	AllowedOrigins        []string
	TrustProxy            bool
	ProxyHeader           string
	TrustProxyProxies     []string
	TrustProxyLoopback    bool
	TrustProxyLinkLocal   bool
	TrustProxyPrivate     bool
	TrustProxyUnixSocket  bool
	EnableIPValidation    bool
	TelegramToken         string
	TelegramChatID        string
	SuperAdminPassword    string
}

func LoadConfig() *Config {
	_ = godotenv.Load()

	dbType := getEnv("DB_TYPE", "sqlite")
	dbDSN := getEnv("DB_DSN", "spareparts.db")

	// Jika tipe data adalah mysql dan DSN tidak disediakan, coba bangun dari komponen .env lain
	if dbType == "mysql" && (dbDSN == "spareparts.db" || os.Getenv("DB_DSN") == "") {
		user := getEnv("DB_USER", "root")
		pass := getEnv("DB_PASSWORD", "")
		host := getEnv("DB_HOST", "127.0.0.1")
		port := getEnv("DB_PORT", "3306")
		name := getEnv("DB_NAME", "spareparts")
		charset := getEnv("DB_CHARSET", "utf8mb4")

		// Validasi: di production, DB_PASSWORD tidak boleh kosong
		env := getEnv("ENV", "production")
		if env == "production" && strings.TrimSpace(pass) == "" {
			log.Fatal("FATAL: DB_PASSWORD tidak boleh kosong di environment production. " +
				"Set DB_PASSWORD dengan password yang kuat di file .env")
		}
		if strings.TrimSpace(pass) == "" {
			log.Println("⚠️  WARNING: DB_PASSWORD kosong. Sangat tidak disarankan untuk production.")
		}

		// format: user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local
		dbDSN = user + ":" + pass + "@tcp(" + host + ":" + port + ")/" + name + "?charset=" + charset + "&parseTime=True&loc=Local"
	}

	jwtSecret := os.Getenv("JWT_SECRET")
	if jwtSecret == "" {
		log.Fatal("FATAL: JWT_SECRET environment variable is not set. Security risk detected.")
	}

	// Validate JWT secret strength
	sm := GetGlobalSecretsManager()
	if err := ValidateSecretStrength(jwtSecret); err != nil {
		log.Printf("⚠️  WARNING: %v", err)
		log.Println("⚠️  For production, please use a strong random secret.")
		PrintSecretGenerationInstructions()
	}

	// Use secrets manager to get validated secret
	validatedSecret := sm.GetJWTSecret()
	csrfSecret := strings.TrimSpace(os.Getenv("CSRF_SECRET"))
	if csrfSecret == "" {
		csrfSecret = validatedSecret
	}
	environment := getEnv("ENV", "production")

	corsRaw, corsConfigured := os.LookupEnv("CORS_ALLOW_ORIGINS")
	if !corsConfigured {
		if environment == "production" {
			log.Fatal("FATAL: CORS_ALLOW_ORIGINS must be configured in production.")
		}
		corsRaw = "http://localhost:3000"
	}

	allowedOrigins := parseCSV(corsRaw)
	if environment == "production" && len(allowedOrigins) == 0 {
		log.Fatal("FATAL: CORS_ALLOW_ORIGINS cannot be empty in production.")
	}
	if environment == "production" {
		for _, origin := range allowedOrigins {
			if origin == "*" {
				log.Fatal("FATAL: wildcard CORS origin is not allowed in production.")
			}
		}
	}

	trustProxy := getEnvBool("TRUST_PROXY", false)
	proxyHeader := strings.TrimSpace(getEnv("PROXY_HEADER", "X-Forwarded-For"))
	trustProxyProxies := parseCSV(getEnv("TRUST_PROXY_PROXIES", ""))
	trustProxyLoopback := getEnvBool("TRUST_PROXY_LOOPBACK", false)
	trustProxyLinkLocal := getEnvBool("TRUST_PROXY_LINK_LOCAL", false)
	trustProxyPrivate := getEnvBool("TRUST_PROXY_PRIVATE", false)
	trustProxyUnixSocket := getEnvBool("TRUST_PROXY_UNIX_SOCKET", false)
	enableIPValidation := getEnvBool("ENABLE_IP_VALIDATION", false)

	return &Config{
		DBType:      dbType,
		DBDSN:       dbDSN,
		JWTSecret:   validatedSecret,
		CSRFSecret:  csrfSecret,
		AppPort:     getEnv("PORT", "8080"),
		Environment: environment,

		AutoKillPortOnStartup: getEnvBool("AUTO_KILL_PORT_ON_STARTUP", false),
		AllowedOrigins:        allowedOrigins,
		TrustProxy:            trustProxy,
		ProxyHeader:           proxyHeader,
		TrustProxyProxies:     trustProxyProxies,
		TrustProxyLoopback:    trustProxyLoopback,
		TrustProxyLinkLocal:   trustProxyLinkLocal,
		TrustProxyPrivate:     trustProxyPrivate,
		TrustProxyUnixSocket:  trustProxyUnixSocket,
		EnableIPValidation:    enableIPValidation,
		TelegramToken:         os.Getenv("TELEGRAM_TOKEN"),
		TelegramChatID:        os.Getenv("TELEGRAM_CHAT_ID"),
		SuperAdminPassword:    os.Getenv("SUPERADMIN_PASSWORD"),
	}
}

func getEnv(key, fallback string) string {
	if value, ok := os.LookupEnv(key); ok {
		return value
	}
	return fallback
}

func getEnvBool(key string, fallback bool) bool {
	raw := strings.TrimSpace(os.Getenv(key))
	if raw == "" {
		return fallback
	}

	parsed, err := strconv.ParseBool(raw)
	if err != nil {
		return fallback
	}

	return parsed
}

func parseCSV(raw string) []string {
	parts := strings.Split(raw, ",")
	out := make([]string, 0, len(parts))

	for _, p := range parts {
		trimmed := strings.TrimSpace(p)
		if trimmed == "" {
			continue
		}
		out = append(out, trimmed)
	}

	return out
}
