package region

import (
	"context"
	"testing"

	. "github.com/onsi/gomega"
	"github.com/samber/lo"
	"github.com/stretchr/testify/require"
	"gorm.io/gorm"

	globalcommonv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/common/v1"
	globalngv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/domain/entity"
	clusterrepoimpl "github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/cluster"
	regionrepoimpl "github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/region"
	"github.com/tidbcloud/tidb-management-service/nextgen-global-service/infra/repoimpl/schema"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/idgenerator"
)

func TestRegisterRegion(t *testing.T) {
	g := NewWithT(t)
	dbPvd := *dbProvider.Load()
	regionRepo := regionrepoimpl.NewRegionRepo(dbPvd)

	providerIdentityRepo := regionrepoimpl.NewRegionProviderIdentityRepo(dbPvd)
	idGeneratorAdapter := idgenerator.NewSonyflakeID(1, "")

	svc := NewService(regionRepo, nil, providerIdentityRepo, nil, nil, dbPvd, nil, idGeneratorAdapter, nil, nil)

	tests := []struct {
		name    string
		req     *globalngv1.RegisterRegionRequest
		wantErr bool
		ErrCode bizerr.ErrCode
		want    *entity.Region
	}{
		{
			name: "cloud provider is not supported",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_ALICLOUD_AP_SOUTHEAST_1,
					LogicalName:     "ap-southeast-1-t0",
					CloudProviderId: globalcommonv1.CloudProvider_ALICLOUD,
					ServicePlan:     globalcommonv1.ServicePlan_BYOC,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{Identity: "test4"},
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeRecordNotFound,
		},
		{
			name: "region is exist",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-a0",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					OpenedTenantIds: []uint64{1, 2, 3},
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{Identity: "test5"},
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeRecordExist,
		},
		{
			name: "register unpublic region",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t0",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					OpenedTenantIds: []uint64{1, 2, 3},
					SortPriority:    100,
					IsPublic:        false,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{Identity: "test6"},
				},
			},
			want: &entity.Region{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-axxx",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					OpenedTenantIds: []uint64{1, 2, 3},
					SortPriority:    100,
					IsPublic:        false,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
			},
		},
		{
			name: "register public region",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t1",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{Identity: "test7"},
				},
			},
			want: &entity.Region{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t1",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
			},
		},
		{
			name: "register public region with provider identities",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t2",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{
						Identity: "identity111",
					},
				},
			},
			want: &entity.Region{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t1",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
			},
		},
		{
			name: "cloud provider is not active",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_ALICLOUD_AP_NORTHEAST_1,
					LogicalName:     "ap-northeast-1-t0",
					CloudProviderId: globalcommonv1.CloudProvider_ALICLOUD,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{Identity: "test8"},
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeParams,
		},
		{
			name: "register region with multiple default identities should fail",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-multi-default",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{
						Identity:  "default-identity-1",
						IsDefault: true,
					},
					{
						Identity:  "default-identity-2",
						IsDefault: true,
					},
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeParams,
		},
		{
			name: "register region with default provider identity",
			req: &globalngv1.RegisterRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t3",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
				RegionProviderIdentities: []*globalngv1.RegionProviderIdentity{
					{
						Identity:  "default-identity-123",
						IsDefault: true,
					},
					{
						Identity:  "regular-identity-456",
						IsDefault: false,
					},
				},
			},
			want: &entity.Region{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t3",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			region, err := svc.RegisterRegion(t.Context(), test.req)
			if test.wantErr {
				g.Expect(err).Should(HaveOccurred())
				bizErr, ok := err.(*bizerr.BizErr)
				g.Expect(ok).To(BeTrue())
				g.Expect(bizErr.ErrCode()).To(Equal(test.ErrCode))
			} else {
				g.Expect(err).Should(BeNil())
				g.Expect(region.RegionID).ShouldNot(BeZero())
				g.Expect(region.ProviderID).ShouldNot(BeZero())
				g.Expect(region.RegionLogicalName).Should(Equal(test.req.GetRegion().GetLogicalName()))
				g.Expect(region.Region.DisplayName).Should(Equal(test.req.GetRegion().GetDisplayName()))
				g.Expect(region.Region.OpenedTenantIds).Should(Equal(test.req.GetRegion().GetOpenedTenantIds()))
				g.Expect(region.Region.SortPriority).Should(Equal(test.req.GetRegion().GetSortPriority()))
				g.Expect(region.Region.IsPublic).Should(Equal(test.req.GetRegion().GetIsPublic()))
				g.Expect(region.Region.State).Should(Equal(test.req.GetRegion().GetState()))
				g.Expect(region.Region.ServicePlan).Should(Equal(test.req.GetRegion().GetServicePlan()))
				g.Expect(region.Region.ServiceAddress).Should(Equal(test.req.GetRegion().GetServiceAddress()))

				var regionModel schema.Region
				dbPvd.ReadDB(t.Context()).
					Model(&schema.Region{}).
					Where("`regions`.`id` = ? and `regions`.`name` = ? and `regions`.`service_plan` = ?", region.RegionID, region.RegionLogicalName, region.Region.ServicePlan.String()).
					Take(&regionModel)
				g.Expect(regionModel.Name).Should(Equal(region.RegionLogicalName))
				g.Expect(regionModel.RegionName).Should(Equal(test.req.GetRegion().GetId().String()))
				g.Expect(regionModel.DisplayName).Should(Equal(test.req.GetRegion().GetDisplayName()))
				g.Expect(regionModel.Priority).Should(Equal(test.req.GetRegion().GetSortPriority()))
				g.Expect(lo.FromPtr(regionModel.IsPublic)).Should(Equal(test.req.GetRegion().GetIsPublic()))
				g.Expect(regionModel.Status).Should(Equal(test.req.GetRegion().GetState().String()))
				g.Expect(regionModel.ServicePlan).Should(Equal(test.req.GetRegion().GetServicePlan().String()))
				g.Expect(regionModel.ServiceAddress).Should(Equal(test.req.GetRegion().GetServiceAddress()))
				var regionTenants []schema.RegionTenant
				dbPvd.ReadDB(t.Context()).
					Model(&schema.RegionTenant{}).
					Where("`region_tenants`.`region_id` = ?", region.RegionID).
					Find(&regionTenants)
				g.Expect(len(regionTenants)).Should(Equal(len(test.req.GetRegion().GetOpenedTenantIds())))
				for _, tenantId := range test.req.GetRegion().GetOpenedTenantIds() {
					g.Expect(lo.ContainsBy(regionTenants, func(each schema.RegionTenant) bool {
						return each.TenantId == tenantId
					})).Should(BeTrue())
				}

				// Verify default provider identities are created correctly
				for _, identity := range test.req.GetRegionProviderIdentities() {
					if identity.GetIsDefault() {
						var defaultIdentities []schema.DefaultProviderIdentity
						dbPvd.ReadDB(t.Context()).Model(&schema.DefaultProviderIdentity{}).
							Where("`default_provider_identities`.`provider_id` = ?", region.ProviderID).
							Where("`default_provider_identities`.`service_plan` = ?", region.ServicePlan.String()).
							Where("`default_provider_identities`.`region_id` = ?", region.RegionID).
							Where("`default_provider_identities`.`tenant_id` = ?", uint64(0)).
							Where("`default_provider_identities`.`identity` = ?", identity.GetIdentity()).
							Find(&defaultIdentities)
						g.Expect(defaultIdentities).Should(HaveLen(1), "Default provider identity should be created for is_default=true")
					}
				}
			}
		})
	}
}

