package cluster

import (
	"context"
	"testing"

	"github.com/aws/aws-sdk-go-v2/aws"
	"github.com/go-logr/logr"
	. "github.com/onsi/gomega"
	"github.com/tidbcloud/aws-shared-provider/pkg/o11y"
	"github.com/tidbcloud/aws-shared-provider/pkg/utils/clientfake"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-api/pkg/consts"
	o11ymetric "github.com/tidbcloud/infra-api/pkg/o11y/metric_agent"
	infrao11y "github.com/tidbcloud/observability/agent-control-server/pkg/o11y/api"
	infrao11yfake "github.com/tidbcloud/observability/agent-control-server/pkg/o11y/api/fake"
	infra "github.com/tidbcloud/tidb-management-service/api/serverless_infra"
	"github.com/tidbcloud/tidb-management-service/api/serverless_infra/meta"
	gomock "go.uber.org/mock/gomock"
	"k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestO11yClusterServerless(t *testing.T) {
	// Define crd objects
	region := "us-west-2"
	o11yID := "fake-o11y-id"
	cluster01 := &infra.Cluster{
		ObjectMeta: meta.ObjectMeta{
			Name:        "cluster_01",
			Region:      region,
			TagsProject: "project_01",
			TagsTenant:  "tenant_01",
		},
		Spec: infra.ClusterSpec{TiDB: infra.TiDBSpec{Replicas: 1}},
	}

	// Set up context
	g := NewGomegaWithT(t)
	g.Expect(cloudv1.AddToScheme(scheme.Scheme)).Should(Succeed())
	ctrl := gomock.NewController(t)
	defer ctrl.Finish()
	o11yApi := infrao11yfake.NewMockApi(ctrl)
	//nolint:lll // ignore
	o11yApi.EXPECT().CreateO11yInfraV2Serverless(
		gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
		&infrao11y.ObservabilityCluster{
			ClusterBaseInfo: infrao11y.ClusterBaseInfo{
				ID: o11yID,
			},
			MonitorInfo: infrao11y.MonitorInfo{
				EndpointServiceName: "fake-endpoint-service-name",
				DnsName:             aws.String("fake-dns-name"),
			},
			Status: infrao11y.ACTIVE,
		}, nil).MinTimes(1)
	o11yApi.EXPECT().DeleteO11yInfra(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(
		&infrao11y.ObservabilityCluster{}, nil).MinTimes(1)
	r := &reconcileContext{Logger: logr.Discard()}
	r.Reconciler = &Reconciler{Logger: logr.Discard()}
	r.ctx = context.Background()
	r.InfraClusterCli = clientfake.NewInfraClient(cluster01).Build()
	r.Client = fake.NewClientBuilder().WithObjects().Build()
	r.cluster = cluster01
	r.KubeClusterName = "dev-us-east-1-f01"
	r.O11yApi = o11yApi
	r.O11yConfig = &cloudv1.ObservabilityInfraConfig{
		Version: 0,
	}

	// Run the creation.
	err := r.ensureO11yCluster()

	// Check the creation output.
	g.Expect(err).Should(Succeed())

	remoteWrite := o11ymetric.NewWriteURLBuilder("fake-dns-name").ForAWS().
		BuildRemoteWrite(o11yID)

	// Assert o11y annotations are added to cluster crd.
	g.Expect(cluster01.Annotations).Should(HaveKeyWithValue(o11y.O11yClusterRemoteWriteAnnotationKey, remoteWrite))
	g.Expect(cluster01.Annotations).Should(HaveKeyWithValue(consts.O11yIDAnnotationKey, o11yID))

	// Run the deletion.
	err = r.deleteO11yCluster()

	// Check the deletion output.
	g.Expect(err).Should(Succeed())
}
