package central

import (
	"fmt"
	"strconv"

	"github.com/gin-gonic/gin"
	centralapi "github.com/tidbcloud/core-svc/idl/pbgen/proto/central"

	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/pkg/grpc"
	coregrpc "github.com/tidbcloud/tidb-management-service/tempo-wrapper/pkg/grpc/core_portal"
	mgmtgrpc "github.com/tidbcloud/tidb-management-service/tempo-wrapper/pkg/grpc/mgmt"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

const (
	defaultClusterNamePrefix = "Cluster"
)

func GenerateName(ctx *gin.Context) {
	req := &centralapi.GenClusterNameReq{}
	err := types.ShouldBindJSON(ctx, req)
	if err != nil {
		types.BadRequestResp(ctx, fmt.Errorf("bind request body failed: %w", err))
		return
	}

	// check org/project id
	orgId, err := strconv.ParseUint(ctx.Param("org_id"), 10, 64)
	if err != nil {
		types.BadRequestResp(ctx, fmt.Errorf("invalid org id: %w", err))
		return
	}
	projectId, err := strconv.ParseUint(ctx.Param("project_id"), 10, 64)
	if err != nil {
		types.BadRequestResp(ctx, fmt.Errorf("invalid project id: %w", err))
		return
	}

	// TDDO: use new open api
	// if ok, err := apiutils.IsNewDedicatedCluster(ctx, clusterId, projectId, orgId); 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
	clusters, err := coregrpc.ListClusters(grpc.NewContext(ctx), &centralapi.ClusterListReq{
		OrgId:     orgId,
		ProjectId: projectId,
	})
	if err != nil {
		types.GrpcErrorResp(ctx, err)
		return
	}

	// serverless
	allow, err := apiutils.IsServerlessAllow(ctx, orgId)
	if err != nil {
		types.InternalErrorResp(ctx, err)
		return
	}
	if allow {
		serverlessClusters, err := mgmtgrpc.ListServerlessClusters(
			grpc.NewContext(ctx),
			&openapiserverlessv1beta1.ListClustersRequest{
				// ProjectId: projectId,
				Filter: fmt.Sprintf("projectId = %d", projectId),
			},
		)
		if err != nil {
			types.GrpcErrorResp(ctx, err)
			return
		}
		clusters.Total += int32(serverlessClusters.TotalSize)
		clusters.Items = append(
			clusters.Items,
			convertListServerlessClustersResp(ctx.Request.Context(), serverlessClusters).Items...)
	}

	// gen names
	var name string
	for i := 0; ; i++ {
		exist := false
		_name := defaultClusterNamePrefix + strconv.Itoa(i)
		for _, cluster := range clusters.Items {
			if cluster.Name == _name {
				exist = true
				break
			}
		}
		if !exist {
			name = _name
			break
		}
	}
	resp := &centralapi.GenClusterNameResp{
		Name: name,
		BaseResp: &centralapi.BaseResp{
			ErrCode: int64(bizerr.ErrCodeOK),
			ErrMsg:  "",
		},
	}
	types.SuccessResp(ctx, resp)
}
