package gardener

import (
	"context"
	"testing"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	. "github.com/onsi/gomega"
	corev1 "k8s.io/api/core/v1"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
	"k8s.io/client-go/kubernetes/scheme"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"

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

func init() {
	utilruntime.Must(cloudv1.AddToScheme(scheme.Scheme))
}

func TestAWSBucket(t *testing.T) {
	g := NewGomegaWithT(t)
	client := fake.NewClientBuilder().Build()
	ctx := context.Background()

	net := new(cloudv1.Network)
	net.Namespace = "ns"
	net.Name = "net-name"
	cp := &cloudv1.GardenerProviderSpec{
		AWS: cloudv1.AwsConfig{CrossplaneProvider: "aws-provider"},
		GCP: cloudv1.GcpConfig{CrossplaneProvider: "aws-provider"},
	}

	_, err := ensureBucket(ctx, client, scheme.Scheme, "aws", cp, net, net.Namespace, net.Name, "us-west-1", nil)
	g.Expect(err).Should(Succeed())

	// bucket should NOT ready
	status, err := GetBucketStatus(ctx, client, "aws", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	c := status.GetCondition(xpv1.TypeReady)
	g.Expect(c.Status).ShouldNot(Equal(corev1.ConditionTrue))

	// mark as ready condition as true and check again
	err = MarkBucketReady(ctx, client, "aws", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	status, err = GetBucketStatus(ctx, client, "aws", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	c = status.GetCondition(xpv1.TypeReady)
	g.Expect(c.Status).Should(Equal(corev1.ConditionTrue))
}

func TestGCPBucket(t *testing.T) {
	g := NewGomegaWithT(t)
	client := fake.NewClientBuilder().Build()
	ctx := context.Background()

	net := new(cloudv1.Network)
	net.Namespace = "ns"
	net.Name = "net-name"
	cp := &cloudv1.GardenerProviderSpec{
		AWS: cloudv1.AwsConfig{CrossplaneProvider: "aws-provider"},
		GCP: cloudv1.GcpConfig{CrossplaneProvider: "aws-provider"},
	}

	_, err := ensureBucket(ctx, client, scheme.Scheme, "gcp", cp, net, net.Namespace, net.Name, "us-west-1", nil)
	g.Expect(err).Should(Succeed())

	// bucket should NOT ready
	status, err := GetBucketStatus(ctx, client, "gcp", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	c := status.GetCondition(xpv1.TypeReady)
	g.Expect(c.Status).ShouldNot(Equal(corev1.ConditionTrue))

	// mark as ready condition as true and check again
	err = MarkBucketReady(ctx, client, "gcp", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	status, err = GetBucketStatus(ctx, client, "gcp", net.Namespace, net.Name)
	g.Expect(err).Should(Succeed())
	c = status.GetCondition(xpv1.TypeReady)
	g.Expect(c.Status).Should(Equal(corev1.ConditionTrue))
}

func TestBucketTags(t *testing.T) {
	g := NewGomegaWithT(t)

	checkTags := map[string]string{"a": "a", "b": "b", "c": "c"}
	awstags := map[string]string{}
	awsRes := buildAWSBucket("", "", "", checkTags, "")
	for _, tag := range awsRes.Spec.ForProvider.BucketTagging.TagSet {
		awstags[tag.Key] = tag.Value
	}
	g.Expect(checkTags).To(Equal(awstags))

	gcpRes := buildGCPBucket("", "", "", checkTags, "")
	gcptags := gcpRes.Spec.BucketParameters.BucketSpecAttrs.DeepCopy().Labels
	g.Expect(checkTags).To(Equal(gcptags))

	checkTags["a"] = "b"
	g.Expect(checkTags).NotTo(Equal(awstags))
	g.Expect(checkTags).NotTo(Equal(gcptags))
}
