package common

import (
	"context"
	"testing"

	"github.com/tidbcloud/infra-provider/pkg/deploy"
	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/appbox/task"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"

	. "github.com/onsi/gomega"
	utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)

func TestCreate(t *testing.T) {
	cases := map[string]struct {
		appbox *v1alpha1.APPBox
		expect func(g *WithT, t *Guardian, res deploy.Result)
	}{
		"appbox is ready": {
			appbox: defaultAPPBox(withAppBoxStatus(v1alpha1.APPBoxPhaseActive)),
			expect: func(g *WithT, t *Guardian, res deploy.Result) {
				g.Expect(res.Error()).To(Succeed())
			},
		},
		"appbox is not ready": {
			appbox: defaultAPPBox(withAppBoxStatus(v1alpha1.APPBoxPhaseCreating)),
			expect: func(g *WithT, t *Guardian, res deploy.Result) {
				err := res.Error()
				g.Expect(err).To(HaveOccurred())
			},
		},
	}

	for name, c := range cases {
		t.Run(name, func(t *testing.T) {
			ctx := context.Background()
			s := runtime.NewScheme()
			utilruntime.Must(v1alpha1.SchemeBuilder.AddToScheme(s))
			g := NewWithT(t)
			gtask := NewGuardian(&task.Context{})
			cli := fake.NewClientBuilder().WithScheme(s).WithRuntimeObjects(c.appbox).Build()
			gtask.Local = cli
			gtask.APPBox = c.appbox
			res := gtask.Create(ctx)
			c.expect(g, gtask, res)
		})
	}
}

func defaultAPPBox(opts ...func(*v1alpha1.APPBox)) *v1alpha1.APPBox {
	o := &v1alpha1.APPBox{
		ObjectMeta: metav1.ObjectMeta{
			Name:      "appbox",
			Namespace: "test",
		},
	}

	for _, f := range opts {
		f(o)
	}
	return o
}

func withAppBoxStatus(status v1alpha1.APPBoxPhase) func(*v1alpha1.APPBox) {
	return func(o *v1alpha1.APPBox) {
		o.Status.Phase = status
	}
}
