package impl_test

import (
	"reflect"
	"testing"

	"github.com/tidbcloud/dataflow-service/app/internal/feature_gate"
	"github.com/tidbcloud/dataflow-service/app/internal/feature_gate/impl"
	"github.com/tidbcloud/dataflow-service/internal/config"
)

//nolint:funlen
func Test_featureGate_IsFeatureEnabled(t *testing.T) {
	const testFeatureA = "test-feature-a"
	const testFeatureB = "test-feature-b"
	const testFeatureC = "test-feature-c"
	const testFeatureD = "test-feature-d"
	config.Global().ServerConfig.FeaturesSwitchers.PublicFeatures = []string{testFeatureA}
	config.Global().ServerConfig.FeaturesSwitchers.EnabledFeatureByDeployment = map[string]config.DeploymentMatcher{
		testFeatureB: {
			Regions:   []string{"us-west-1", "us-west-2"},
			Providers: []string{"eks", "aws"},
		},
	}
	config.Global().ServerConfig.FeaturesSwitchers.FeaturesAllowList = map[string]config.AllowListMatcher{
		testFeatureC: {
			TenantID:  []string{"1", "2"},
			ProjectID: []string{"1", "2"},
			ClusterID: []string{"1", "2"},
		},
		testFeatureD: {
			TenantID:  []string{"3", "4"},
			ProjectID: []string{"3", "4"},
			ClusterID: []string{"3", "4"},
			DeploymentMatcher: &config.DeploymentMatcher{
				Regions:   []string{"us-west-1", "us-west-2"},
				Providers: []string{"eks", "aws"},
			},
		},
	}

	type args struct {
		req     *feature_gate.QueryFeatureGateReq
		feature string
	}
	tests := []struct {
		name string
		args args
		want bool
	}{
		{
			name: "feature-public",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:      1,
					ProjectID:     11,
					ClusterID:     11,
					Region:        "xxx",
					InfraProvider: "xxx",
				},
				feature: testFeatureA,
			},
			want: true,
		},
		{
			name: "feature-allow-deployment",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:      1,
					ProjectID:     11,
					ClusterID:     11,
					Region:        "us-west-1",
					InfraProvider: "eks",
				},
				feature: testFeatureB,
			},
			want: true,
		},
		{
			name: "feature-allow-list",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:  1,
					ProjectID: 1,
					ClusterID: 1,
				},
				feature: testFeatureC,
			},
			want: true,
		},
		{
			name: "feature-allow-list-2",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:      3,
					ProjectID:     3,
					ClusterID:     3,
					Region:        "us-west-1",
					InfraProvider: "eks",
				},
				feature: testFeatureD,
			},
			want: true,
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			f := impl.NewFeatureGate()
			if got := f.IsFeatureEnabled(tt.args.req, tt.args.feature); got != tt.want {
				t.Errorf("IsFeatureEnabled() = %v, want %v", got, tt.want)
			}
		})
	}
}

//nolint:funlen
func Test_featureGate_QueryEnabledFeatures(t *testing.T) {
	const testFeatureA = "test-feature-a"
	const testFeatureB = "test-feature-b"
	const testFeatureC = "test-feature-c"
	const testFeatureD = "test-feature-d"
	config.Global().ServerConfig.FeaturesSwitchers.PublicFeatures = []string{testFeatureA}
	config.Global().ServerConfig.FeaturesSwitchers.EnabledFeatureByDeployment = map[string]config.DeploymentMatcher{
		testFeatureB: {
			Regions:   []string{"us-west-1", "us-west-2"},
			Providers: []string{"eks", "aws"},
		},
	}
	config.Global().ServerConfig.FeaturesSwitchers.FeaturesAllowList = map[string]config.AllowListMatcher{
		testFeatureC: {
			TenantID:  []string{"1", "2"},
			ProjectID: []string{"1", "2"},
			ClusterID: []string{"1", "2"},
		},
		testFeatureD: {
			TenantID:  []string{"3", "4"},
			ProjectID: []string{"3", "4"},
			ClusterID: []string{"3", "4"},
			DeploymentMatcher: &config.DeploymentMatcher{
				Regions:   []string{"us-west-1", "us-west-2"},
				Providers: []string{"eks", "aws"},
			},
		},
	}

	type args struct {
		req *feature_gate.QueryFeatureGateReq
	}
	tests := []struct {
		name string
		args args
		want feature_gate.QueryFeatureGateResp
	}{
		{
			name: "feature-public",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:      1111,
					ProjectID:     1111,
					ClusterID:     1111,
					Region:        "xxx",
					InfraProvider: "xxx",
				},
			},
			want: feature_gate.QueryFeatureGateResp{
				Features: []string{testFeatureA},
			},
		},
		{
			name: "feature-allow-deployment",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					Region:        "us-west-1",
					InfraProvider: "eks",
				},
			},
			want: feature_gate.QueryFeatureGateResp{
				Features: []string{testFeatureA, testFeatureB},
			},
		},
		{
			name: "feature-allow-list",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:  1,
					ProjectID: 1,
					ClusterID: 1,
				},
			},
			want: feature_gate.QueryFeatureGateResp{
				Features: []string{testFeatureA, testFeatureC},
			},
		},
		{
			name: "feature-allow-list-2",
			args: args{
				req: &feature_gate.QueryFeatureGateReq{
					TenantID:      3,
					ProjectID:     3,
					ClusterID:     3,
					Region:        "us-west-1",
					InfraProvider: "eks",
				},
			},
			want: feature_gate.QueryFeatureGateResp{
				Features: []string{testFeatureA, testFeatureB, testFeatureD},
			},
		},
	}
	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			f := impl.NewFeatureGate()
			if got := f.QueryEnabledFeatures(tt.args.req); !reflect.DeepEqual(got, tt.want) {
				t.Errorf("name:%v , QueryEnabledFeatures() = %v, want %v", tt.name, got, tt.want)
			}
		})
	}
}
