package impl

import (
	"testing"

	"github.com/stretchr/testify/assert"
	"github.com/tidbcloud/dataflow-service/app/internal/feature_gate"
	"github.com/tidbcloud/dataflow-service/internal/config"
)

func TestFeatureGateV2_IsFeatureEnabled(t *testing.T) {
	tests := map[string]struct {
		setupConfig func() *config.CentralConfig
		req         *feature_gate.QueryFeatureGateReq
		feature     string
		wantEnabled bool
		description string
	}{
		"feature enabled for all": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"test-feature": {All: true},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "test-feature",
			wantEnabled: true,
			description: "Feature with All=true should be enabled for everyone",
		},
		"feature enabled by provider (eks->aws)": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"aws-only": {EnabledProviders: []string{"aws"}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "aws-only",
			wantEnabled: true,
			description: "InfraProvider 'eks' should be converted to Provider 'aws'",
		},
		"feature is not enabled by provider (gke->gcp)": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"aws-only": {EnabledProviders: []string{"aws"}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "asia-southeast1",
				InfraProvider: "gke",
			},
			feature:     "aws-only",
			wantEnabled: false,
			description: "InfraProvider 'gke' should be converted to Provider 'gcp' and not enabled",
		},
		"feature enabled by region": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"regional": {EnabledRegions: []string{"us-west-2"}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "regional",
			wantEnabled: true,
			description: "Region should be constructed as 'us-west-2'",
		},
		"feature disabled by provider": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"test": {All: true, DisabledProviders: []string{"aws"}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "test",
			wantEnabled: false,
			description: "Should be disabled for AWS even with All=true",
		},
		"feature enabled by tenant": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"tenant-only": {EnabledTenants: []uint64{100, 200}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      100,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "tenant-only",
			wantEnabled: true,
			description: "Should be enabled for specified tenant",
		},
		"feature disabled by tenant": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"test": {All: true, DisabledTenants: []uint64{999}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      999,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "test",
			wantEnabled: false,
			description: "Should be disabled for blacklisted tenant",
		},
		"required provider - matching": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"aws-required": {
								RequiredProviders: []string{"aws"},
								DisabledTenants:   []uint64{1},
							},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "aws-required",
			wantEnabled: true,
			description: "Required provider should enable when matched even if tenant is disabled",
		},
		"required provider - not matching": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"gcp-required": {RequiredProviders: []string{"gcp"}},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "gcp-required",
			wantEnabled: false,
			description: "Required provider should disable when not matched",
		},
		"case sensitive feature name": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"BR-3-Layer": {All: true},
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "br-3-layer",
			wantEnabled: false,
			description: "Feature matching should be case-sensitive",
		},
		"feature not configured": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      1,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			feature:     "non-existent",
			wantEnabled: false,
			description: "Non-configured feature should be disabled",
		},
	}

	for name, tt := range tests {
		t.Run(name, func(t *testing.T) {
			// Setup and restore config
			original := *config.Global()
			*config.Global() = *tt.setupConfig()
			defer func() { *config.Global() = original }()

			fg := NewFeatureGateV2()
			got := fg.IsFeatureEnabled(tt.req, tt.feature)
			assert.Equal(t, tt.wantEnabled, got, tt.description)
		})
	}
}

func TestFeatureGateV2_QueryEnabledFeatures(t *testing.T) {
	tests := map[string]struct {
		setupConfig  func() *config.CentralConfig
		req          *feature_gate.QueryFeatureGateReq
		wantFeatures []string
		description  string
	}{
		"multiple features enabled": {
			setupConfig: func() *config.CentralConfig {
				return &config.CentralConfig{
					ServerConfig: config.ServerConfig{
						FeatureGates: map[string]config.FeatureGate{
							"feature-1": {All: true},
							"feature-2": {EnabledProviders: []string{"aws"}},
							"feature-3": {EnabledTenants: []uint64{100}},
							"feature-4": {DisabledProviders: []string{"aws"}},
							"feature-5": {RequiredProviders: []string{"aws"}, DisabledTenants: []uint64{100}},    // 'required' take priority
							"feature-6": {RequiredRegions: []string{"us-west-2"}, DisabledProjects: []uint64{2}}, // 'required' take priority
							"feature-7": {EnabledTenants: []uint64{100}, DisabledProjects: []uint64{2}},          // 'disabled' take priority
							"feature-8": {EnabledProviders: []string{"aws"}, DisabledClusters: []uint64{3}},      // 'disabled' take priority
							"FEATURE-9": {EnabledProviders: []string{"aws"}},                                     // feature name should be converted to lower case
						},
					},
				}
			},
			req: &feature_gate.QueryFeatureGateReq{
				TenantID:      100,
				ProjectID:     2,
				ClusterID:     3,
				Region:        "us-west-2",
				InfraProvider: "eks",
			},
			wantFeatures: []string{"feature-1", "feature-2", "feature-3", "feature-5", "feature-6", "feature-9"},
			description:  "Should return all enabled features sorted",
		},
	}

	for name, tt := range tests {
		t.Run(name, func(t *testing.T) {
			// Setup and restore config
			original := *config.Global()
			*config.Global() = *tt.setupConfig()
			defer func() { *config.Global() = original }()

			fg := NewFeatureGateV2()
			resp := fg.QueryEnabledFeatures(tt.req)
			assert.Equal(t, tt.wantFeatures, resp.Features, tt.description)
		})
	}
}
