package dataplanemgr

import (
	"fmt"
	"time"

	dplanemgrv1 "github.com/tidbcloud/cluster-service-ng/api/dataplane-manager/v1"
	grpcutils "github.com/tidbcloud/cluster-service-ng/pkg/grpc"
	tigrpcclient "github.com/tidbcloud/tiinf/transport/tigrpc/client"
)

type Client interface {
	dplanemgrv1.DataPlaneServiceClient
	dplanemgrv1.BucketServiceClient
	dplanemgrv1.PrivateLinkConnectionServiceClient
	dplanemgrv1.LoadBalancerServiceClient
	dplanemgrv1.KeyspaceRoleServiceClient
	GetDataPlaneServiceClient() dplanemgrv1.DataPlaneServiceClient
	GetBucketServiceClient() dplanemgrv1.BucketServiceClient
	GetPrivateLinkConnectionServiceClient() dplanemgrv1.PrivateLinkConnectionServiceClient
	GetLoadBalancerServiceClient() dplanemgrv1.LoadBalancerServiceClient
	GetKeyspaceRoleServiceClient() dplanemgrv1.KeyspaceRoleServiceClient
}

type client struct {
	dplanemgrv1.DataPlaneServiceClient
	dplanemgrv1.BucketServiceClient
	dplanemgrv1.PrivateLinkConnectionServiceClient
	dplanemgrv1.LoadBalancerServiceClient
	dplanemgrv1.KeyspaceRoleServiceClient
}

func (c *client) GetDataPlaneServiceClient() dplanemgrv1.DataPlaneServiceClient {
	return c.DataPlaneServiceClient
}

func (c *client) GetBucketServiceClient() dplanemgrv1.BucketServiceClient {
	return c.BucketServiceClient
}

func (c *client) GetPrivateLinkConnectionServiceClient() dplanemgrv1.PrivateLinkConnectionServiceClient {
	return c.PrivateLinkConnectionServiceClient
}

func (c *client) GetLoadBalancerServiceClient() dplanemgrv1.LoadBalancerServiceClient {
	return c.LoadBalancerServiceClient
}

func (c *client) GetKeyspaceRoleServiceClient() dplanemgrv1.KeyspaceRoleServiceClient {
	return c.KeyspaceRoleServiceClient
}

func NewClient(dataPlaneManagerAddr string) (Client, error) {
	dataplaneMgrConn, err := tigrpcclient.NewClientConn(
		dataPlaneManagerAddr,
		tigrpcclient.WithDefault(),
		tigrpcclient.WithUnaryInterceptors(
			grpcutils.ClientPayloadLogInterceptor,
			grpcutils.CallingTimeoutInterceptor(5*time.Second),
		),
	)
	if err != nil {
		return nil, fmt.Errorf("failed to create dataplane manager client connection: %w", err)
	}

	return &client{
		DataPlaneServiceClient:             dplanemgrv1.NewDataPlaneServiceClient(dataplaneMgrConn),
		BucketServiceClient:                dplanemgrv1.NewBucketServiceClient(dataplaneMgrConn),
		PrivateLinkConnectionServiceClient: dplanemgrv1.NewPrivateLinkConnectionServiceClient(dataplaneMgrConn),
		LoadBalancerServiceClient:          dplanemgrv1.NewLoadBalancerServiceClient(dataplaneMgrConn),
		KeyspaceRoleServiceClient:          dplanemgrv1.NewKeyspaceRoleServiceClient(dataplaneMgrConn),
	}, nil
}
