package cluster

import (
	"context"
	"testing"

	"github.com/stretchr/testify/require"
	"go.uber.org/mock/gomock"

	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	dedicatedcluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/dedicated/cluster"
	mocknextgencluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/nextgen/cluster/mock_cluster"
	serverlesscluster "github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/domain/service/serverless/cluster"
)

func TestCleanClustersNextGen(t *testing.T) {
	ctrl := gomock.NewController(t)
	nextgenService := mocknextgencluster.NewMockService(ctrl)
	nextgenService.EXPECT().CleanClusters(gomock.Any(), uint64(8), true).Return(nil)
	server := &serverImpl{nextgenClusterSvc: nextgenService}

	response, err := server.CleanClusters(t.Context(), &tidbmgmtservicev1.CleanClustersRequest{
		OrganizationId: 8,
		DeployType:     tidbmgmtservicev1.DeployType_DEPLOY_TYPE_NEXTGEN,
	})

	require.NoError(t, err)
	require.NotNil(t, response)
}

func TestCleanClustersUnspecifiedIncludesNextGen(t *testing.T) {
	ctrl := gomock.NewController(t)
	nextgenService := mocknextgencluster.NewMockService(ctrl)
	order := make([]string, 0, 3)
	serverlessService := cleanServerlessService{clean: func(context.Context, uint64) error {
		order = append(order, "serverless")
		return nil
	}}
	dedicatedService := cleanDedicatedService{clean: func(context.Context, uint64, bool) error {
		order = append(order, "dedicated")
		return nil
	}}
	nextgenService.EXPECT().CleanClusters(gomock.Any(), uint64(8), false).DoAndReturn(
		func(context.Context, uint64, bool) error {
			order = append(order, "nextgen")
			return nil
		},
	)
	server := &serverImpl{
		serverlessClusterSvc: serverlessService,
		dedicatedClusterSvc:  dedicatedService,
		nextgenClusterSvc:    nextgenService,
	}

	response, err := server.CleanClusters(t.Context(), &tidbmgmtservicev1.CleanClustersRequest{
		OrganizationId:     8,
		DisableFinalBackup: true,
	})

	require.NoError(t, err)
	require.NotNil(t, response)
	require.Equal(t, []string{"serverless", "dedicated", "nextgen"}, order)
}

type cleanServerlessService struct {
	serverlesscluster.Service

	clean func(context.Context, uint64) error
}

func (s cleanServerlessService) CleanClusters(ctx context.Context, organizationID uint64) error {
	return s.clean(ctx, organizationID)
}

type cleanDedicatedService struct {
	dedicatedcluster.Service

	clean func(context.Context, uint64, bool) error
}

func (s cleanDedicatedService) CleanClusters(ctx context.Context, organizationID uint64, needFinalBackup bool) error {
	return s.clean(ctx, organizationID, needFinalBackup)
}
