package config

import (
	"os"
	"testing"
	"time"
)

func TestLoad_EmbeddedConfig(t *testing.T) {
	clearEnvVars(t)
	setRequiredEnvVars(t)
	defer clearEnvVars(t)

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load() 失败: %v", err)
	}

	if cfg.Server.Address != ":3000" {
		t.Errorf("server.address 期望 :3000, 实际 %s", cfg.Server.Address)
	}
	if cfg.Server.ReadTimeout != 30*time.Second {
		t.Errorf("server.read_timeout 期望 30s, 实际 %v", cfg.Server.ReadTimeout)
	}
	if cfg.Logging.Level != "info" {
		t.Errorf("logging.level 期望 info, 实际 %s", cfg.Logging.Level)
	}
}

func TestLoad_EnvOverride(t *testing.T) {
	clearEnvVars(t)
	setRequiredEnvVars(t)
	defer clearEnvVars(t)

	os.Setenv("JUNHONG_SERVER_ADDRESS", ":8080")
	os.Setenv("JUNHONG_LOGGING_LEVEL", "debug")
	defer func() {
		os.Unsetenv("JUNHONG_SERVER_ADDRESS")
		os.Unsetenv("JUNHONG_LOGGING_LEVEL")
	}()

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load() 失败: %v", err)
	}

	if cfg.Server.Address != ":8080" {
		t.Errorf("server.address 期望 :8080, 实际 %s", cfg.Server.Address)
	}
	if cfg.Logging.Level != "debug" {
		t.Errorf("logging.level 期望 debug, 实际 %s", cfg.Logging.Level)
	}
}

func TestLoad_MissingRequired(t *testing.T) {
	clearEnvVars(t)
	defer clearEnvVars(t)

	_, err := Load()
	if err == nil {
		t.Fatal("Load() 缺少必填配置时应返回错误")
	}

	expectedFields := []string{"database.host", "database.user", "database.password", "database.dbname", "redis.address", "jwt.secret_key"}
	for _, field := range expectedFields {
		if !containsString(err.Error(), field) {
			t.Errorf("错误信息应包含 %q, 实际: %s", field, err.Error())
		}
	}
}

func TestLoad_PartialRequired(t *testing.T) {
	clearEnvVars(t)
	defer clearEnvVars(t)

	os.Setenv("JUNHONG_DATABASE_HOST", "localhost")
	os.Setenv("JUNHONG_DATABASE_USER", "user")

	_, err := Load()
	if err == nil {
		t.Fatal("Load() 部分必填配置缺失时应返回错误")
	}

	if containsString(err.Error(), "database.host") {
		t.Error("database.host 已设置，不应在错误信息中")
	}
	if containsString(err.Error(), "database.user") {
		t.Error("database.user 已设置，不应在错误信息中")
	}
	if !containsString(err.Error(), "database.password") {
		t.Error("database.password 未设置，应在错误信息中")
	}
}

func TestLoad_GlobalConfig(t *testing.T) {
	clearEnvVars(t)
	setRequiredEnvVars(t)
	defer clearEnvVars(t)

	cfg, err := Load()
	if err != nil {
		t.Fatalf("Load() 失败: %v", err)
	}

	globalCfg := Get()
	if globalCfg == nil {
		t.Fatal("Get() 返回 nil")
	}

	if globalCfg.Server.Address != cfg.Server.Address {
		t.Errorf("全局配置与返回配置不一致")
	}
}

func TestValidateRequired(t *testing.T) {
	tests := []struct {
		name    string
		cfg     *Config
		wantErr bool
	}{
		{
			name: "all required set",
			cfg: &Config{
				Database: DatabaseConfig{
					Host:     "localhost",
					User:     "user",
					Password: "pass",
					DBName:   "db",
				},
				Redis: RedisConfig{Address: "localhost"},
				JWT:   JWTConfig{SecretKey: "12345678901234567890123456789012"},
			},
			wantErr: false,
		},
		{
			name: "missing database host",
			cfg: &Config{
				Database: DatabaseConfig{
					User:     "user",
					Password: "pass",
					DBName:   "db",
				},
				Redis: RedisConfig{Address: "localhost"},
				JWT:   JWTConfig{SecretKey: "12345678901234567890123456789012"},
			},
			wantErr: true,
		},
		{
			name: "missing redis address",
			cfg: &Config{
				Database: DatabaseConfig{
					Host:     "localhost",
					User:     "user",
					Password: "pass",
					DBName:   "db",
				},
				Redis: RedisConfig{},
				JWT:   JWTConfig{SecretKey: "12345678901234567890123456789012"},
			},
			wantErr: true,
		},
		{
			name: "missing jwt secret",
			cfg: &Config{
				Database: DatabaseConfig{
					Host:     "localhost",
					User:     "user",
					Password: "pass",
					DBName:   "db",
				},
				Redis: RedisConfig{Address: "localhost"},
				JWT:   JWTConfig{},
			},
			wantErr: true,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := tt.cfg.ValidateRequired()
			if (err != nil) != tt.wantErr {
				t.Errorf("ValidateRequired() error = %v, wantErr %v", err, tt.wantErr)
			}
		})
	}
}

func setRequiredEnvVars(t *testing.T) {
	t.Helper()
	os.Setenv("JUNHONG_DATABASE_HOST", "localhost")
	os.Setenv("JUNHONG_DATABASE_USER", "testuser")
	os.Setenv("JUNHONG_DATABASE_PASSWORD", "testpass")
	os.Setenv("JUNHONG_DATABASE_DBNAME", "testdb")
	os.Setenv("JUNHONG_REDIS_ADDRESS", "localhost")
	os.Setenv("JUNHONG_JWT_SECRET_KEY", "12345678901234567890123456789012")
}

func clearEnvVars(t *testing.T) {
	t.Helper()
	envVars := []string{
		"JUNHONG_DATABASE_HOST",
		"JUNHONG_DATABASE_PORT",
		"JUNHONG_DATABASE_USER",
		"JUNHONG_DATABASE_PASSWORD",
		"JUNHONG_DATABASE_DBNAME",
		"JUNHONG_REDIS_ADDRESS",
		"JUNHONG_REDIS_PORT",
		"JUNHONG_REDIS_PASSWORD",
		"JUNHONG_JWT_SECRET_KEY",
		"JUNHONG_SERVER_ADDRESS",
		"JUNHONG_LOGGING_LEVEL",
	}
	for _, v := range envVars {
		os.Unsetenv(v)
	}
}

func containsString(s, substr string) bool {
	return len(s) >= len(substr) && (s == substr || len(s) > 0 && (s[:len(substr)] == substr || containsString(s[1:], substr)))
}
