package v1beta

import (
	"github.com/gin-gonic/gin"
	"github.com/samber/lo"
	openapilegacy "github.com/tidbcloud/idl/pbgen/proto/openapi/cm"

	openapicommonv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/common/v1beta1"
	openapiserverlessv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/serverless/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tempo-wrapper/internal/api/types"
	apiutils "github.com/tidbcloud/tidb-management-service/tempo-wrapper/internal/api/utils"
	"github.com/tidbcloud/tidb-management-service/tempo-wrapper/internal/auth"
	"github.com/tidbcloud/tidb-management-service/tempo-wrapper/pkg/grpc"
	mgmtgrpc "github.com/tidbcloud/tidb-management-service/tempo-wrapper/pkg/grpc/mgmt"
	openapigrpc "github.com/tidbcloud/tidb-management-service/tempo-wrapper/pkg/grpc/openapi"
)

func ListRegions(ctx *gin.Context) {
	// TDDO: use new open api
	// if ok, err := apiutils.IsDedicatedAllow(ctx, orgId, projectId); err != nil {
	// 	types.InternalErrorResp(ctx, fmt.Errorf("check cluster failed: %w", err))
	// 	return
	// } else if ok {
	// 	types.SuccessResp(ctx, &emptypb.Empty{})
	// 	return
	// }

	// core-portal will split traffic to dedicated global
	// https://github.com/tidbcloud/core-svc/pull/1316
	// OpenAPI
	resp, err := openapigrpc.ListOpenAPIRegion(grpc.NewContext(ctx))
	if err != nil {
		types.OpenAPIErrorResp(ctx, err)
		return
	}

	// add serverless region
	orgId, err := auth.GetOrgIDByHeader(ctx)
	if err != nil {
		types.OpenAPIInvalidArgumentResp(ctx, err)
		return
	}

	allow, err := apiutils.IsServerlessAllow(ctx, orgId)
	if err != nil {
		types.OpenAPIInternalErrorResp(ctx, err)
		return
	}
	if allow {
		// filter serverless
		resp.Items = lo.Filter(resp.Items, func(item *openapilegacy.ListProviderRegionsItem, _ int) bool {
			return item.ClusterType != openapilegacy.ClusterType_DEVELOPER
		})

		// tidb management service
		serverlessResp, err := mgmtgrpc.ListServerlessRegions(grpc.NewContext(ctx))
		if err != nil {
			types.OpenAPIErrorResp(ctx, err)
			return
		}

		// filter serverless
		resp.Items = append(resp.Items, convertServerlessListRegionResp(serverlessResp).Items...)
	}

	types.SuccessResp(ctx, resp)
}

const serverlessNodeSize = "Shared0"

func convertServerlessListRegionResp(
	r *openapiserverlessv1beta1.ListRegionsResponse,
) *openapilegacy.ListProviderRegionsResp {
	resp := &openapilegacy.ListProviderRegionsResp{
		Items: make([]*openapilegacy.ListProviderRegionsItem, 0, len(r.Regions)),
	}

	// provider
	for _, region := range r.Regions {
		// only return aws region for serverless legacy openapi
		if region.CloudProvider != openapicommonv1beta1.Region_aws {
			continue
		}

		resp.Items = append(resp.Items, &openapilegacy.ListProviderRegionsItem{
			ClusterType:   openapilegacy.ClusterType_DEVELOPER,
			CloudProvider: openapilegacy.CloudProvider(region.CloudProvider),
			Region:        apiutils.ConvertRegionName(region.Name),

			Tidb: []*openapilegacy.TiDBProfile{
				{
					NodeSize:          serverlessNodeSize,
					NodeQuantityRange: &openapilegacy.NodeQuantityRange{Min: 1, Step: 1},
				},
			},
			Tikv: []*openapilegacy.TiKVProfile{
				{
					NodeSize:            serverlessNodeSize,
					NodeQuantityRange:   &openapilegacy.NodeQuantityRange{Min: 1, Step: 1},
					StorageSizeGibRange: &openapilegacy.NodeStorageSizeRange{Min: 1, Max: 1},
				},
			},
			Tiflash: []*openapilegacy.TiFlashProfile{
				{
					NodeSize:            serverlessNodeSize,
					NodeQuantityRange:   &openapilegacy.NodeQuantityRange{Min: 1, Step: 1},
					StorageSizeGibRange: &openapilegacy.NodeStorageSizeRange{Min: 1, Max: 1},
				},
			},
		})
	}
	return resp
}
