package infra

import (
	"strings"
	"testing"

	. "github.com/onsi/gomega"
	"github.com/prometheus/client_golang/prometheus/testutil"
	corev1 "k8s.io/api/core/v1"
	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/utils/pointer"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

func TestMetricsCollector_Collect(t *testing.T) {
	tests := []struct {
		name           string
		objs           []client.Object
		expecedMetrics string
	}{
		//{
		//	name: "basic metrics collector function - namespace",
		//	objs: []client.Object{
		//		&corev1.Namespace{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name: "unit-123",
		//			},
		//			Status: corev1.NamespaceStatus{
		//				Phase: "Active",
		//				Conditions: []corev1.NamespaceCondition{
		//					{
		//						Type:               "",
		//						Status:             "",
		//						LastTransitionTime: v1.Time{},
		//						Reason:             "",
		//						Message:            "",
		//					},
		//				},
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_namespace_info Information and status of infra namespace.
		//	# TYPE infra_api_resources_namespace_info gauge
		//	infra_api_resources_namespace_info{name="unit-123",status="Active"} 1
		//	`,
		//},
		{
			name: "basic metrics collector function - network",
			objs: []client.Object{
				&cloudv1.Network{
					ObjectMeta: v1.ObjectMeta{
						Name:      "network",
						Namespace: "test",
						Labels: map[string]string{
							cloudv1.ProviderTypeLabel: cloudv1.ProviderTypeAWS,
						},
					},
					Spec: cloudv1.NetworkSpec{
						Provider: "aws",
						Region:   "us-west-2",
						CIDR:     "1",
					},
					Status: cloudv1.NetworkStatus{
						Phase: "Active",
						Peering: cloudv1.PeeringStatus{
							Allowed: false,
						},
						Import: cloudv1.NetworkImportStatus{
							RoleARN: "",
						},
						IAM: cloudv1.IAMStatus{
							ServiceAccountEmail: "123@dbaas.com",
							AccountID:           "123",
							ExternalId:          "111",
						},
						FromProvider: runtime.RawExtension{Object: &cloudv1.GardenerNetworkStatus{
							AWS: cloudv1.GardenerNetworkAWSStatus{
								VpcID: pointer.String("vpc-id"),
							},
						}},
					},
				},
			},
			expecedMetrics: `
			# HELP infra_api_resources_network_info Information and status of infra network.
			# TYPE infra_api_resources_network_info gauge
			infra_api_resources_network_info{account_id="123",bucket_name="",cidr="1",email="123@dbaas.com",external_id="111",name="network",namespace="test",project_id="",provider="aws",region="us-west-2",shoot_name="",status="Active",tenant_id="",vpc="vpc-id"} 1
			`,
		},
		{
			name: "basic metrics collector function - cluster",
			objs: []client.Object{
				&cloudv1.Cluster{
					ObjectMeta: v1.ObjectMeta{
						Name:      "test",
						Namespace: "test",
						Labels: map[string]string{
							cloudv1.ProviderTypeLabel: cloudv1.ProviderGCP,
						},
					},
					Spec: cloudv1.ClusterSpec{
						NetworkName: "test",
						SqlEndpoints: cloudv1.SqlEndpoints{
							Public: cloudv1.Service{
								Enabled:                  new(bool),
								LoadBalancerSourceRanges: []string{},
							},
							Private: &cloudv1.Service{
								Enabled:                  new(bool),
								LoadBalancerSourceRanges: []string{},
							},
						},
					},
					Status: cloudv1.ClusterStatus{
						Phase:  "normal",
						Reason: "",
						DB: &cloudv1.DBStatus{
							Version: "v5.3.0",
						},
						SqlEndpoints: cloudv1.SqlEndpointsStatus{
							PublicEndpoint: &cloudv1.SqlEndpointStatus{
								Host: "",
								Port: 0,
							},
							PrivateEndpoint: &cloudv1.SqlEndpointStatus{
								Host: "",
								Port: 0,
							},
						},
						ObjectStore: &cloudv1.ObjectStoreStatus{
							S3: &cloudv1.Path{
								Path: "s3://aws.com",
							},
							GCS: &cloudv1.Path{
								Path: "gcp://gcp.com",
							},
						},
						Metrics: &cloudv1.MetricsStatus{
							BaseURL:          "",
							CredentialConfig: "",
						},
						Proxy: &cloudv1.ProxyStatus{
							Endpoint:         "",
							CredentialConfig: "",
						},
						LastActiveTimestamp: &v1.Time{},
						LastDetectTimestamp: &v1.Time{},
						Conditions:          []cloudv1.ClusterCondition{},
						FromProvider:        runtime.RawExtension{},
					},
				},
			},
			expecedMetrics: `
            # HELP infra_api_resources_cluster_created Creation timestamp and status of infra cluster.
            # TYPE infra_api_resources_cluster_created gauge
            infra_api_resources_cluster_created{name="test",namespace="test",status="normal"} -6.21355968e+10
            # HELP infra_api_resources_cluster_info Information and status of infra cluster.
            # TYPE infra_api_resources_cluster_info gauge
            infra_api_resources_cluster_info{metrics_base_url="",name="test",namespace="test",network_name="test",proxy_endpoint="",status="normal",version="v5.3.0"} 1
			`,
		},
		//{
		//	name: "basic metrics collector function - import",
		//	objs: []client.Object{
		//		&cloudv1.Import{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name:      "test",
		//				Namespace: "test",
		//				Labels: map[string]string{
		//					cloudv1.ProviderTypeLabel: consts.ProviderTypeAWS,
		//					consts.TenantTagKey:       "1",
		//					consts.ProjectTagKey:      "1",
		//					consts.ClusterTagKey:      "123",
		//				},
		//			},
		//			Spec: cloudv1.ImportSpec{
		//				ClusterName: "test",
		//				Source: cloudv1.Source{
		//					Format:   0,
		//					Filters:  []string{},
		//					UserName: "remove-it",
		//					Password: "remove-it",
		//					CsvFormat: &cloudv1.CsvFormat{
		//						Separator:         new(string),
		//						Delimiter:         new(string),
		//						Header:            new(bool),
		//						NotNull:           new(bool),
		//						Null:              new(string),
		//						BackslashEscape:   new(bool),
		//						TrimLastSeparator: new(bool),
		//					},
		//				},
		//				StorageRequest: "",
		//				DryRun:         false,
		//				AccessConfig: cloudv1.AccessConfig{
		//					RoleArn: "",
		//				},
		//			},
		//			Status: cloudv1.ImportStatus{
		//				Phase: "running",
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_import_info Information and status of import job.
		//    # TYPE infra_api_resources_import_info gauge
		//    infra_api_resources_import_info{cloud_provider="aws",cluster_id="123",cluster_name="test",import_config="{\"clusterName\":\"test\",\"source\":{\"storage\":{},\"csvFormat\":{\"separator\":\"\",\"delimiter\":\"\",\"header\":false,\"notNull\":false,\"null\":\"\",\"backslashEscape\":false,\"trimLastSeparator\":false}},\"accessConfig\":{},\"customConfigs\":{}}",name="test",namespace="test",project_id="1",status="running",tenant_id="1"} 1
		//	`,
		//},
		//{
		//	name: "basic metrics collector function - backup",
		//	objs: []client.Object{
		//		&cloudv1.Backup{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name:      "test",
		//				Namespace: "test",
		//				Labels: map[string]string{
		//					cloudv1.ProviderTypeLabel: consts.ProviderTypeAWS,
		//					consts.TenantTagKey:       "1",
		//					consts.ProjectTagKey:      "1",
		//					consts.ClusterTagKey:      "123",
		//				},
		//			},
		//			Spec: cloudv1.BackupSpec{
		//				ClusterName: "123",
		//			},
		//			Status: cloudv1.BackupStatus{
		//				Phase:      "running",
		//				BackupSize: 0,
		//				BackupTS:   "",
		//				BucketName: "",
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_backup_info Information and status of backup job.
		//    # TYPE infra_api_resources_backup_info gauge
		//    infra_api_resources_backup_info{bucket_name="",cloud_provider="aws",cluster_id="123",cluster_name="123",name="test",namespace="test",project_id="1",status="running",tenant_id="1"} 1
		//	`,
		//},
		//{
		//	name: "basic metrics collector function - restore",
		//	objs: []client.Object{
		//		&cloudv1.Restore{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name:      "test",
		//				Namespace: "test",
		//				Labels: map[string]string{
		//					cloudv1.ProviderTypeLabel: consts.ProviderTypeAWS,
		//					consts.TenantTagKey:       "1",
		//					consts.ProjectTagKey:      "1",
		//					consts.ClusterTagKey:      "123",
		//				},
		//			},
		//			Spec: cloudv1.RestoreSpec{
		//				ClusterName: "123",
		//				From: cloudv1.From{
		//					Backup: "test",
		//				},
		//			},
		//			Status: cloudv1.RestoreStatus{
		//				Phase: "running",
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_restore_info Information and status of restore job.
		//    # TYPE infra_api_resources_restore_info gauge
		//    infra_api_resources_restore_info{backup="test",cloud_provider="aws",cluster_id="123",cluster_name="123",name="test",namespace="test",project_id="1",status="running",tenant_id="1"} 1
		//	`,
		//},
		//{
		//	name: "basic metrics collector function - networkpeer",
		//	objs: []client.Object{
		//		&cloudv1.NetworkPeer{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name:      "test",
		//				Namespace: "test",
		//			},
		//			Spec: cloudv1.NetworkPeerSpec{
		//				Source: "aws-us-west-2",
		//				Target: cloudv1.Target{
		//					AWS: &cloudv1.AWS{
		//						AccountID:  "123",
		//						VpcID:      "123",
		//						PeerCIDR:   "10.0.0.0/24",
		//						PeerRegion: "us-west-2",
		//					},
		//					GCP: &cloudv1.GCP{
		//						ProjectID:   "123",
		//						PeerNetwork: "test",
		//					},
		//					TargetNetwork: &cloudv1.TargetNetwork{
		//						NetworkName: "targetNetwork",
		//					},
		//				},
		//			},
		//			Status: cloudv1.NetworkPeerStatus{
		//				Phase:        cloudv1.NetworkPeerPhaseActive,
		//				PeeringID:    "test",
		//				HostedZoneID: "test",
		//				VpcCidr:      "10.250.0.0/16",
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_networkpeer_info Information and status of networkpeer.
		//    # TYPE infra_api_resources_networkpeer_info gauge
		//    infra_api_resources_networkpeer_info{hosted_zone_id="test",name="test",namespace="test",peer_cidr="10.0.0.0/24",peer_network="test",peer_region="us-west-2",peering_id="test",source="aws-us-west-2",status="Active",target_account_id="123",target_network="targetNetwork",target_project_id="123",target_vpc_id="123",vpc_cidr="10.250.0.0/16"} 1
		//	`,
		//},
		//{
		//	name: "basic metrics collector function - ticdc",
		//	objs: []client.Object{
		//		&cloudv1.TiCDC{
		//			ObjectMeta: v1.ObjectMeta{
		//				Name:      "test",
		//				Namespace: "test",
		//			},
		//			Spec: cloudv1.TiCDCSpec{
		//				NetworkName:  "aws-us-west-2",
		//				ClusterName:  "1",
		//				Replicas:     1,
		//				InstanceType: "test",
		//				StorageSize: resource.Quantity{
		//					Format: "",
		//				},
		//			},
		//			Status: cloudv1.TiCDCStatus{
		//				Phase: cloudv1.TiCDCPhaseCreating,
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_ticdc_info Information and status of TiCDC.
		//    # TYPE infra_api_resources_ticdc_info gauge
		//    infra_api_resources_ticdc_info{cluster_name="1",instance_type="test",name="test",namespace="test",network_name="aws-us-west-2",replicas="1",status="Creating"} 1
		//	`,
		//},
		//{
		//	name: "basic metrics collector function - clusterconfig",
		//	objs: []client.Object{
		//		&cloudv1.ClusterConfig{
		//			ObjectMeta: v1.ObjectMeta{Name: "test", Namespace: "test"},
		//			Spec: cloudv1.ClusterConfigSpec{
		//				Version: "",
		//				ConfigMeta: &cloudv1.ConfigMeta{
		//					GitCommitID:   "",
		//					ConfigVersion: 0,
		//				},
		//				TiDB: &cloudv1.Configuration{
		//					BaseImage: new(string),
		//					Tag:       new(string),
		//					Config:    &cloudv1.TomlConfig{},
		//				},
		//				PD:           &cloudv1.Configuration{},
		//				TiKV:         &cloudv1.Configuration{},
		//				TiFlash:      &cloudv1.Configuration{},
		//				Backup:       &cloudv1.Configuration{},
		//				Restore:      &cloudv1.Configuration{},
		//				Lightning:    &cloudv1.Configuration{},
		//				TiCDC:        &cloudv1.Configuration{},
		//				UpdatePolicy: "",
		//				Priority:     0,
		//				Selector:     &v1.LabelSelector{},
		//			},
		//		},
		//	},
		//	expecedMetrics: `
		//	# HELP infra_api_resources_clusterconfig_info Information and status of ClusterConfig.
		//    # TYPE infra_api_resources_clusterconfig_info gauge
		//    infra_api_resources_clusterconfig_info{cluster_config="{\"version\":\"\",\"configMeta\":{\"gitCommitID\":\"\",\"configVersion\":0},\"tidb\":{\"baseImage\":\"\",\"tag\":\"\",\"config\":\"\"},\"pd\":{\"config\":null},\"tikv\":{\"config\":null},\"tiflash\":{\"config\":null},\"backup\":{\"config\":null},\"restore\":{\"config\":null},\"lightning\":{\"config\":null},\"ticdc\":{\"config\":null},\"selector\":{}}",cluster_id="",cluster_version="",name="test",tenant_id=""} 1
		//	`,
		//},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			g := NewGomegaWithT(t)

			// initialize cli
			scheme := runtime.NewScheme()
			g.Expect(corev1.AddToScheme(scheme)).To(Succeed())
			g.Expect(cloudv1.AddToScheme(scheme)).To(Succeed())
			cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(tt.objs...).Build()
			// initialize collector
			collector := &MetricsCollector{
				infraCli: cli,
			}

			err := testutil.CollectAndCompare(collector, strings.NewReader(tt.expecedMetrics))
			// use err to benil when you add the case
			// g.Expect(err).To(BeNil())
			if err != nil {
				t.Fatal(err)
			}
		})
	}
}
