package mgmt_svc

import (
	"context"
	"fmt"

	grpczap "github.com/grpc-ecosystem/go-grpc-middleware/logging/zap"
	pingcaplog "github.com/pingcap/log"
	nextgenv1 "github.com/tidbcloud/tidb-management-service/api/spec/global/nextgen/v1"
	mgmtv1 "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	tigrpcclient "github.com/tidbcloud/tiinf/transport/tigrpc/client"
)

type Client struct {
	clusterCli      mgmtv1.ClusterServiceClient
	resourcePoolCli mgmtv1.ResourcePoolServiceClient
}

func New(endpoint string) (*Client, error) {
	dialOptions := customizedTiGRPCOptions()
	conn, err := tigrpcclient.NewClientConn(endpoint, dialOptions...)
	if err != nil {
		return nil, err
	}
	c := &Client{
		clusterCli:      mgmtv1.NewClusterServiceClient(conn),
		resourcePoolCli: mgmtv1.NewResourcePoolServiceClient(conn),
	}
	return c, nil
}

// we do not enable traceing for grpc
func customizedTiGRPCOptions() []tigrpcclient.Option {
	zapOpts := grpczap.WithMessageProducer(tigrpcclient.TraceIDMessageProducer)
	opts := []tigrpcclient.Option{tigrpcclient.WithPrometheus(), tigrpcclient.WithZapLogger(pingcaplog.L(), zapOpts)}
	return opts
}

func (c *Client) GetCluster(ctx context.Context, clusterID uint64) (*mgmtv1.Cluster, error) {
	req := &mgmtv1.ListClustersRequest{
		Filter: &mgmtv1.ClusterFilter{
			ClusterIds: []uint64{clusterID},
		},
	}
	resp, err := c.clusterCli.ListClusters(ctx, req)
	if err != nil {
		return nil, err
	}
	if len(resp.Clusters) == 0 {
		return nil, fmt.Errorf("cluster %d not found in mgmt service", clusterID)
	}

	return resp.Clusters[0], nil
}

func (c *Client) GetResourcePool(ctx context.Context, resourcePoolID uint64) (*nextgenv1.ResourcePoolProfile, error) {
	req := &nextgenv1.GetResourcePoolRequest{
		ResourcePoolId: resourcePoolID,
		ShowDeleted:    true,
	}
	resp, err := c.resourcePoolCli.GetResourcePool(ctx, req)
	if err != nil {
		return nil, err
	}
	if resp == nil || resp.ResourcePool == nil {
		return nil, fmt.Errorf("resource pool %d not found in mgmt service", resourcePoolID)
	}
	return resp, nil
}