func TestNormalizeServicePlans(t *testing.T) {
	g := NewWithT(t)

	region := &globalcommonv1.Region{
		ServicePlan: globalcommonv1.ServicePlan_Premium,
		RegionWhiteLists: []*globalcommonv1.RegionWhiteList{
			{ServicePlan: globalcommonv1.ServicePlan_BYOC},
			{ServicePlan: globalcommonv1.ServicePlan_BYOC},
		},
	}
	g.Expect(normalizeServicePlans(region)).To(Equal([]globalcommonv1.ServicePlan{globalcommonv1.ServicePlan_BYOC}))

	region.RegionWhiteLists = nil
	g.Expect(normalizeServicePlans(region)).To(Equal([]globalcommonv1.ServicePlan{globalcommonv1.ServicePlan_Premium}))

	g.Expect(normalizeServicePlans(&globalcommonv1.Region{})).To(BeEmpty())
}

func TestUpdateRegion(t *testing.T) {
	g := NewWithT(t)
	dbPvd := *dbProvider.Load()
	regionRepo := regionrepoimpl.NewRegionRepo(dbPvd)

	providerIdentityRepo := regionrepoimpl.NewRegionProviderIdentityRepo(dbPvd)
	idGeneratorAdapter := idgenerator.NewSonyflakeID(1, "")

	svc := NewService(regionRepo, nil, providerIdentityRepo, nil, nil, dbPvd, nil, idGeneratorAdapter, nil, nil)

	tests := []struct {
		name    string
		initFn  func()
		req     *globalngv1.UpdateRegionRequest
		wantErr bool
		ErrCode bizerr.ErrCode
		want    *entity.Region
	}{
		{
			name: "logical name is empty",
			req: &globalngv1.UpdateRegionRequest{
				Region: &globalcommonv1.Region{
					Id:          globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName: "",
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeParams,
		},
		{
			name: "cloud provider is not supported",
			req: &globalngv1.UpdateRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_ALICLOUD_AP_NORTHEAST_1,
					LogicalName:     "ap-northeast-1-t0",
					CloudProviderId: globalcommonv1.CloudProvider_ALICLOUD,
					ServicePlan:     globalcommonv1.ServicePlan_BYOC,
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeRecordNotFound,
		},
		{
			name: "region is not found",
			req: &globalngv1.UpdateRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-t-xxxxxxxxx",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
				},
			},
			wantErr: true,
			ErrCode: bizerr.ErrCodeRecordNotFound,
		},
		{
			initFn: func() {
				dbPvd.WriteDB(t.Context()).Model(&schema.Region{}).Create(
					&schema.Region{
						Model: gorm.Model{
							ID: 900001,
						},
						Name:        "us-west-2-x1",
						RegionName:  "us-west-2",
						ProviderId:  1,
						DisplayName: "US West 2",
						CountryCode: "US",
						Area:        "Americas",
						Priority:    100,
						Status:      "active",
						IsPublic:    lo.ToPtr(false),
						ServicePlan: "Premium",
					},
				)
				dbPvd.WriteDB(t.Context()).Model(&schema.RegionTenant{}).Create(
					&schema.RegionTenant{
						RegionId: 900001,
						TenantId: 1,
					},
				)
				dbPvd.WriteDB(t.Context()).Model(&schema.RegionTenant{}).Create(
					&schema.RegionTenant{
						RegionId: 900001,
						TenantId: 2,
					},
				)
				dbPvd.WriteDB(t.Context()).Model(&schema.RegionTenant{}).Create(
					&schema.RegionTenant{
						RegionId: 900001,
						TenantId: 3,
					},
				)
			},
			name: "update region success",
			req: &globalngv1.UpdateRegionRequest{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-x1",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
					DisplayName:     "US West 2",
					OpenedTenantIds: []uint64{1, 2, 3},
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
				},
			},
			want: &entity.Region{
				Region: &globalcommonv1.Region{
					Id:              globalcommonv1.Region_AWS_US_WEST_2,
					LogicalName:     "us-west-2-x1",
					CloudProviderId: globalcommonv1.CloudProvider_AWS,
					DisplayName:     "US West 2",
					SortPriority:    100,
					IsPublic:        true,
					State:           globalcommonv1.Region_ACTIVE,
					ServicePlan:     globalcommonv1.ServicePlan_Premium,
					OpenedTenantIds: []uint64{1, 2, 3},
				},
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if test.initFn != nil {
				test.initFn()
			}
			region, err := svc.UpdateRegion(t.Context(), test.req)
			if test.wantErr {
				g.Expect(err).Should(HaveOccurred())
				bizErr, ok := err.(*bizerr.BizErr)
				g.Expect(ok).To(BeTrue())
				g.Expect(bizErr.ErrCode()).To(Equal(test.ErrCode))
			}
			if test.want != nil {
				g.Expect(region.RegionID).ShouldNot(BeZero())
				g.Expect(region.ProviderID).ShouldNot(BeZero())
				g.Expect(region.RegionLogicalName).Should(Equal(test.want.LogicalName))
				g.Expect(region.Region.DisplayName).Should(Equal(test.want.DisplayName))
				g.Expect(region.Region.SortPriority).Should(Equal(test.want.SortPriority))
				g.Expect(region.Region.IsPublic).Should(Equal(test.want.IsPublic))
				g.Expect(region.Region.State).Should(Equal(test.want.State))
				g.Expect(region.Region.ServicePlan).Should(Equal(test.want.ServicePlan))
				g.Expect(region.Region.ServiceAddress).Should(Equal(test.want.ServiceAddress))
				var regionTenants []schema.RegionTenant
				dbPvd.ReadDB(t.Context()).
					Model(&schema.RegionTenant{}).
					Where("`region_tenants`.`region_id` = ?", region.RegionID).
					Find(&regionTenants)
				g.Expect(len(regionTenants)).Should(Equal(len(test.want.OpenedTenantIds)))
				for _, tenantId := range test.want.OpenedTenantIds {
					g.Expect(lo.ContainsBy(regionTenants, func(each schema.RegionTenant) bool {
						return each.TenantId == tenantId
					})).Should(BeTrue())
				}
			}
		})
	}
}

