package ngoperation

import (
	"context"

	ccproto "github.com/tidbcloud/config-center/proto/config_center"
	opent "github.com/tidbcloud/devops/entity/operation"
	"github.com/tidbcloud/devops/pkg/infra/clients/configcentercli"
	"github.com/tidbcloud/devops/pkg/infra/utils/test"
	"github.com/tidbcloud/devops/pkg/service/operation/actions"

	gk "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
	"go.uber.org/mock/gomock"
)

var _ = gk.Describe("modifyNgImage", func() {
	var fw = test.Framework()
	var ctx context.Context
	var configAPI *configcentercli.MockConfigCenterServiceClient
	var action *modifyNgImage

	gk.BeforeEach(func() {
		ctx = context.Background()
		configAPI = configcentercli.NewMockConfigCenterServiceClient(fw.Ctrl)
		action = &modifyNgImage{
			comps: &actions.Components{
				CfgCenterCli: &configcentercli.Client{
					ConfigAPI: configAPI,
				},
			},
		}
	})

	gk.Describe("Start", func() {
		gk.DescribeTable("updates the component image with the requested version",
			func(version string) {
				instance := buildModifyNgImageInstance(version)

				configAPI.EXPECT().
					UpdateComponentImage(gomock.Any(), gomock.Any()).
					DoAndReturn(func(_ context.Context, req *ccproto.UpdateComponentImageRequest, _ ...interface{}) (*ccproto.ComponentImage, error) {
						expectUpdateComponentImageRequest(req, version)
						return &ccproto.ComponentImage{}, nil
					})

				result, err := action.Start(ctx, instance)
				Expect(err).To(BeNil())
				Expect(result.Result).To(Equal(opent.ActionStatusSucceeded))
			},
			gk.Entry("keeps the legacy skip version unchanged", "v8.5.4"),
			gk.Entry("keeps patch versions unchanged", "v26.3.1"),
			gk.Entry("keeps minor versions unchanged", "v26.3"),
		)
	})
})

func buildModifyNgImageInstance(version string) *opent.Instance {
	return &opent.Instance{
		Params: map[opent.ParamName]string{
			opent.ParamCloudConfigClusterType:         ccproto.ClusterType_LOGICAL_CLUSTER.String(),
			opent.ParamNgModifyImageComponent:         "tidb",
			opent.ParamCloudConfigVersion:             version,
			opent.ParamNgModifyImageBaseImage:         "pingcap/tidb",
			opent.ParamNgModifyImageTag:               "nightly",
			opent.ParamNgModifyImageRelatedChangeLink: "https://example.com/change",
		},
	}
}

func expectUpdateComponentImageRequest(req *ccproto.UpdateComponentImageRequest, version string) {
	Expect(req.GetClusterType()).To(Equal(ccproto.ClusterType_LOGICAL_CLUSTER))
	Expect(req.GetComponentName()).To(Equal("tidb"))
	Expect(req.GetComponentVersion()).To(Equal(version))
	Expect(req.GetBaseImage()).To(Equal("pingcap/tidb"))
	Expect(req.GetTag()).To(Equal("nightly"))
}
