package tests

import (
	"fmt"
	"testing"

	"github.com/pingcap/dbaas/billing2/config"
	"github.com/pingcap/dbaas/billing2/constant"
	"github.com/pingcap/dbaas/billing2/db"
	"github.com/pingcap/dbaas/billing2/db/entity"
	"github.com/pingcap/dbaas/billing2/forms"
	"github.com/pingcap/dbaas/billing2/handler/centralhandler"
	"github.com/pingcap/dbaas/billing2/handler/paymenthandler"
	"github.com/pingcap/dbaas/billing2/handler/paymenthandler/impl"
	"github.com/pingcap/dbaas/billing2/model/control"
	"github.com/pingcap/dbaas/billing2/model/creditriskcontrol"
	"github.com/pingcap/dbaas/billing2/model/marketing"
	"github.com/pingcap/dbaas/billing2/model/marketing/plan"
	"github.com/pingcap/dbaas/billing2/model/marketing/unit_filter"
	"github.com/pingcap/dbaas/billing2/model/payment/paymentsub"
	"github.com/pingcap/dbaas/billing2/utils/tests"
	"github.com/pingcap/dbaas/billing2/utils/tests/datainit"
	"github.com/pingcap/dbaas/billing2/utils/timeutils"
	"github.com/shopspring/decimal"
	"github.com/stretchr/testify/suite"
)

var controlModel = &control.Model{}

type ControlTestSuite struct {
	tests.BillingTestSuite
}

func TestControlTestSuite(t *testing.T) {
	suite.Run(t, new(ControlTestSuite))
}

type MockCentralHandlerImpl struct {
	tests.MockCentralHandlerImpl
}

func (*MockCentralHandlerImpl) GetTenant(tenantID uint) (*forms.Tenant, error) {
	fmt.Println(tenantID)
	if tenantID == 100 {
		return &forms.Tenant{
			TenantID:                  tenantID,
			ThirdPartyAccountProvider: constant.MSPAccountProvider,
			Status:                    centralhandler.TenantStatusActive,
		}, nil
	} else if tenantID == 22 {
		return &forms.Tenant{
			TenantID:                  tenantID,
			ThirdPartyAccountProvider: constant.AwsAccountProvider,
			Status:                    centralhandler.TenantStatusActive,
		}, nil
	}
	return &forms.Tenant{
		TenantID:                  tenantID,
		ThirdPartyAccountProvider: constant.GCPAccountProvider,
		Status:                    centralhandler.TenantStatusActive,
	}, nil
}

