package config

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"

	"github.com/spf13/viper"
)

func Load(path string) (*Config, error) {
	v := viper.New()

	// Try to find config file - support multiple paths
	configPath := resolveConfigPath(path)
	if configPath == "" {
		return nil, fmt.Errorf("config file not found at: %s (and no alternative paths worked)", path)
	}

	v.SetConfigFile(configPath)
	v.SetConfigType("yaml")
	v.SetEnvPrefix("SECURITY_CENTER")
	v.SetEnvKeyReplacer(strings.NewReplacer(".", "_"))
	v.AutomaticEnv()

	setDefaults(v)

	if err := v.ReadInConfig(); err != nil {
		return nil, fmt.Errorf("read config: %w", err)
	}

	applyEnvOverrides(v)

	var cfg Config
	if err := v.Unmarshal(&cfg); err != nil {
		return nil, fmt.Errorf("decode config: %w", err)
	}

	return &cfg, nil
}

// resolveConfigPath tries to find the config file in multiple locations
func resolveConfigPath(defaultPath string) string {
	// Check if environment variable is set
	if envPath := os.Getenv("SECURITY_CENTER_CONFIG_PATH"); envPath != "" {
		if _, err := os.Stat(envPath); err == nil {
			return envPath
		}
	}

	// Try the provided path
	if _, err := os.Stat(defaultPath); err == nil {
		return defaultPath
	}

	// Try relative to current working directory
	cwd, err := os.Getwd()
	if err == nil {
		paths := []string{
			filepath.Join(cwd, "configs/config.yaml"),
			filepath.Join(cwd, "config.yaml"),
		}
		for _, p := range paths {
			if _, err := os.Stat(p); err == nil {
				return p
			}
		}
	}

	// Try relative to executable directory
	exePath, err := os.Executable()
	if err == nil {
		exeDir := filepath.Dir(exePath)
		paths := []string{
			filepath.Join(exeDir, "configs/config.yaml"),
			filepath.Join(exeDir, "config.yaml"),
			filepath.Join(filepath.Dir(exeDir), "configs/config.yaml"),
		}
		for _, p := range paths {
			if _, err := os.Stat(p); err == nil {
				return p
			}
		}
	}

	return ""
}

func applyEnvOverrides(v *viper.Viper) {
	setIfEnv := func(key string, envs ...string) {
		for _, env := range envs {
			val, ok := os.LookupEnv(env)
			if !ok {
				continue
			}
			val = strings.TrimSpace(val)
			if val == "" {
				continue
			}
			v.Set(key, val)
			return
		}
	}

	setCSVIfEnv := func(key string, envs ...string) {
		for _, env := range envs {
			val, ok := os.LookupEnv(env)
			if !ok {
				continue
			}

			parts := strings.Split(val, ",")
			items := make([]string, 0, len(parts))
			for _, part := range parts {
				part = strings.TrimSpace(part)
				if part == "" {
					continue
				}
				items = append(items, part)
			}

			if len(items) == 0 {
				continue
			}

			v.Set(key, items)
			return
		}
	}

	setCSVIfEnv("http.allowed_origins", "SECURITY_CENTER_HTTP_ALLOWED_ORIGINS", "SC_ALLOWED_ORIGINS")

	setIfEnv("storage.provider", "SECURITY_CENTER_STORAGE_PROVIDER")
	setIfEnv("storage.s3.enabled", "SECURITY_CENTER_STORAGE_S3_ENABLED", "SC_S3_ENABLED")
	setIfEnv("storage.s3.bucket", "SECURITY_CENTER_STORAGE_S3_BUCKET", "SC_S3_BUCKET")
	setIfEnv("storage.s3.region", "SECURITY_CENTER_STORAGE_S3_REGION", "SC_S3_REGION")
	setIfEnv("storage.s3.access_key_id", "SECURITY_CENTER_STORAGE_S3_ACCESS_KEY_ID")
	setIfEnv("storage.s3.secret_access_key", "SECURITY_CENTER_STORAGE_S3_SECRET_ACCESS_KEY")
	setIfEnv("storage.s3.endpoint", "SECURITY_CENTER_STORAGE_S3_ENDPOINT")
	setIfEnv("storage.s3.public_endpoint", "SECURITY_CENTER_STORAGE_S3_PUBLIC_ENDPOINT")
	setIfEnv("storage.s3.use_path_style", "SECURITY_CENTER_STORAGE_S3_USE_PATH_STYLE")
	setIfEnv("storage.s3.base_url", "SECURITY_CENTER_STORAGE_S3_BASE_URL", "SC_S3_BASE_URL")
	setIfEnv("storage.s3.upload_prefix", "SECURITY_CENTER_STORAGE_S3_UPLOAD_PREFIX", "SC_S3_UPLOAD_PREFIX")
	setIfEnv("storage.s3.presign_ttl", "SECURITY_CENTER_STORAGE_S3_PRESIGN_TTL")

	setIfEnv("scan.scanner.enabled", "SECURITY_CENTER_SCAN_SCANNER_ENABLED")
	setIfEnv("scan.scanner.base_url", "SECURITY_CENTER_SCAN_SCANNER_BASE_URL")
	setIfEnv("scan.scanner.api_token", "SECURITY_CENTER_SCAN_SCANNER_API_TOKEN")
	setIfEnv("scan.scanner.callback_token", "SECURITY_CENTER_SCAN_SCANNER_CALLBACK_TOKEN")
	setIfEnv("scan.scanner.timeout", "SECURITY_CENTER_SCAN_SCANNER_TIMEOUT")
	setIfEnv("scan.scanner.user_agent", "SECURITY_CENTER_SCAN_SCANNER_USER_AGENT")
	setIfEnv("scan.scanner.max_targets_per_batch", "SECURITY_CENTER_SCAN_SCANNER_MAX_TARGETS_PER_BATCH")
	setIfEnv("scan.scanner.max_campaign_targets", "SECURITY_CENTER_SCAN_SCANNER_MAX_CAMPAIGN_TARGETS")
	setIfEnv("scan.scanner.campaign_submit_concurrency", "SECURITY_CENTER_SCAN_SCANNER_CAMPAIGN_SUBMIT_CONCURRENCY")
	setIfEnv("scan.scanner.campaign_dispatcher_interval", "SECURITY_CENTER_SCAN_SCANNER_CAMPAIGN_DISPATCHER_INTERVAL")
	setIfEnv("scan.scanner.allow_non_public_targets", "SECURITY_CENTER_SCAN_SCANNER_ALLOW_NON_PUBLIC_TARGETS")
}

