package client

import (
	"context"
	"fmt"

	apemanagerV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/apemanager"
	rpcapi "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc"
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
	sessionV2 "git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/session"
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/signature"
	apeSDK "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/ape"
	apistatus "git.frostfs.info/TrueCloudLab/frostfs-sdk-go/client/status"
)

// PrmAPEManagerListChains groups parameters of APEManagerListChains operation.
type PrmAPEManagerListChains struct {
	XHeaders []string

	ChainTarget apeSDK.ChainTarget
}

func (prm *PrmAPEManagerListChains) buildRequest(c *Client) (*apemanagerV2.ListChainsRequest, error) {
	if len(prm.XHeaders)%2 != 0 {
		return nil, errorInvalidXHeaders
	}

	req := new(apemanagerV2.ListChainsRequest)
	reqBody := new(apemanagerV2.ListChainsRequestBody)

	reqBody.SetTarget(prm.ChainTarget.ToV2())

	req.SetBody(reqBody)

	var meta sessionV2.RequestMetaHeader
	writeXHeadersToMeta(prm.XHeaders, &meta)

	c.prepareRequest(req, &meta)

	return req, nil
}

type ResAPEManagerListChains struct {
	statusRes

	Chains []apeSDK.Chain
}

// APEManagerListChains lists Chains for ChainTarget.
func (c *Client) APEManagerListChains(ctx context.Context, prm PrmAPEManagerListChains) (*ResAPEManagerListChains, error) {
	req, err := prm.buildRequest(c)
	if err != nil {
		return nil, err
	}

	if err := signature.SignServiceMessage(&c.prm.Key, req); err != nil {
		return nil, fmt.Errorf("sign request: %w", err)
	}

	resp, err := rpcapi.ListChains(&c.c, req, client.WithContext(ctx))
	if err != nil {
		return nil, err
	}

	var res ResAPEManagerListChains
	res.st, err = c.processResponse(resp)
	if err != nil || !apistatus.IsSuccessful(res.st) {
		return nil, err
	}

	for _, ch := range resp.GetBody().GetChains() {
		var chSDK apeSDK.Chain
		if err := chSDK.ReadFromV2(ch); err != nil {
			return nil, err
		}
		res.Chains = append(res.Chains, chSDK)
	}

	return &res, nil
}