func (suite *ControlTestSuite) TestActionCheck() {
	central := &MockCentralHandlerImpl{}
	centralhandler.SetCentralHandler(central)
	config.Get().Set(config.InAPPNotificationEnable, false)
	assert := suite.Assert()
	timeutils.SetMockNow(datainit.BillingDate)
	var tenantID = uint(1)
	provider := forms.Provider_GCP
	actionInfo := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_DedicatedCluster,
			Provider: &provider,
			IsFree:   true,
			Origin:   map[string]interface{}{"region": "us-east-1", "zone": "us-east-1a", "id": 1, "meta": map[string]interface{}{"op": "create", "kl": 111, "x": []interface{}{2134, "csacsa", map[string]interface{}{"ss": true}}}},
		},
	}
	res, err := controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	assert.Equal(actionInfo.Resource.Origin, res.Original)
	res, err = controlModel.BillingActionCheck(100, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	res, err = controlModel.BillingActionCheck(22, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	billingConfig, err := datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	assert.NoError(err)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	actionInfo.Resource.IsFree = false
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.UnpayableMsg, *res.Reason)
	actionInfo.Resource.Type = forms.BillingResourceType_LakeWarehouse
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.UnpayableMsg, *res.Reason)
	actionInfo.Resource.Type = forms.BillingResourceType_DedicatedCluster
	now := timeutils.GetNow()
	generalUnitFilter, err := (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "General", Description: "General"},
		General:        true,
	})
	assert.NoError(err)
	credits, err := (&marketing.CreditsPackageModel{}).CreateCreditsPackage(tenantID, &forms.CreditsPackage{
		Usage:                 entity.CreditsPackageUsage_POC,
		TotalCredits:          decimal.NewFromInt(1),
		StartDate:             timeutils.GetMonthDate(now),
		ExpiredDate:           timeutils.GetMonthDate(now).AddDate(0, 1, 0),
		UnitFilters:           []*forms.UnitFilterSlim{&generalUnitFilter.UnitFilterSlim},
		BindedBillingConfigID: &billingConfig.BillingConfigID,
	})
	assert.NoError(err)
	assert.NoError((&plan.TenantPlanModel{}).EnableTenantPOCPlanAfterCreditsOpened(tenantID))
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	err = entity.NewBindedPackageQuerySet(db.GetDB()).IDEq(*credits.BindedPackageID).GetUpdater().SetRemainingCredits(decimal.Zero).Update()
	assert.NoError(err)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.NoPOCCreditsMsg, *res.Reason)

	config.Get().Set(config.EnableActionCheckOnBillable, false)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	config.Get().Set(config.EnableActionCheckOnBillable, true)

	assert.NoError(err)
	assert.NoError(datainit.CreatePaymentMock(tenantID))
	centralhandler.SetCentralHandler(central)
	assert.NoError((&plan.TenantPlanModel{}).EnableTenantOnDemandPlan(tenantID))

	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	payment, err := (&paymentsub.PaymentModel{}).GetActivePaymentMethod(tenantID, billingConfig.BillingConfigID)
	assert.NoError(err)
	assert.NoError(entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payment.PaymentMethodID).GetUpdater().SetPaymentType(entity.PaymentType_AWSCPPOTransfer).Update())

	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.NotMatchedProviderMsg, *res.Reason)

	actionInfo.Resource.IsFree = true
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.NotMatchedProviderMsg, *res.Reason)
	config.Get().Set(config.EnableActionCheckProviderMatched, false)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	config.Get().Set(config.EnableActionCheckProviderMatched, true)

	actionInfo.Resource.IsFree = false
	provider = forms.Provider_AWS
	actionInfo.Resource.Provider = &provider
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	actionInfo.Resource.Type = forms.BillingResourceType_LakeWarehouse
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	actionInfo.Resource.Type = forms.BillingResourceType_DedicatedCluster

	actionInfo.Resource.Type = forms.BillingResourceType_ServerlessCluster
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	actionInfo.Resource.Type = forms.BillingResourceType_DedicatedBackup
	actionInfo.Action = forms.BillingAction_Delete
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	creditCreditRiskLevel := &forms.CreditRiskLevel{
		CreditRiskLevelID: 1,
		Name:              "test",
	}

	_, err = (&creditriskcontrol.CreditRiskLevelModel{}).CreateCreditRiskLevel(creditCreditRiskLevel)
	assert.NoError(err)
	closeModel := &creditriskcontrol.TenantCloseModel{}
	closePolicy := forms.ClosePolicy{
		Actions: []*forms.CloseAction{
			{
				Action:           "test",
				ActionTimeInHour: 1,
			},
		},
	}
	err = closeModel.CreateTenantRiskClosePolicy(0, &forms.TenantClosePolicy{
		ClosePolicy: closePolicy,
	})
	assert.NoError(err)
	_, err = closeModel.CreateTenantClosePolicy(&forms.TenantClosePolicy{
		CreditRiskLevelID: 0,
		Reason:            entity.TenantCloseReason_Unpayable,
		ClosePolicy:       closePolicy,
	})
	assert.NoError(err)
	err = closeModel.RunTenantClose(tenantID, entity.TenantCloseReason_Unpayable)
	assert.NoError(err)

	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.OrgSuspendMsg, *res.Reason)

	actionInfo.Resource.Type = forms.BillingResourceType_DedicatedCluster
	actionInfo.Action = forms.BillingAction_Create
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.OrgSuspendMsg, *res.Reason)
	actionInfo.Resource.Type = forms.BillingResourceType_LakeWarehouse
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.OrgSuspendMsg, *res.Reason)
	actionInfo.Resource.Type = forms.BillingResourceType_DedicatedCluster

	actionInfo.Action = forms.BillingAction_Scaledown
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.OrgSuspendMsg, *res.Reason)

	actionInfo.Action = forms.BillingAction_Scaleup
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.OrgSuspendMsg, *res.Reason)

	actionInfo.Action = forms.BillingAction_Delete
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	actionInfoView := forms.BillingActionInfo{
		Action: forms.BillingAction_View,
		Resource: forms.BillingResource{
			Type:   forms.BillingResourceType_DedicatedCluster,
			IsFree: false,
		},
	}

	// Get Active Payment Method
	payment, err = (&paymentsub.PaymentModel{}).GetActivePaymentMethod(tenantID, billingConfig.BillingConfigID)
	assert.NoError(err)

	// 1.1 Test with AWS Payment Type
	assert.NoError(entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payment.PaymentMethodID).GetUpdater().SetPaymentType(entity.PaymentType_AWS).Update())
	providerAWS := forms.Provider_AWS
	actionInfoView.Resource.Provider = &providerAWS
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfoView)
	assert.NoError(err)
	assert.True(res.Pass)

	// 1.2 Test with GCP Payment Type
	assert.NoError(entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payment.PaymentMethodID).GetUpdater().SetPaymentType(entity.PaymentType_GCP).Update())
	providerGCP := forms.Provider_GCP
	actionInfoView.Resource.Provider = &providerGCP
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfoView)
	assert.NoError(err)
	assert.True(res.Pass)

	// 1.3 Test with Azure Payment Type
	assert.NoError(entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payment.PaymentMethodID).GetUpdater().SetPaymentType(entity.PaymentType_AZURE).Update())
	providerAzure := forms.Provider_Azure
	actionInfoView.Resource.Provider = &providerAzure
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfoView)
	assert.NoError(err)
	assert.True(res.Pass)

	assert.NoError(entity.NewPaymentMethodQuerySet(db.GetDB()).IDEq(payment.PaymentMethodID).GetUpdater().SetPaymentType(entity.PaymentType_AliCloud).Update())
	providerAliCloud := forms.Provider_AliCloud
	actionInfoView.Resource.Provider = &providerAliCloud
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfoView)
	assert.NoError(err)
	assert.True(res.Pass)

	config.Get().Set(config.EnableActionCheckProviderMatched, false)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfoView)
	assert.NoError(err)
	assert.True(res.Pass)
	config.Get().Set(config.EnableActionCheckProviderMatched, true) // Reset to default

	provider = forms.Provider_GCP
	actionInfo.Resource.Provider = &provider
	actionInfo.Action = forms.BillingAction_View
	res, err = controlModel.BillingActionCheck(100, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)

	res, err = controlModel.BillingActionCheck(22, &actionInfo)
	assert.NoError(err)
	assert.False(res.Pass) //Expect fail because AwsAccountProvider does not match GCP

	// 2.3 tenantID == 1 (GCPAccountProvider)
	res, err = controlModel.BillingActionCheck(3333, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass) //Expect pass because GCPAccountProvider match GCP

	// 2.4 config.EnableThirdPartyProviderFromAccountCheck = false
	config.Get().Set(config.EnableThirdPartyProviderFromAccountCheck, false)
	res, err = controlModel.BillingActionCheck(100, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)                                                   //Expect pass because  ThirdPartyProviderFromAccountCheck is disabled
	config.Get().Set(config.EnableThirdPartyProviderFromAccountCheck, true) //reset to default

	// 3. EnableActionCheckOnClosing 为 false 的情况
	config.Get().Set(config.EnableActionCheckOnClosing, false)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo) // Use existing actionInfo
	assert.NoError(err)
	config.Get().Set(config.EnableActionCheckOnClosing, true) // Reset to default

	// 4. EnableActionCheck 为 false 的情况
	config.Get().Set(config.EnableActionCheck, false)
	res, err = controlModel.BillingActionCheck(tenantID, &actionInfo)
	assert.NoError(err)
	assert.True(res.Pass)
	config.Get().Set(config.EnableActionCheck, true) // Reset to default

	// 5. EnableActionCheckProviderMatched 为 false 的情况
	config.Get().Set(config.EnableActionCheckProviderMatched, false)
	actionInfoCreate := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_DedicatedCluster,
			Provider: &provider, //GCP
			IsFree:   false,
		},
	}
	res, err = controlModel.BillingActionCheck(3333, &actionInfoCreate)
	assert.NoError(err)
	assert.True(res.Pass)

	actionInfoDelete := forms.BillingActionInfo{
		Action: forms.BillingAction_Delete,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_DedicatedCluster,
			Provider: &provider, //GCP
			IsFree:   false,
		},
	}
	res, err = controlModel.BillingActionCheck(3333, &actionInfoDelete)
	assert.NoError(err)
	assert.True(res.Pass)

	actionInfoScaleUp := forms.BillingActionInfo{
		Action: forms.BillingAction_Scaleup,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_DedicatedCluster,
			Provider: &provider, //GCP
			IsFree:   false,
		},
	}
	res, err = controlModel.BillingActionCheck(3333, &actionInfoScaleUp)
	assert.NoError(err)
	assert.True(res.Pass)

}