func setDefaults(v *viper.Viper) {
	v.SetDefault("app.name", "security-center")
	v.SetDefault("app.environment", "development")
	v.SetDefault("http.host", "0.0.0.0")
	v.SetDefault("http.port", 8080)
	v.SetDefault("http.read_timeout", "15s")
	v.SetDefault("http.write_timeout", "15s")
	v.SetDefault("http.shutdown_timeout", "10s")
	v.SetDefault("http.gzip_enabled", true)
	v.SetDefault("http.gzip_level", 5)
	v.SetDefault("http.gzip_min_bytes", 1024)
	v.SetDefault("log.level", "info")
	v.SetDefault("log.format", "json")
	v.SetDefault("auth.bypass_sso", false)
	v.SetDefault("auth.dev_user.id", "dev-user")
	v.SetDefault("auth.dev_user.email", "dev.user@example.com")
	v.SetDefault("auth.dev_user.name", "Development User")
	v.SetDefault("auth.dev_user.roles", []string{"admin"})
	v.SetDefault("database.max_open_conns", 50)
	v.SetDefault("database.max_idle_conns", 10)
	v.SetDefault("database.conn_max_lifetime", "1h")
	v.SetDefault("redis.db", 0)
	v.SetDefault("redis.pool_size", 50)
	v.SetDefault("redis.min_idle_conns", 10)
	v.SetDefault("redis.dial_timeout", "5s")
	v.SetDefault("redis.read_timeout", "2s")
	v.SetDefault("redis.write_timeout", "2s")
	v.SetDefault("jwt.access_token_ttl", "24h")
	v.SetDefault("jwt.refresh_token_ttl", "168h")
	v.SetDefault("jwt.refresh_grace_period", "15m")
	v.SetDefault("jwt.signing_algorithm", "HS256")
	v.SetDefault("oauth.enabled", true)
	v.SetDefault("oauth.provider", "google")
	v.SetDefault("oauth.bypass_provider", false)
	v.SetDefault("storage.provider", "s3")
	v.SetDefault("storage.s3.enabled", false)
	v.SetDefault("storage.s3.use_path_style", false)
	v.SetDefault("storage.s3.upload_prefix", "vuln-uploads/")
	v.SetDefault("storage.s3.presign_ttl", "15m")
	v.SetDefault("scan.scanner.enabled", false)
	v.SetDefault("scan.scanner.timeout", "10s")
	v.SetDefault("scan.scanner.user_agent", "security-center-scan-client")
	v.SetDefault("scan.scanner.max_targets_per_batch", 1000)
	v.SetDefault("scan.scanner.max_campaign_targets", 50000)
	v.SetDefault("scan.scanner.campaign_submit_concurrency", 2)
	v.SetDefault("scan.scanner.campaign_dispatcher_interval", "5s")
	v.SetDefault("audit.retention_days", 90)
}
