package control

import (
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/common"
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/grpc"
)

const serviceName = "ircontrol.ControlService"

const (
	rpcHealthCheck = "HealthCheck"
	rpcTickEpoch   = "TickEpoch"
	rpcRemoveNode  = "RemoveNode"
)

// HealthCheck executes ControlService.HealthCheck RPC.
func HealthCheck(
	cli *client.Client,
	req *HealthCheckRequest,
	opts ...client.CallOption,
) (*HealthCheckResponse, error) {
	return sendUnary[HealthCheckRequest, HealthCheckResponse](cli, rpcHealthCheck, req, opts...)
}

// TickEpoch executes ControlService.TickEpoch RPC.
func TickEpoch(
	cli *client.Client,
	req *TickEpochRequest,
	opts ...client.CallOption,
) (*TickEpochResponse, error) {
	return sendUnary[TickEpochRequest, TickEpochResponse](cli, rpcTickEpoch, req, opts...)
}

func RemoveNode(
	cli *client.Client,
	req *RemoveNodeRequest,
	opts ...client.CallOption,
) (*RemoveNodeResponse, error) {
	return sendUnary[RemoveNodeRequest, RemoveNodeResponse](cli, rpcRemoveNode, req, opts...)
}

func sendUnary[I, O grpc.Message](cli *client.Client, rpcName string, req *I, opts ...client.CallOption) (*O, error) {
	var resp O
	wResp := &responseWrapper[*O]{
		m: &resp,
	}

	wReq := &requestWrapper{
		m: req,
	}

	err := client.SendUnary(cli, common.CallMethodInfoUnary(serviceName, rpcName), wReq, wResp, opts...)
	if err != nil {
		return nil, err
	}

	return wResp.m, nil
}