package cluster

import (
	"context"
	"errors"

	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
	"gorm.io/gorm"

	tidbmgmtservicev1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-service/pkg/apimiddleware/bizerror"
	"github.com/tidbcloud/tidb-management-service/utilities/bizerr"
)

func (c *serverImpl) AddClusterLabels(
	ctx context.Context,
	request *tidbmgmtservicev1.AddClusterLabelsRequest,
) (*tidbmgmtservicev1.Cluster, error) {
	if request == nil {
		return nil, bizerr.New(bizerr.ErrCodeParams, "request is nil")
	}
	if request.GetClusterId() == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "cluster_id is required")
	}
	if len(request.GetLabels()) == 0 {
		return nil, bizerr.New(bizerr.ErrCodeParams, "labels is empty")
	}

	_, err := c.clusterRepo.GetCluster(ctx, request.GetClusterId(), false)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, bizerror.NewNotFound(err, "cluster not found")
		}
		return nil, bizerror.NewInternal(err, "failed to get cluster")
	}

	if err = c.clusterRepo.UpdateLabels(ctx, request.GetClusterId(), request.GetLabels()); err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, bizerror.NewNotFound(err, "cluster not found")
		}
		return nil, bizerror.NewInternal(err, "failed to add cluster labels")
	}

	cluster, err := c.clusterRepo.GetCluster(ctx, request.GetClusterId(), false)
	if err != nil {
		if errors.Is(err, gorm.ErrRecordNotFound) {
			return nil, bizerror.NewNotFound(err, "cluster not found")
		}
		return nil, bizerror.NewInternal(err, "failed to get cluster after adding labels")
	}

	cstatus, err := c.customStatusSvc.ListClusterCustomStatus(ctx, []uint64{cluster.ClusterId}, nil, false)
	if err != nil {
		return nil, status.Error(codes.Internal, err.Error())
	}

	return cvtToMgmtCluster(cluster, cstatus[cluster.ClusterId]), nil
}
