package bootstrap

import (
	"encoding/json"
	"fmt"
	"os"
	"path/filepath"
	"sort"
	"strconv"
	"strings"
)

// BootstrapConfig 预注入配置
type BootstrapConfig struct {
	Enabled    bool           `json:"enabled"`
	Users      []UserSeed     `json:"users"`
	Registries []RegistrySeed `json:"registries"`
	Clusters   []ClusterSeed  `json:"clusters"`
}

// UserSeed 用户预注入数据
type UserSeed struct {
	Username string `json:"username"`
	Password string `json:"password"`
	Email    string `json:"email"`
	Role     string `json:"role"`
}

// RegistrySeed Registry 预注入数据
type RegistrySeed struct {
	Name        string `json:"name"`
	URL         string `json:"url"`
	Description string `json:"description"`
	Username    string `json:"username"`
	Password    string `json:"password"`
	Insecure    bool   `json:"insecure"`
}

// ClusterSeed Cluster 预注入数据
type ClusterSeed struct {
	Name        string `json:"name"`
	Host        string `json:"host"`
	Description string `json:"description"`
	CAData      string `json:"ca_data"`
	CertData    string `json:"cert_data"`
	KeyData     string `json:"key_data"`
	Token       string `json:"token,omitempty"`
}

// LoadBootstrapConfig 加载预注入配置
// 支持从文件或环境变量加载
//
// 加载优先级：
// 1. 环境变量 BOOTSTRAP_CONFIG_JSON (最高优先级)
// 2. 环境变量 BOOTSTRAP_* (root .env / container env)
// 3. Mock 模式: 配置文件 config/bootstrap.json
// 4. 未提供任何 bootstrap 配置时禁用预注入
func LoadBootstrapConfig() (*BootstrapConfig, error) {
	// 1. 优先从环境变量加载
	if configJSON := os.Getenv("BOOTSTRAP_CONFIG_JSON"); configJSON != "" {
		var config BootstrapConfig
		if err := json.Unmarshal([]byte(configJSON), &config); err != nil {
			return nil, fmt.Errorf("failed to parse BOOTSTRAP_CONFIG_JSON: %w", err)
		}
		return &config, nil
	}

	if config, ok := loadBootstrapConfigFromEnv(); ok {
		return config, nil
	}

	// 2. 检查适配器模式
	adapterMode := os.Getenv("ADAPTER_MODE")

	// Mock 模式: 使用配置文件（假数据）
	if adapterMode == "mock" {
		configPath := os.Getenv("BOOTSTRAP_CONFIG_FILE")
		if configPath == "" {
			configPath = filepath.Join("config", "bootstrap.json")
		}

		// 检查文件是否存在
		if _, err := os.Stat(configPath); os.IsNotExist(err) {
			// 配置文件不存在，不预注入任何数据
			return GetDefaultBootstrapConfig(), nil
		}

		data, err := os.ReadFile(configPath)
		if err != nil {
			return nil, fmt.Errorf("failed to read bootstrap config file %s: %w", configPath, err)
		}

		var config BootstrapConfig
		if err := json.Unmarshal(data, &config); err != nil {
			return nil, fmt.Errorf("failed to parse bootstrap config: %w", err)
		}

		return &config, nil
	}

	// 3. 真实模式: 未显式配置时不预注入任何数据
	return GetDefaultBootstrapConfig(), nil
}

