//go:build legacytests
// +build legacytests

package unit

import (
	"os"
	"path/filepath"
	"testing"

	. "github.com/smartystreets/goconvey/convey"
	"quyun/v2/app/config"
)

// TestConfigLoading 测试配置加载功能
func TestConfigLoading(t *testing.T) {
	Convey("配置加载测试", t, func() {
		var testConfig *config.Config
		var configPath string
		var testDir string

		Convey("当准备测试配置文件时", func() {
			originalWd, _ := os.Getwd()
			testDir = filepath.Join(originalWd, "..", "..", "fixtures", "test_config")

			Convey("应该创建测试配置目录", func() {
				err := os.MkdirAll(testDir, 0o755)
				So(err, ShouldBeNil)
			})

			Convey("应该创建测试配置文件", func() {
				testConfigContent := `App:
  Mode: "test"
  BaseURI: "http://localhost:8080"
Http:
  Port: 8080
Database:
  Host: "localhost"
  Port: 5432
  Database: "test_db"
  Username: "test_user"
  Password: "test_password"
  SslMode: "disable"
Log:
  Level: "debug"
  Format: "text"
  EnableCaller: true`

				configPath = filepath.Join(testDir, "config.toml")
				err := os.WriteFile(configPath, []byte(testConfigContent), 0o644)
				So(err, ShouldBeNil)
			})

			Convey("应该成功加载配置", func() {
				var err error
				testConfig, err = config.Load(configPath)
				So(err, ShouldBeNil)
				So(testConfig, ShouldNotBeNil)
			})
		})

		Convey("验证配置内容", func() {
			So(testConfig, ShouldNotBeNil)

			Convey("应用配置应该正确", func() {
				So(testConfig.App.Mode, ShouldEqual, "test")
				So(testConfig.App.BaseURI, ShouldEqual, "http://localhost:8080")
			})

			Convey("HTTP配置应该正确", func() {
				So(testConfig.Http.Port, ShouldEqual, 8080)
			})

			Convey("数据库配置应该正确", func() {
				So(testConfig.Database.Host, ShouldEqual, "localhost")
				So(testConfig.Database.Port, ShouldEqual, 5432)
				So(testConfig.Database.Database, ShouldEqual, "test_db")
				So(testConfig.Database.Username, ShouldEqual, "test_user")
				So(testConfig.Database.Password, ShouldEqual, "test_password")
				So(testConfig.Database.SslMode, ShouldEqual, "disable")
			})

			Convey("日志配置应该正确", func() {
				So(testConfig.Log.Level, ShouldEqual, "debug")
				So(testConfig.Log.Format, ShouldEqual, "text")
				So(testConfig.Log.EnableCaller, ShouldBeTrue)
			})
		})

		Reset(func() {
			// 清理测试文件
			if testDir != "" {
				os.RemoveAll(testDir)
			}
		})
	})
}