func (suite *ControlTestSuite) TestBillingActionCheck_ServerlessWithReferralCredits() {
	central := &MockCentralHandlerImpl{}
	centralhandler.SetCentralHandler(central)
	config.Get().Set(config.InAPPNotificationEnable, false)
	assert := suite.Assert()
	timeutils.SetMockNow(datainit.BillingDate)

	var tenantID = uint(5001)
	billingConfig, err := datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	assert.NoError(err)

	serverlessAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:   forms.BillingResourceType_ServerlessCluster,
			IsFree: false,
		},
	}

	// no referral credits, no payment -> should fail
	res, err := controlModel.BillingActionCheck(tenantID, &serverlessAction)
	assert.NoError(err)
	assert.False(res.Pass)

	// create referral credits
	now := timeutils.GetNow()
	generalUnitFilter, err := (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "ReferralTest", Description: "ReferralTest"},
		General:        true,
	})
	assert.NoError(err)
	_, err = (&marketing.CreditsPackageModel{}).CreateCreditsPackage(tenantID, &forms.CreditsPackage{
		Usage:                 entity.CreditsPackageUsage_Referral,
		TotalCredits:          decimal.NewFromInt(100),
		StartDate:             now,
		ExpiredDate:           now.AddDate(0, 1, 0),
		UnitFilters:           []*forms.UnitFilterSlim{&generalUnitFilter.UnitFilterSlim},
		BindedBillingConfigID: &billingConfig.BillingConfigID,
	})
	assert.NoError(err)
	assert.NoError((&plan.TenantPlanModel{}).EnableTenantPOCPlanAfterCreditsOpened(tenantID))

	// has referral credits -> should pass for serverless_cluster add
	res, err = controlModel.BillingActionCheck(tenantID, &serverlessAction)
	assert.NoError(err)
	assert.True(res.Pass)

	// serverless_cluster add with referral credits but action is delete -> still pass (delete always allowed for non-closing)
	serverlessAction.Action = forms.BillingAction_Delete
	res, err = controlModel.BillingActionCheck(tenantID, &serverlessAction)
	assert.NoError(err)
	assert.True(res.Pass)
	serverlessAction.Action = forms.BillingAction_Create

	// non-serverless resource with referral credits -> should still fail
	dedicatedAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:   forms.BillingResourceType_DedicatedCluster,
			IsFree: false,
		},
	}
	res, err = controlModel.BillingActionCheck(tenantID, &dedicatedAction)
	assert.NoError(err)
	assert.False(res.Pass)

	// free serverless_cluster -> should pass without referral credits check
	freeServerlessAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:   forms.BillingResourceType_ServerlessCluster,
			IsFree: true,
		},
	}
	res, err = controlModel.BillingActionCheck(tenantID, &freeServerlessAction)
	assert.NoError(err)
	assert.True(res.Pass)
}

