package config

import (
	"testing"
	"time"

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

func TestO11yExchangeSecretSourceValidation(t *testing.T) {
	t.Parallel()
	conf := validProxyConfig()
	conf.Services.SecretStore.Runtimes["github-pat"] = RuntimeConfig{
		Source: SecretSourceConfig{
			Type: SecretSourceAWSSecretsManager,
			AWSSecretsManager: &AWSSecretsManagerSecretSourceConfig{
				Region: "us-west-2", SecretID: "example/github", Format: SecretFormatJSON,
			},
		},
		Refresh: SecretRefreshConfig{Interval: 5 * time.Minute, MaxStaleness: time.Hour},
	}
	conf.Services.SecretStore.Runtimes["o11y-session"] = RuntimeConfig{
		Source: SecretSourceConfig{
			Type: SecretSourceO11yExchange,
			O11yExchange: &O11yExchangeSecretSourceConfig{
				Environment:   O11yEnvironmentProd,
				Bootstrap:     SecretReferenceConfig{Secret: "github-pat", Field: "token"},
				CloudProvider: O11yCloudProviderAWS,
			},
		},
		Refresh: SecretRefreshConfig{RefreshBeforeExpiry: time.Hour},
	}
	conf.Normalize()

	require.NoError(t, conf.Validate())
}

func TestO11yExchangeSecretSourceDefaults(t *testing.T) {
	t.Parallel()
	conf := validO11yConfig()
	source := conf.Services.SecretStore.Runtimes["o11y-session"].Source.O11yExchange

	require.Equal(t, "https://www.ds.us-west-2.aws.observability.tidbcloud.com/client/auth", source.Endpoint)
	require.Equal(t, 12*time.Hour, source.TokenTTL)
	require.Equal(t, 10*time.Second, source.RequestTimeout)
}

func TestSecretSourceBootstrapReferenceValidation(t *testing.T) {
	t.Parallel()
	tests := []struct {
		name      string
		mutate    func(*RootConfig)
		wantError string
	}{
		{
			name: "unknown bootstrap secret",
			mutate: func(conf *RootConfig) {
				secret := conf.Services.SecretStore.Runtimes["o11y-session"]
				secret.Source.O11yExchange.Bootstrap.Secret = "missing"
				conf.Services.SecretStore.Runtimes["o11y-session"] = secret
			},
			wantError: "unknown bootstrap secret",
		},
		{
			name: "bootstrap reference cycle",
			mutate: func(conf *RootConfig) {
				secret := conf.Services.SecretStore.Runtimes["github-pat"]
				secret.Source = SecretSourceConfig{
					Type: SecretSourceO11yExchange,
					O11yExchange: &O11yExchangeSecretSourceConfig{
						Environment:   O11yEnvironmentProd,
						Bootstrap:     SecretReferenceConfig{Secret: "o11y-session", Field: "auth0Token"},
						CloudProvider: O11yCloudProviderAWS,
					},
				}
				secret.Refresh = SecretRefreshConfig{RefreshBeforeExpiry: time.Hour}
				conf.Services.SecretStore.Runtimes["github-pat"] = secret
			},
			wantError: "contains a cycle",
		},
		{
			name: "unsupported environment",
			mutate: func(conf *RootConfig) {
				secret := conf.Services.SecretStore.Runtimes["o11y-session"]
				secret.Source.O11yExchange.Environment = "staging"
				conf.Services.SecretStore.Runtimes["o11y-session"] = secret
			},
			wantError: "unsupported o11y environment",
		},
		{
			name: "refresh buffer reaches token ttl",
			mutate: func(conf *RootConfig) {
				secret := conf.Services.SecretStore.Runtimes["o11y-session"]
				secret.Refresh.RefreshBeforeExpiry = 12 * time.Hour
				conf.Services.SecretStore.Runtimes["o11y-session"] = secret
			},
			wantError: "shorter than the o11y token TTL",
		},
		{
			name: "refresh buffer reaches configured token ttl",
			mutate: func(conf *RootConfig) {
				secret := conf.Services.SecretStore.Runtimes["o11y-session"]
				secret.Source.O11yExchange.TokenTTL = 30 * time.Minute
				secret.Refresh.RefreshBeforeExpiry = 30 * time.Minute
				conf.Services.SecretStore.Runtimes["o11y-session"] = secret
			},
			wantError: "shorter than the o11y token TTL",
		},
	}
	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			t.Parallel()
			conf := validO11yConfig()
			test.mutate(&conf)
			conf.Normalize()
			require.ErrorContains(t, conf.Validate(), test.wantError)
		})
	}
}

func validO11yConfig() RootConfig {
	conf := validProxyConfig()
	conf.Services.SecretStore.Runtimes["github-pat"] = RuntimeConfig{
		Source: SecretSourceConfig{
			Type: SecretSourceAWSSecretsManager,
			AWSSecretsManager: &AWSSecretsManagerSecretSourceConfig{
				Region: "us-west-2", SecretID: "example/github", Format: SecretFormatJSON,
			},
		},
		Refresh: SecretRefreshConfig{Interval: 5 * time.Minute, MaxStaleness: time.Hour},
	}
	conf.Services.SecretStore.Runtimes["o11y-session"] = RuntimeConfig{
		Source: SecretSourceConfig{
			Type: SecretSourceO11yExchange,
			O11yExchange: &O11yExchangeSecretSourceConfig{
				Environment:   O11yEnvironmentProd,
				Bootstrap:     SecretReferenceConfig{Secret: "github-pat", Field: "token"},
				CloudProvider: O11yCloudProviderAWS,
			},
		},
		Refresh: SecretRefreshConfig{RefreshBeforeExpiry: time.Hour},
	}
	conf.Normalize()
	return conf
}
