package cluster

import (
	"context"
	"testing"

	. "github.com/onsi/gomega"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/log"

	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/shared-provider/pkg/utils"
)

func TestObserveCluster(t *testing.T) {
	cases := map[string]struct {
		cluster *cloudv1.Cluster
		tc      *v1alpha1.TidbCluster

		expectMetrics     *cloudv1.MetricsStatus
		expectProxy       *cloudv1.ProxyStatus
		expectObjectStore *cloudv1.ObjectStoreStatus
	}{
		"TEST": {
			cluster: &cloudv1.Cluster{
				ObjectMeta: metav1.ObjectMeta{
					Name:      "test",
					Namespace: "test-ns",
				},
				Spec: cloudv1.ClusterSpec{
					Cluster: cloudv1.ClusterTopology{
						TiDB: cloudv1.TiDB{
							Replicas:     1,
							InstanceType: "tidb.sharedtier",
						},
						TiKV: cloudv1.TiKV{
							Replicas:     1,
							InstanceType: "tikv.sharedtier",
							StorageSize:  resource.MustParse("15Gi"),
						},
						PD: cloudv1.PD{
							Replicas:     1,
							InstanceType: "pd.sharedtier",
							StorageSize:  resource.MustParse("2Gi"),
						},
					},
				},
			},
			tc: &v1alpha1.TidbCluster{
				ObjectMeta: metav1.ObjectMeta{
					Name: "test",
					UID:  "dd2aac1d-16bf-9999-ab21-708454b9aa99",
				},
				Spec: v1alpha1.TidbClusterSpec{
					Version: "v5.0.2",
					TiDB: &v1alpha1.TiDBSpec{
						Replicas: 1,
					},
					TiKV: &v1alpha1.TiKVSpec{
						Replicas: 1,
					},
					PD: &v1alpha1.PDSpec{
						Replicas: 1,
					},
				},
				Status: v1alpha1.TidbClusterStatus{
					TiDB: v1alpha1.TiDBStatus{
						Phase: v1alpha1.NormalPhase,
						Members: map[string]v1alpha1.TiDBMember{
							"tidb1": {Name: "tidb1", Health: true},
						},
					},
					PD: v1alpha1.PDStatus{
						Phase: v1alpha1.NormalPhase,
						Members: map[string]v1alpha1.PDMember{
							"pd1": {Name: "pd1", Health: true},
						},
					},
					TiKV: v1alpha1.TiKVStatus{
						Phase: v1alpha1.NormalPhase,
						Stores: map[string]v1alpha1.TiKVStore{
							"tikv1": {PodName: "tikv1", State: v1alpha1.TiKVStateUp},
						},
					},
				},
			},
			expectMetrics: &cloudv1.MetricsStatus{
				BaseURL: "fakeproxy.com/proxy/namespace/test-user-ns/tidbmonitor/test/prometheus",
			},
			expectProxy: &cloudv1.ProxyStatus{
				Endpoint: "fakeproxy.com/proxy/namespace/test-user-ns/cluster/test",
			},
			expectObjectStore: &cloudv1.ObjectStoreStatus{
				S3: &cloudv1.Path{
					Path: "s3_bucket",
				},
			},
		},
	}
	for name, c := range cases {
		t.Run(name, func(t *testing.T) {
			g := NewGomegaWithT(t)
			r := newFakeReconcileContext(c.cluster, nil)
			r.tc = c.tc

			err := r.Client.Create(context.Background(), r.tc)
			g.Expect(err).To(Succeed())

			g.Expect(r.createTidbMonitor()).To(Succeed())

			err = r.observeCluster()
			g.Expect(err).NotTo(Succeed())
			res, err := utils.ReconcileErr(log.Log, err)
			g.Expect(err).To(Succeed())
			g.Expect(res.RequeueAfter).ShouldNot(Equal(0))

			g.Expect(r.cluster.Status.Metrics).To(Equal(c.expectMetrics))
			g.Expect(r.cluster.Status.Proxy).To(Equal(c.expectProxy))
			g.Expect(r.cluster.Status.ObjectStore).To(Equal(c.expectObjectStore))
		})
	}
}