func (suite *ControlTestSuite) TestBillingActionCheck_ServerlessWithNonReferralCredits() {
	central := &MockCentralHandlerImpl{}
	centralhandler.SetCentralHandler(central)
	config.Get().Set(config.InAPPNotificationEnable, false)
	assert := suite.Assert()
	timeutils.SetMockNow(datainit.BillingDate)

	var tenantID = uint(5002)
	billingConfig, err := datainit.CreateBillingConfig(tenantID, entity.BillingConfigType_DirectCustomer)
	assert.NoError(err)

	// create non-referral (marketing) credits
	now := timeutils.GetNow()
	generalUnitFilter, err := (&unit_filter.Model{}).CreateUnitFilter(&forms.UnitFilter{
		UnitFilterSlim: forms.UnitFilterSlim{Name: "MarketingTest", Description: "MarketingTest"},
		General:        true,
	})
	assert.NoError(err)
	_, err = (&marketing.CreditsPackageModel{}).CreateCreditsPackage(tenantID, &forms.CreditsPackage{
		Usage:                 entity.CreditsPackageUsage_Marketing,
		TotalCredits:          decimal.NewFromInt(100),
		StartDate:             now,
		ExpiredDate:           now.AddDate(0, 1, 0),
		UnitFilters:           []*forms.UnitFilterSlim{&generalUnitFilter.UnitFilterSlim},
		BindedBillingConfigID: &billingConfig.BillingConfigID,
	})
	assert.NoError(err)
	assert.NoError((&plan.TenantPlanModel{}).EnableTenantPOCPlanAfterCreditsOpened(tenantID))

	// has credits but NOT referral -> should still fail for serverless_cluster add
	serverlessAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:   forms.BillingResourceType_ServerlessCluster,
			IsFree: false,
		},
	}
	res, err := controlModel.BillingActionCheck(tenantID, &serverlessAction)
	assert.NoError(err)
	assert.False(res.Pass)
}

