package grpcli

import (
	"context"

	"github.com/tidbcloud/dataflow-service/pkg/log"
	"github.com/tidbcloud/pkgv2/bizerr"
	globalv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/dedicated/v1"
	"go.uber.org/zap"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/status"
)

const _maxGrpcCode codes.Code = 17

// CompatibleCrGrpcClient get partial information about network from dedicated global service
// It's used to be compatible with dedicated migration, and is just a temporary interface
type CompatibleCrGrpcClient interface {
	GetNetwork(ctx context.Context, req *globalv1.GetCompatNetworkRequest) (*globalv1.CompatNetwork, bizerr.BizError)
	GetCluster(ctx context.Context, req *globalv1.GetCompatClusterRequest) (*globalv1.CompatCluster, bizerr.BizError)
}

type compatibleCrGrpcClientImpl struct {
	client globalv1.DataPlatformCompatServiceClient
}

func newCompatibleCrGrpcClientImpl(ctx context.Context, addr string) CompatibleCrGrpcClient {
	logger := log.GetLogger(ctx)
	logger.Info("initializing compat service client", zap.String("addr", addr))

	conn := MustBuildGrpcClientConnection(ctx, addr)
	client := globalv1.NewDataPlatformCompatServiceClient(conn)
	return &compatibleCrGrpcClientImpl{
		client: client,
	}
}

func (c *compatibleCrGrpcClientImpl) GetNetwork(
	ctx context.Context, req *globalv1.GetCompatNetworkRequest,
) (*globalv1.CompatNetwork, bizerr.BizError) {
	network, err := c.client.GetCompatNetwork(ctx, req)
	if err != nil {
		return nil, globalServiceError2BizError(err)
	}
	return network, nil
}

func (c *compatibleCrGrpcClientImpl) GetCluster(
	ctx context.Context, req *globalv1.GetCompatClusterRequest,
) (*globalv1.CompatCluster, bizerr.BizError) {
	cluster, err := c.client.GetCompatCluster(ctx, req)
	if err != nil {
		return nil, globalServiceError2BizError(err)
	}
	return cluster, nil
}

func globalServiceError2BizError(err error) bizerr.BizError {
	if err == nil {
		return nil
	}

	if s, ok := status.FromError(err); ok {
		if s.Code() > _maxGrpcCode {
			// if the code is not grpc code, it's bizerr code
			return bizerr.Restore(bizerr.ErrCode(s.Code()), s.Message())
		}
	}
	return bizerr.WrapGrpcError(err, "grpc error")
}
