package cluster

import (
	"testing"

	"github.com/onsi/gomega"

	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/entity"
)

func nextgenClusterFixture(
	id, orgID uint64,
	servicePlan openapicommonv1beta1.ServicePlan,
) *entity.Cluster {
	return &entity.Cluster{
		ClusterId:      id,
		OrganizationId: orgID,
		ProjectId:      100,
		DeployType:     entity.DeployTypeNextGen,
		ServicePlan:    servicePlan,
	}
}

func TestValidateMoveCluster(t *testing.T) {
	const (
		orgID    = uint64(10)
		otherOrg = uint64(99)
	)

	tests := []struct {
		name    string
		cluster *entity.Cluster
		orgID   uint64
		wantErr string
	}{
		{
			name:    "premium cluster is valid",
			cluster: nextgenClusterFixture(1, orgID, openapicommonv1beta1.ServicePlan_Premium),
			orgID:   orgID,
		},
		{
			name:    "byoc cluster is valid",
			cluster: nextgenClusterFixture(2, orgID, openapicommonv1beta1.ServicePlan_BYOC),
			orgID:   orgID,
		},
		{
			name:    "essential v2 cluster is valid",
			cluster: nextgenClusterFixture(3, orgID, openapicommonv1beta1.ServicePlan_Essential_V2),
			orgID:   orgID,
		},
		{
			name:    "cluster from wrong org is rejected",
			cluster: nextgenClusterFixture(4, otherOrg, openapicommonv1beta1.ServicePlan_Essential_V2),
			orgID:   orgID,
			wantErr: "does not belong",
		},
		{
			name: "serverless cluster is rejected",
			cluster: &entity.Cluster{
				ClusterId:      5,
				OrganizationId: orgID,
				ProjectId:      100,
				DeployType:     entity.DeployTypeServerless,
				ServicePlan:    openapicommonv1beta1.ServicePlan_Starter,
			},
			orgID:   orgID,
			wantErr: "only supported for NextGen",
		},
		{
			name:    "dedicated plan is rejected",
			cluster: nextgenClusterFixture(6, orgID, openapicommonv1beta1.ServicePlan_Dedicated),
			orgID:   orgID,
			wantErr: "not supported for migration",
		},
	}

	for _, tc := range tests {
		t.Run(tc.name, func(t *testing.T) {
			g := gomega.NewWithT(t)
			err := validateMoveCluster(tc.cluster, tc.orgID)
			if tc.wantErr == "" {
				g.Expect(err).To(gomega.Succeed())
			} else {
				g.Expect(err).To(gomega.HaveOccurred())
				g.Expect(err.Error()).To(gomega.ContainSubstring(tc.wantErr))
			}
		})
	}
}
