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 starterCluster(id, orgId, projectId uint64) *entity.Cluster {
	return &entity.Cluster{
		ClusterId:      id,
		OrganizationId: orgId,
		ProjectId:      projectId,
		DeployType:     entity.DeployTypeServerless,
		ServicePlan:    openapicommonv1beta1.ServicePlan_Starter,
	}
}

func essentialCluster(id, orgId, projectId uint64) *entity.Cluster {
	return &entity.Cluster{
		ClusterId:      id,
		OrganizationId: orgId,
		ProjectId:      projectId,
		DeployType:     entity.DeployTypeServerless,
		ServicePlan:    openapicommonv1beta1.ServicePlan_Essential,
	}
}

func dedicatedClusterFixture(id, orgId, projectId uint64) *entity.Cluster {
	return &entity.Cluster{
		ClusterId:      id,
		OrganizationId: orgId,
		ProjectId:      projectId,
		DeployType:     entity.DeployTypeDedicated,
		ServicePlan:    openapicommonv1beta1.ServicePlan_Dedicated,
	}
}

// TestValidateMoveCluster tests the validateMoveCluster helper that enforces
// the core business rules for serverless cluster migration eligibility.
func TestValidateMoveCluster(t *testing.T) {
	const (
		orgId    = uint64(10)
		otherOrg = uint64(99)
		proj     = uint64(100)
	)

	tests := []struct {
		name    string
		cluster *entity.Cluster
		orgId   uint64
		wantErr string
	}{
		{
			name:    "starter cluster is valid",
			cluster: starterCluster(1, orgId, proj),
			orgId:   orgId,
		},
		{
			name:    "essential cluster is valid",
			cluster: essentialCluster(2, orgId, proj),
			orgId:   orgId,
		},
		{
			name:    "dedicated cluster is rejected",
			cluster: dedicatedClusterFixture(3, orgId, proj),
			orgId:   orgId,
			wantErr: "only supported for Serverless",
		},
		{
			name:    "cluster from wrong org is rejected",
			cluster: starterCluster(4, otherOrg, proj),
			orgId:   orgId,
			wantErr: "does not belong",
		},
		{
			name: "premium cluster is rejected by serverless service",
			cluster: &entity.Cluster{
				ClusterId:      5,
				OrganizationId: orgId,
				ProjectId:      proj,
				DeployType:     entity.DeployTypeNextGen,
				ServicePlan:    openapicommonv1beta1.ServicePlan_Premium,
			},
			orgId:   orgId,
			wantErr: "only supported for Serverless",
		},
		{
			name: "BYOC cluster is rejected by serverless service",
			cluster: &entity.Cluster{
				ClusterId:      6,
				OrganizationId: orgId,
				ProjectId:      proj,
				DeployType:     entity.DeployTypeNextGen,
				ServicePlan:    openapicommonv1beta1.ServicePlan_BYOC,
			},
			orgId:   orgId,
			wantErr: "only supported for Serverless",
		},
		{
			name: "premium cluster with serverless deploy type is rejected",
			cluster: &entity.Cluster{
				ClusterId:      7,
				OrganizationId: orgId,
				ProjectId:      proj,
				DeployType:     entity.DeployTypeServerless,
				ServicePlan:    openapicommonv1beta1.ServicePlan_Premium,
			},
			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))
			}
		})
	}
}