func TestUpdateRegion_RestoresSoftDeletedDefaultProviderIdentity(t *testing.T) {
	g := NewWithT(t)
	dbPvd := *dbProvider.Load()
	regionRepo := regionrepoimpl.NewRegionRepo(dbPvd)
	providerIdentityRepo := regionrepoimpl.NewRegionProviderIdentityRepo(dbPvd)
	idGeneratorAdapter := idgenerator.NewSonyflakeID(1, "")

	svc := NewService(regionRepo, nil, providerIdentityRepo, nil, nil, dbPvd, nil, idGeneratorAdapter, nil, nil)
	ctx := context.Background()

	regionModel := &schema.Region{
		Model:       gorm.Model{ID: 900101},
		Name:        "us-west-2-soft-delete-default",
		RegionName:  globalcommonv1.Region_AWS_US_WEST_2.String(),
		ProviderId:  1,
		DisplayName: "US West 2",
		CountryCode: "US",
		Area:        "Americas",
		Priority:    100,
		Status:      "active",
		IsPublic:    lo.ToPtr(false),
		ServicePlan: "Premium",
	}
	require.NoError(t, dbPvd.WriteDB(ctx).Create(regionModel).Error)
	t.Cleanup(func() {
		require.NoError(t, dbPvd.WriteDB(ctx).Unscoped().Delete(&schema.DefaultProviderIdentity{}, "region_id = ?", regionModel.ID).Error)
		require.NoError(t, dbPvd.WriteDB(ctx).Unscoped().Delete(&schema.ProviderIdentity{}, "region_id = ?", regionModel.ID).Error)
		require.NoError(t, dbPvd.WriteDB(ctx).Unscoped().Delete(&schema.RegionTenant{}, "region_id = ?", regionModel.ID).Error)
		require.NoError(t, dbPvd.WriteDB(ctx).Unscoped().Delete(&schema.RegionServicePlan{}, "region_id = ?", regionModel.ID).Error)
		require.NoError(t, dbPvd.WriteDB(ctx).Unscoped().Delete(&schema.Region{}, "id = ?", regionModel.ID).Error)
	})

	providerIdentity := &schema.ProviderIdentity{
		ID:       900102,
		RegionId: uint64(regionModel.ID),
		Identity: "013690006788",
	}
	require.NoError(t, dbPvd.WriteDB(ctx).Create(providerIdentity).Error)

	defaultIdentity := &schema.DefaultProviderIdentity{
		ProviderId:  regionModel.ProviderId,
		ServicePlan: "Premium",
		RegionId:    uint64(regionModel.ID),
		TenantId:    1369847559691367379,
		Identity:    providerIdentity.Identity,
	}
	require.NoError(t, dbPvd.WriteDB(ctx).Create(defaultIdentity).Error)

	updatedRegion, err := svc.UpdateRegion(ctx, &globalngv1.UpdateRegionRequest{
		Region: &globalcommonv1.Region{
			Id:              globalcommonv1.Region_AWS_US_WEST_2,
			LogicalName:     regionModel.Name,
			CloudProviderId: globalcommonv1.CloudProvider_AWS,
			ServicePlan:     globalcommonv1.ServicePlan_Premium,
			DisplayName:     regionModel.DisplayName,
			OpenedTenantIds: []uint64{1369847559691367379},
			SortPriority:    100,
			IsPublic:        false,
			State:           globalcommonv1.Region_ACTIVE,
		},
		DefaultProviderIdentities: []*globalngv1.DefaultRegionProviderIdentity{
			{
				TenantId:    1369847559691367379,
				Identity:    providerIdentity.Identity,
				ServicePlan: globalcommonv1.ServicePlan_Premium,
			},
		},
	})
	require.NoError(t, err)
	g.Expect(updatedRegion.RegionID).To(Equal(uint64(regionModel.ID)))

	var activeDefaults []schema.DefaultProviderIdentity
	require.NoError(t, dbPvd.ReadDB(ctx).
		Model(&schema.DefaultProviderIdentity{}).
		Where("provider_id = ? AND service_plan = ? AND region_id = ? AND tenant_id = ? AND identity = ?",
			regionModel.ProviderId, "Premium", regionModel.ID, uint64(1369847559691367379), providerIdentity.Identity).
		Find(&activeDefaults).Error)
	g.Expect(activeDefaults).To(HaveLen(1))

	var stored schema.DefaultProviderIdentity
	require.NoError(t, dbPvd.ReadDB(ctx).
		Unscoped().
		Where("provider_id = ? AND service_plan = ? AND region_id = ? AND tenant_id = ?",
			regionModel.ProviderId, "Premium", regionModel.ID, uint64(1369847559691367379)).
		First(&stored).Error)
	g.Expect(stored.DeletedAt.Valid).To(BeFalse())
	g.Expect(stored.Identity).To(Equal(providerIdentity.Identity))
}