// TestConfigFromEnvironment 测试从环境变量加载配置
func TestConfigFromEnvironment(t *testing.T) {
	Convey("环境变量配置测试", t, func() {
		var originalEnvVars map[string]string

		Convey("当设置环境变量时", func() {
			// 保存原始环境变量
			originalEnvVars = map[string]string{
				"APP_MODE":  os.Getenv("APP_MODE"),
				"HTTP_PORT": os.Getenv("HTTP_PORT"),
				"DB_HOST":   os.Getenv("DB_HOST"),
			}

			// 设置测试环境变量
			os.Setenv("APP_MODE", "test")
			os.Setenv("HTTP_PORT", "9090")
			os.Setenv("DB_HOST", "test-host")

			Convey("环境变量应该被正确设置", func() {
				So(os.Getenv("APP_MODE"), ShouldEqual, "test")
				So(os.Getenv("HTTP_PORT"), ShouldEqual, "9090")
				So(os.Getenv("DB_HOST"), ShouldEqual, "test-host")
			})
		})

		Convey("当从环境变量加载配置时", func() {
			originalWd, _ := os.Getwd()
			testDir := filepath.Join(originalWd, "..", "..", "fixtures", "test_config_env")

			Convey("应该创建测试配置目录", func() {
				err := os.MkdirAll(testDir, 0o755)
				So(err, ShouldBeNil)
			})

			Convey("应该创建基础配置文件", func() {
				testConfigContent := `App:
  Mode: "development"
  BaseURI: "http://localhost:3000"
Http:
  Port: 3000
Database:
  Host: "localhost"
  Port: 5432
  Database: "default_db"
  Username: "default_user"
  Password: "default_password"
  SslMode: "disable"`

				configPath := filepath.Join(testDir, "config.toml")
				err := os.WriteFile(configPath, []byte(testConfigContent), 0o644)
				So(err, ShouldBeNil)
			})

			Convey("应该成功加载并合并配置", func() {
				configPath := filepath.Join(testDir, "config.toml")
				loadedConfig, err := config.Load(configPath)

				So(err, ShouldBeNil)
				So(loadedConfig, ShouldNotBeNil)

				Convey("环境变量应该覆盖配置文件", func() {
					So(loadedConfig.App.Mode, ShouldEqual, "test")
					So(loadedConfig.Http.Port, ShouldEqual, 9090)
					So(loadedConfig.Database.Host, ShouldEqual, "test-host")
				})

				Convey("配置文件的默认值应该保留", func() {
					So(loadedConfig.App.BaseURI, ShouldEqual, "http://localhost:3000")
					So(loadedConfig.Database.Database, ShouldEqual, "default_db")
				})
			})

			Reset(func() {
				// 清理测试目录
				os.RemoveAll(testDir)
			})
		})

		Reset(func() {
			// 恢复原始环境变量
			if originalEnvVars != nil {
				for key, value := range originalEnvVars {
					if value == "" {
						os.Unsetenv(key)
					} else {
						os.Setenv(key, value)
					}
				}
			}
		})
	})
}

// TestConfigValidation 测试配置验证
func TestConfigValidation(t *testing.T) {
	Convey("配置验证测试", t, func() {
		Convey("当配置为空时", func() {
			config := &config.Config{}

			Convey("应该检测到缺失的必需配置", func() {
				So(config.App.Mode, ShouldBeEmpty)
				So(config.Http.Port, ShouldEqual, 0)
				So(config.Database.Host, ShouldBeEmpty)
			})
		})

		Convey("当配置端口无效时", func() {
			config := &config.Config{
				Http: config.HttpConfig{
					Port: -1,
				},
			}

			Convey("应该检测到无效端口", func() {
				So(config.Http.Port, ShouldBeLessThan, 0)
			})
		})

		Convey("当配置模式有效时", func() {
			validModes := []string{"development", "production", "testing"}

			for _, mode := range validModes {
				config := &config.Config{
					App: config.AppConfig{
						Mode: mode,
					},
				}

				Convey("模式 "+mode+" 应该是有效的", func() {
					So(config.App.Mode, ShouldBeIn, validModes)
				})
			}
		})
	})
}

// TestConfigDefaults 测试配置默认值
func TestConfigDefaults(t *testing.T) {
	Convey("配置默认值测试", t, func() {
		Convey("当创建新配置时", func() {
			config := &config.Config{}

			Convey("应该有合理的默认值", func() {
				// 测试应用的默认值
				So(config.App.Mode, ShouldEqual, "development")

				// 测试HTTP的默认值
				So(config.Http.Port, ShouldEqual, 8080)

				// 测试数据库的默认值
				So(config.Database.Port, ShouldEqual, 5432)
				So(config.Database.SslMode, ShouldEqual, "disable")

				// 测试日志的默认值
				So(config.Log.Level, ShouldEqual, "info")
				So(config.Log.Format, ShouldEqual, "json")
			})
		})
	})
}

// TestConfigHelpers 测试配置辅助函数
func TestConfigHelpers(t *testing.T) {
	Convey("配置辅助函数测试", t, func() {
		Convey("当使用配置辅助函数时", func() {
			config := &config.Config{
				App: config.AppConfig{
					Mode:    "production",
					BaseURI: "https://api.example.com",
				},
				Http: config.HttpConfig{
					Port: 443,
				},
			}

			Convey("应该能够获取应用环境", func() {
				env := config.App.Mode
				So(env, ShouldEqual, "production")
			})

			Convey("应该能够构建完整URL", func() {
				fullURL := config.App.BaseURI + "/api/v1/users"
				So(fullURL, ShouldEqual, "https://api.example.com/api/v1/users")
			})

			Convey("应该能够判断HTTPS", func() {
				isHTTPS := config.Http.Port == 443
				So(isHTTPS, ShouldBeTrue)
			})
		})
	})
}