func loadBootstrapConfigFromEnv() (*BootstrapConfig, bool) {
	if !hasBootstrapEnv() {
		return nil, false
	}

	config := &BootstrapConfig{
		Enabled:    true,
		Users:      make([]UserSeed, 0, 1),
		Registries: make([]RegistrySeed, 0, 1),
		Clusters:   make([]ClusterSeed, 0),
	}

	adminUser := strings.TrimSpace(os.Getenv("BOOTSTRAP_ADMIN_USER"))
	adminPass := strings.TrimSpace(os.Getenv("BOOTSTRAP_ADMIN_PASS"))
	if adminUser != "" && adminPass != "" {
		config.Users = append(config.Users, UserSeed{
			Username: adminUser,
			Password: adminPass,
			Email:    getEnv("BOOTSTRAP_ADMIN_EMAIL", adminUser+"@example.local"),
			Role:     "admin",
		})
	}

	if registryURL := os.Getenv("BOOTSTRAP_REGISTRY_URL"); registryURL != "" {
		registryUser := getEnv("BOOTSTRAP_REGISTRY_ROBOT_USER", getEnv("BOOTSTRAP_REGISTRY_USER", ""))
		registryPass := getEnv("BOOTSTRAP_REGISTRY_ROBOT_PASS", getEnv("BOOTSTRAP_REGISTRY_PASS", ""))
		config.Registries = append(config.Registries, RegistrySeed{
			Name:        getEnv("BOOTSTRAP_REGISTRY_NAME", "harbor"),
			URL:         registryURL,
			Description: getEnv("BOOTSTRAP_REGISTRY_DESC", ""),
			Username:    registryUser,
			Password:    registryPass,
			Insecure:    parseBoolEnv("BOOTSTRAP_REGISTRY_INSECURE", false),
		})
	}

	enableClusters := parseBoolEnv("BOOTSTRAP_ENABLE_CLUSTERS", false) ||
		os.Getenv("BOOTSTRAP_CLUSTERS") != ""
	if enableClusters {
		for _, clusterName := range discoverBootstrapClusters() {
			prefix := "BOOTSTRAP_CLUSTER_" + normalizeEnvName(clusterName) + "_"
			host := os.Getenv(prefix + "HOST")
			if host == "" {
				continue
			}

			config.Clusters = append(config.Clusters, ClusterSeed{
				Name:        strings.ToLower(clusterName),
				Host:        host,
				Description: os.Getenv(prefix + "DESC"),
				CAData:      os.Getenv(prefix + "CA"),
				CertData:    os.Getenv(prefix + "CERT"),
				KeyData:     os.Getenv(prefix + "KEY"),
				Token:       os.Getenv(prefix + "TOKEN"),
			})
		}
	}

	return config, true
}

func hasBootstrapEnv() bool {
	for _, env := range os.Environ() {
		if strings.HasPrefix(env, "BOOTSTRAP_") {
			return true
		}
	}
	return false
}

func discoverBootstrapClusters() []string {
	names := make(map[string]struct{})

	if configured := os.Getenv("BOOTSTRAP_CLUSTERS"); configured != "" {
		for _, name := range strings.Split(configured, ",") {
			name = strings.TrimSpace(name)
			if name != "" {
				names[normalizeEnvName(name)] = struct{}{}
			}
		}
	}

	for _, env := range os.Environ() {
		key, _, ok := strings.Cut(env, "=")
		if !ok || !strings.HasPrefix(key, "BOOTSTRAP_CLUSTER_") || !strings.HasSuffix(key, "_HOST") {
			continue
		}
		name := strings.TrimSuffix(strings.TrimPrefix(key, "BOOTSTRAP_CLUSTER_"), "_HOST")
		if name != "" {
			names[name] = struct{}{}
		}
	}

	result := make([]string, 0, len(names))
	for name := range names {
		result = append(result, name)
	}
	sort.Strings(result)
	return result
}

func normalizeEnvName(name string) string {
	replacer := strings.NewReplacer("-", "_", ".", "_", " ", "_")
	return strings.ToUpper(replacer.Replace(strings.TrimSpace(name)))
}

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

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

// GetDefaultBootstrapConfig 返回安全的空默认配置。
//
// 这里不能包含真实或示例账号密码、Registry 或集群凭据。预注入数据必须来自
// BOOTSTRAP_CONFIG_JSON、BOOTSTRAP_* 环境变量，或显式提供的 bootstrap 配置文件。
func GetDefaultBootstrapConfig() *BootstrapConfig {
	return &BootstrapConfig{
		Enabled:    false,
		Users:      []UserSeed{},
		Registries: []RegistrySeed{},
		Clusters:   []ClusterSeed{},
	}
}
