package tidbgroup

import (
	"context"
	"strconv"

	globaldedicatedv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	openapidedicatedv1beta1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_cloud_open_api/dedicated/v1beta1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/bizerror"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/common"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
	"github.com/tidbcloud/tidb-management-service/utilities/grpc/metadata"
)

func (s serverImpl) ListTidbNodeGroups(
	ctx context.Context,
	req *openapidedicatedv1beta1.ListTidbNodeGroupsRequest,
) (*openapidedicatedv1beta1.ListTidbNodeGroupsResponse, error) {
	ctx, span := tracer.Start(ctx, "ListTidbNodeGroups")
	defer span.End()

	// Extract request meta.
	_, err := metadata.ExtractRequestMetaWithCheckPermission(ctx)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "failed to extract request metadata")
	}

	// Validate request.
	clusterId, err := strconv.ParseUint(req.GetClusterId(), 10, 64)
	if err != nil {
		return nil, bizerr.WrapErrorWithCode(err, bizerr.ErrCodeParams, "invalid cluster id")
	}

	// get cluster info from domain
	tidbGroups, err := s.dedicatedCli.ListTidbNodeGroups(ctx, &globaldedicatedv1.ListTidbNodeGroupsRequest{
		ClusterIds:  []uint64{clusterId},
		ShowDetails: true,
	})
	if err != nil {
		return nil, bizerror.NewInternal(err, "failed to list cluster tidb node group")
	}

	if len(tidbGroups.GetTidbNodeGroups()) == 0 {
		return nil, bizerror.NewNotFound(nil, "tidb node group not found")
	}

	// Build response.
	var groups []*openapidedicatedv1beta1.TidbNodeGroup
	for _, globalGroup := range tidbGroups.GetTidbNodeGroups() {
		groups = append(groups, cvtGlobalToTidbNodeGroup(globalGroup))
	}

	pagedGroups, nextToken, err := common.LocalPagination(
		groups,
		req,
		common.ListDefaultPageSize,
		common.ListMaxPageSize,
	)
	if err != nil {
		return nil, bizerror.NewInternal(err, "failed to paginate node specs")
	}

	return &openapidedicatedv1beta1.ListTidbNodeGroupsResponse{
		TidbNodeGroups: pagedGroups,
		TotalSize:      int32(len(groups)),
		NextPageToken:  nextToken,
	}, nil
}