func TestDeleteRegion(t *testing.T) {
	g := NewWithT(t)
	dbPvd := *dbProvider.Load()
	regionRepo := regionrepoimpl.NewRegionRepo(dbPvd)
	clusterRepo := clusterrepoimpl.NewClusterRepo(dbPvd)

	providerIdentityRepo := regionrepoimpl.NewRegionProviderIdentityRepo(dbPvd)
	idGeneratorAdapter := idgenerator.NewSonyflakeID(1, "")

	svc := NewService(regionRepo, clusterRepo, providerIdentityRepo, nil, nil, dbPvd, nil, idGeneratorAdapter, nil, nil)

	tests := []struct {
		name     string
		initFn   func()
		req      *globalngv1.DeleteRegionRequest
		outputFn func(err bizerr.BizError)
	}{
		{
			name: "region is not found",
			req: &globalngv1.DeleteRegionRequest{
				RegionLogicalName: "us-west-2-t-xxxxxxxxx",
			},
			outputFn: func(err bizerr.BizError) {
				g.Expect(err.ErrCode()).To(Equal(bizerr.ErrCodeRecordNotFound))
			},
		},
		{
			name: "region is not in cloud provider",
			req: &globalngv1.DeleteRegionRequest{
				RegionLogicalName: "us-west-2-a0",
				CloudProviderId:   globalcommonv1.CloudProvider_ALICLOUD,
			},
			outputFn: func(err bizerr.BizError) {
				g.Expect(err.ErrCode()).To(Equal(bizerr.ErrCodeParams))
				g.Expect(err.ErrMsg()).To(ContainSubstring("region us-west-2-a0 is not in cloud provider alicloud"))
			},
		},
		{
			name: "region is public",
			req: &globalngv1.DeleteRegionRequest{
				RegionLogicalName: "us-west-2-a0",
				CloudProviderId:   globalcommonv1.CloudProvider_AWS,
			},
			outputFn: func(err bizerr.BizError) {
				g.Expect(err.ErrCode()).To(Equal(bizerr.ErrCodeParams))
				g.Expect(err.ErrMsg()).To(ContainSubstring("public region us-west-2-a0 can not be deleted"))
			},
		},
		{
			name: "cluster is exist",
			req: &globalngv1.DeleteRegionRequest{
				RegionLogicalName: "us-west-2-90002",
				CloudProviderId:   globalcommonv1.CloudProvider_AWS,
			},
			initFn: func() {
				dbPvd.WriteDB(t.Context()).Model(&schema.Region{}).Create(
					&schema.Region{
						Model: gorm.Model{
							ID: 900002,
						},
						Name:        "us-west-2-90002",
						RegionName:  "us-west-2",
						ProviderId:  1,
						DisplayName: "US West 2",
						CountryCode: "US",
						Area:        "Americas",
						Priority:    100,
						Status:      "active",
						IsPublic:    lo.ToPtr(false),
						ServicePlan: "Premium",
					},
				)
				dbPvd.WriteDB(t.Context()).Model(&schema.Cluster{}).Create(
					&schema.Cluster{
						ID:         900001,
						RegionId:   900002,
						ProviderId: 1,
						TenantId:   3,
						Attributes: schema.ClusterAttributes{},
					},
				)
			},
			outputFn: func(err bizerr.BizError) {
				g.Expect(err.ErrCode()).To(Equal(bizerr.ErrCodeParams))
				g.Expect(err.ErrMsg()).To(ContainSubstring("region us-west-2-90002 is used by cluster 900001"))
			},
		},
		{
			name: "delete region success",
			req: &globalngv1.DeleteRegionRequest{
				RegionLogicalName: "us-west-2-90002",
				CloudProviderId:   globalcommonv1.CloudProvider_AWS,
			},
			initFn: func() {
				dbPvd.WriteDB(t.Context()).Model(&schema.Cluster{}).Delete(&schema.Cluster{
					ID: 900001,
				})
			},
			outputFn: func(err bizerr.BizError) {
				g.Expect(err).Should(BeNil())
				dberr := dbPvd.ReadDB(t.Context()).
					Model(&schema.Region{}).
					Where("`regions`.`name` = ?", "us-west-2-90002").
					Take(&schema.Region{}).
					Error
				g.Expect(dberr).Should(HaveOccurred())
				g.Expect(dberr.Error()).To(ContainSubstring("record not found"))
			},
		},
	}

	for _, test := range tests {
		t.Run(test.name, func(t *testing.T) {
			if test.initFn != nil {
				test.initFn()
			}
			_, err := svc.DeleteRegion(t.Context(), test.req)
			if test.outputFn != nil {
				test.outputFn(err)
			}
		})
	}
}
