package k8s

import (
	"context"
	"testing"

	. "github.com/onsi/gomega"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	models "github.com/tidbcloud/infra-provider/pkg/compat/models"
	"github.com/tidbcloud/infra-provider/pkg/config"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestCompatK8sClient(t *testing.T) {
	g := NewGomegaWithT(t)
	s := runtime.NewScheme()
	// g.Expect(scheme.AddToScheme(s)).To(Succeed())
	g.Expect(cloudv1.SchemeBuilder.AddToScheme(s)).To(Succeed())
	{
		// get from old path
		network := &cloudv1.Network{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "test",
				Namespace: "test",
			},
		}
		key := client.ObjectKey{
			Name:      "test",
			Namespace: "test",
		}
		retnetwork := &cloudv1.Network{}
		cli := fake.NewClientBuilder().WithScheme(s).WithObjects(network).Build()
		ckc := NewCompatK8sClient(cli, "dev", "", "", "", config.OverrideConfig{}, "")
		err := ckc.Get(context.TODO(), key, retnetwork)
		g.Expect(err).ToNot(HaveOccurred())
		g.Expect(retnetwork.Name).Should(Equal(network.Name))
	}
	{
		// get from new path network
		network := &cloudv1.Network{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "test",
				Namespace: "test",
			},
		}
		key := client.ObjectKey{
			Name:      "test",
			Namespace: "test",
		}
		retnetwork := &cloudv1.Network{}
		newcli := fake.NewClientBuilder().WithScheme(s).WithObjects(network).Build()
		cli := fake.NewClientBuilder().WithScheme(s).Build()
		ckc := CompatK8sClient{
			CompatK8sReader: &CompatK8sReader{
				cli:        cli,
				networkcli: NewFakeCompatK8sClient(newcli),
			},
		}
		err := ckc.Get(context.TODO(), key, retnetwork)
		g.Expect(err).ToNot(HaveOccurred())
		g.Expect(retnetwork.Name).Should(Equal(network.Name))
	}
	{
		// get from new path cluster
		cluster := &cloudv1.Cluster{
			ObjectMeta: metav1.ObjectMeta{
				Name:      "test",
				Namespace: "test",
			},
		}
		key := client.ObjectKey{
			Name:      "test",
			Namespace: "test",
		}
		retcluster := &cloudv1.Cluster{}
		newcli := fake.NewClientBuilder().WithScheme(s).WithObjects(cluster).Build()
		cli := fake.NewClientBuilder().WithScheme(s).Build()
		ckc := CompatK8sClient{
			CompatK8sReader: &CompatK8sReader{
				cli:        cli,
				clustercli: NewFakeCompatK8sClient(newcli),
			},
		}
		err := ckc.Get(context.TODO(), key, retcluster)
		g.Expect(err).ToNot(HaveOccurred())
		g.Expect(retcluster.Name).Should(Equal(cluster.Name))
	}
}

type FakeCompatK8sClient struct {
	cli client.Client
}

func NewFakeCompatK8sClient(cli client.Client) *FakeCompatK8sClient {
	return &FakeCompatK8sClient{
		cli: cli,
	}
}

func (ckc FakeCompatK8sClient) GetCluster(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
	return ckc.cli.Get(ctx, key, obj, opts...)
}

func (ckc FakeCompatK8sClient) GetNetwork(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
	return ckc.cli.Get(ctx, key, obj, opts...)
}

func (ckc FakeCompatK8sClient) GetPrivateSubnet(ctx context.Context, network *cloudv1.Network) ([]models.Globaldedicatedv1CompatNetworkAwsNodeSubnet, error) {
	return nil, nil
}

func (ckc FakeCompatK8sClient) GetProvider(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
	return ckc.cli.Get(ctx, key, obj, opts...)
}