func (suite *ControlTestSuite) TestBillingActionCheck_ServerlessAlicloudThirdParty() {
	central := &MockCentralHandlerImpl{}
	centralhandler.SetCentralHandler(central)
	paymenthandler.SetPaymentHandler(&impl.PaymentHandlerImpl{})
	config.Get().Set(config.EnableActionCheckProviderMatched, true)
	config.Get().Set(config.EnableActionCheckOnBillable, true)
	config.Get().Set(config.EnableActionCheckOnClosing, true)
	config.Get().Set(config.EnableActionCheck, true)
	config.Get().Set(config.InAPPNotificationEnable, false)
	assert := suite.Assert()
	timeutils.SetMockNow(datainit.BillingDate)

	alicloudProvider := forms.Provider_AliCloud
	serverlessAlicloudAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_ServerlessCluster,
			Provider: &alicloudProvider,
			IsFree:   false,
		},
	}

	thirdPartyTenantID := uint(6001)
	thirdPartyBillingConfig, err := datainit.CreateBillingConfig(thirdPartyTenantID, entity.BillingConfigType_DirectCustomer)
	assert.NoError(err)
	isThirdParty := true
	_, err = (&paymentsub.PaymentModel{}).CreatePaymentMethodAndActive(
		thirdPartyTenantID,
		&forms.PaymentMethodCreateQuery{
			PaymentType:           entity.PaymentType_AliCloud,
			BindedBillingConfigID: &thirdPartyBillingConfig.BillingConfigID,
			PaymentMeta:           forms.PaymentMeta{IsThirdParty: &isThirdParty},
		},
	)
	assert.NoError(err)

	assert.NoError((&plan.TenantPlanModel{}).EnableTenantOnDemandPlan(thirdPartyTenantID))
	centralhandler.SetCentralHandler(central)

	res, err := controlModel.BillingActionCheck(thirdPartyTenantID, &serverlessAlicloudAction)
	assert.NoError(err)
	assert.True(res.Pass)

	nonThirdPartyTenantID := uint(6002)
	nonThirdPartyBillingConfig, err := datainit.CreateBillingConfig(nonThirdPartyTenantID, entity.BillingConfigType_DirectCustomer)
	assert.NoError(err)
	isNotThirdParty := false
	_, err = (&paymentsub.PaymentModel{}).CreatePaymentMethodAndActive(
		nonThirdPartyTenantID,
		&forms.PaymentMethodCreateQuery{
			PaymentType:           entity.PaymentType_AliCloud,
			BindedBillingConfigID: &nonThirdPartyBillingConfig.BillingConfigID,
			PaymentMeta:           forms.PaymentMeta{IsThirdParty: &isNotThirdParty},
		},
	)
	assert.NoError(err)
	assert.NoError((&plan.TenantPlanModel{}).EnableTenantOnDemandPlan(nonThirdPartyTenantID))
	centralhandler.SetCentralHandler(central)

	res, err = controlModel.BillingActionCheck(nonThirdPartyTenantID, &serverlessAlicloudAction)
	assert.NoError(err)
	assert.False(res.Pass)
	assert.Equal(control.ServerlessAlicloudNonThirdPartyMsg, *res.Reason)

	serverlessAlicloudAction.Action = forms.BillingAction_Delete
	res, err = controlModel.BillingActionCheck(thirdPartyTenantID, &serverlessAlicloudAction)
	assert.NoError(err)
	assert.True(res.Pass)

	res, err = controlModel.BillingActionCheck(nonThirdPartyTenantID, &serverlessAlicloudAction)
	assert.NoError(err)
	assert.False(res.Pass)

	gcpProvider := forms.Provider_GCP
	serverlessGCPAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_ServerlessCluster,
			Provider: &gcpProvider,
			IsFree:   false,
		},
	}
	res, err = controlModel.BillingActionCheck(nonThirdPartyTenantID, &serverlessGCPAction)
	assert.NoError(err)
	assert.False(res.Pass)

	dedicatedAction := forms.BillingActionInfo{
		Action: forms.BillingAction_Create,
		Resource: forms.BillingResource{
			Type:     forms.BillingResourceType_DedicatedCluster,
			Provider: &alicloudProvider,
			IsFree:   false,
		},
	}
	res, err = controlModel.BillingActionCheck(nonThirdPartyTenantID, &dedicatedAction)
	assert.NoError(err)
	assert.True(res.Pass)
}
