package cloudconfig

import (
	"testing"

	ccproto "github.com/tidbcloud/config-center/proto/config_center"
	ccapi "github.com/tidbcloud/devops/api/cloudconfig"
	clusterapi "github.com/tidbcloud/devops/api/cluster"
	ccent "github.com/tidbcloud/devops/entity/cloudconfig"
	"github.com/tidbcloud/devops/pkg/infra/utils/test"

	. "github.com/onsi/ginkgo/v2"
	. "github.com/onsi/gomega"
)

func TestCloudConfigController(t *testing.T) {
	RegisterFailHandler(Fail)
	RunSpecs(t, "CloudConfig Controller Suite", test.ReporterConfig())
}

var _ = Describe("[ConfigChange]", func() {
	Describe("BuildParamToCreateConfigurationChange", func() {
		It("maps execution window", func() {
			req := &ccapi.CreateConfigurationChangeReq{
				ExecutionWindow: &clusterapi.CreateOpsExecutionWindowReq{
					StartAt: 100,
					EndAt:   200,
				},
			}

			param := BuildParamToCreateConfigurationChange(req, "user@pingcap.com")

			Expect(param.ExecutionWindow.StartAt).To(Equal(req.ExecutionWindow.StartAt))
			Expect(param.ExecutionWindow.EndAt).To(Equal(req.ExecutionWindow.EndAt))
		})
	})
})

var _ = Describe("[CloudConfigController]", func() {
	Describe("normalizeComponentImageRecordClusterType", func() {
		It("normalizes query cluster type for params search", func() {
			Expect(normalizeComponentImageRecordClusterType(ccent.ClusterType("shared_pool"))).To(Equal(ccent.ClusterTypeSharedPool))
			Expect(normalizeComponentImageRecordClusterType(ccent.ClusterType("logical-cluster"))).To(Equal(ccent.ClusterTypeLogicalCluster))
			Expect(normalizeComponentImageRecordClusterType(ccent.ClusterType(""))).To(Equal(ccent.ClusterTypeUnknown))
		})
	})

	Describe("validateMetaProfileComponentVersions", func() {
		It("accepts image tags with matching component versions", func() {
			req := &ccapi.CreateMetaProfileReq{
				ComponentImageTags: map[string]string{
					"tidb": "v8.5.4-20260629",
				},
				ComponentVersions: map[string]string{
					"tidb": "v8.5.4",
				},
			}

			Expect(validateMetaProfileComponentVersions(req)).To(Succeed())
		})

		It("rejects image tags without matching component versions", func() {
			req := &ccapi.CreateMetaProfileReq{
				ComponentImageTags: map[string]string{
					"tidb": "v8.5.4-20260629",
				},
			}

			Expect(validateMetaProfileComponentVersions(req)).To(MatchError("component_versions[tidb] is required when component_image_tags[tidb] is set"))
		})

		It("rejects empty component versions", func() {
			req := &ccapi.CreateMetaProfileReq{
				ComponentVersions: map[string]string{
					"tidb": "",
				},
			}

			Expect(validateMetaProfileComponentVersions(req)).To(MatchError("component_versions[tidb] is required"))
		})
	})
})

var _ = Describe("[DefaultConfigChange]", func() {
	Describe("parseListDefaultVersionRulesClusterType", func() {
		It("maps cluster type to config center cluster type", func() {
			clusterType, err := parseListDefaultVersionRulesClusterType(ccent.ClusterTypeSharedPool)

			Expect(err).NotTo(HaveOccurred())
			Expect(clusterType).To(Equal(ccproto.ClusterType_SHARED_POOL))
		})

		It("rejects invalid cluster type", func() {
			_, err := parseListDefaultVersionRulesClusterType(ccent.ClusterType("invalid"))

			Expect(err).To(HaveOccurred())
		})
	})

	Describe("buildListDefaultVersionRulesResp", func() {
		It("converts cluster type to cloudconfig cluster type", func() {
			resp := buildListDefaultVersionRulesResp(&ccproto.ListDefaultVersionRulesResponse{
				Rules: []*ccproto.DefaultVersionRule{
					{
						ClusterType:    ccproto.ClusterType_SHARED_POOL,
						Component:      "tikv",
						ClusterVersion: "v8.5.0",
						CloudProvider:  "aws",
						Region:         "us-west-2",
						Version:        "v8.5.1",
					},
				},
			})

			Expect(resp.Rules).To(HaveLen(1))
			Expect(resp.Rules[0].ClusterType).To(Equal(ccent.ClusterTypeSharedPool))
			Expect(resp.Rules[0].Component).To(Equal("tikv"))
			Expect(resp.Rules[0].ClusterVersion).To(Equal("v8.5.0"))
			Expect(resp.Rules[0].CloudProvider).To(Equal("aws"))
			Expect(resp.Rules[0].Region).To(Equal("us-west-2"))
			Expect(resp.Rules[0].Version).To(Equal("v8.5.1"))
		})

		It("converts unknown cluster type to empty cloudconfig cluster type", func() {
			resp := buildListDefaultVersionRulesResp(&ccproto.ListDefaultVersionRulesResponse{
				Rules: []*ccproto.DefaultVersionRule{
					{
						ClusterType: ccproto.ClusterType_CLUSTER_TYPE_UNSPECIFIED,
					},
				},
			})

			Expect(resp.Rules).To(HaveLen(1))
			Expect(resp.Rules[0].ClusterType).To(Equal(ccent.ClusterTypeUnknown))
		})
	})
})
