package config

import (
	"os"
	"testing"

	"github.com/stretchr/testify/require"
)

func TestLoadConfigWithFile(t *testing.T) {
	// Create a temporary config file
	configContent := `
server:
  logLevel: "debug"

storage:
  usageDataDir: "/tmp/test-usage-data"

quotas:
  specialLimits:
    test-tenant: 1000000000
`

	tmpFile, err := os.CreateTemp("", "test-config-*.yaml")
	require.NoError(t, err)
	defer os.Remove(tmpFile.Name())

	_, err = tmpFile.WriteString(configContent)
	require.NoError(t, err)
	tmpFile.Close()

	// Load config with file
	err = LoadConfig(tmpFile.Name())
	require.NoError(t, err)

	cfg := Global()

	// Test that file overrides work
	require.Equal(t, "debug", cfg.Server.LogLevel)

	// Test that defaults are still present
	require.Equal(t, ":8080", cfg.Server.HTTPListenAddr)

	// Test storage configuration
	require.Equal(t, "/tmp/test-usage-data", cfg.Storage.UsageDataDir)

	// Test special limits
	expectedLimit := int64(1000000000) // $1000.00 in micro-dollars
	require.Equal(t, expectedLimit, cfg.Quotas.SpecialLimits["test-tenant"])

	// Test that models are still loaded (from defaults)
	require.NotEmpty(t, cfg.Models)
}

func TestConfigForPrint(t *testing.T) {
	// Load default config
	err := LoadConfig("")
	require.NoError(t, err)

	cfg := Global()

	// Set sensitive values
	cfg.EmbeddingProviders.AWSBedrock.APIToken = "secret-bedrock-token"
	cfg.Server.CheckServiceAPIKey = "secret-service-key"
	cfg.Server.CheckManagementAPIKey = "secret-management-key"

	// Get masked config
	maskedCfg := cfg.ForPrint()

	// Verify sensitive values are masked with last 4 characters shown
	require.Equal(t, "******oken", maskedCfg.EmbeddingProviders.AWSBedrock.APIToken)
	require.Equal(t, "******-key", maskedCfg.Server.CheckServiceAPIKey)
	require.Equal(t, "******-key", maskedCfg.Server.CheckManagementAPIKey)

	// Verify other values are not affected
	require.Equal(t, cfg.Server.HTTPListenAddr, maskedCfg.Server.HTTPListenAddr)
	require.Equal(t, cfg.Server.LogLevel, maskedCfg.Server.LogLevel)
}

func TestConfigForPrintWithEmptyKeys(t *testing.T) {
	// Load default config
	err := LoadConfig("")
	require.NoError(t, err)

	cfg := Global()

	// Leave API keys empty
	cfg.EmbeddingProviders.AWSBedrock.APIToken = "secret-bedrock-token"
	cfg.Server.CheckServiceAPIKey = ""
	cfg.Server.CheckManagementAPIKey = ""

	// Get masked config
	maskedCfg := cfg.ForPrint()

	// Verify only non-empty sensitive values are masked
	require.Equal(t, "******oken", maskedCfg.EmbeddingProviders.AWSBedrock.APIToken)
	require.Equal(t, "", maskedCfg.Server.CheckServiceAPIKey)    // Should remain empty
	require.Equal(t, "", maskedCfg.Server.CheckManagementAPIKey) // Should remain empty
}

func TestConfigForPrintWithShortKeys(t *testing.T) {
	// Load default config
	err := LoadConfig("")
	require.NoError(t, err)

	cfg := Global()

	// Set short sensitive values (4 characters or less)
	cfg.EmbeddingProviders.AWSBedrock.APIToken = "abc"
	cfg.Server.CheckServiceAPIKey = "1234"
	cfg.Server.CheckManagementAPIKey = "xyz"

	// Get masked config
	maskedCfg := cfg.ForPrint()

	// Verify short values are completely masked
	require.Equal(t, "******", maskedCfg.EmbeddingProviders.AWSBedrock.APIToken)
	require.Equal(t, "******", maskedCfg.Server.CheckServiceAPIKey)
	require.Equal(t, "******", maskedCfg.Server.CheckManagementAPIKey)
}

func TestMaskSensitiveValue(t *testing.T) {
	tests := []struct {
		name     string
		input    string
		expected string
	}{
		{
			name:     "empty string",
			input:    "",
			expected: "",
		},
		{
			name:     "short value (3 chars)",
			input:    "abc",
			expected: "******",
		},
		{
			name:     "short value (4 chars)",
			input:    "abcd",
			expected: "******",
		},
		{
			name:     "long value (5 chars)",
			input:    "abcde",
			expected: "******bcde",
		},
		{
			name:     "normal API key",
			input:    "secret-api-key-12345",
			expected: "******2345",
		},
		{
			name:     "very long token",
			input:    "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c",
			expected: "******sw5c",
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := maskSensitiveValue(tt.input)
			require.Equal(t, tt.expected, result)
		})
	}
}

func TestEnvironmentVariableOverrides(t *testing.T) {
	// Set environment variables
	os.Setenv("INFERENCE_SERVICE_API_KEY", "env-service-key")
	os.Setenv("INFERENCE_MANAGEMENT_API_KEY", "env-management-key")
	defer func() {
		os.Unsetenv("INFERENCE_SERVICE_API_KEY")
		os.Unsetenv("INFERENCE_MANAGEMENT_API_KEY")
	}()

	// Load config without file
	err := LoadConfig("")
	require.NoError(t, err)

	cfg := Global()

	// Verify environment variables override defaults
	require.Equal(t, "env-service-key", cfg.Server.CheckServiceAPIKey)
	require.Equal(t, "env-management-key", cfg.Server.CheckManagementAPIKey)
}
