package container

import (
	"crypto/sha256"
	"fmt"

	core "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/core/container"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/morph/client"
)

// Delete marshals container ID, and passes it to Wrapper's Delete method
// along with signature and session token.
//
// Returns error if container ID is nil.
func Delete(c *Client, witness core.RemovalWitness) error {
	binCnr := make([]byte, sha256.Size)
	witness.ContainerID.Encode(binCnr)

	var prm DeletePrm

	prm.SetCID(binCnr)
	prm.SetSignature(witness.Signature.GetSign())
	prm.SetKey(witness.Signature.GetKey())

	if tok := witness.SessionToken; tok != nil {
		prm.SetToken(tok.Marshal())
	}

	_, err := c.Delete(prm)
	return err
}

// DeletePrm groups parameters of Delete client operation.
type DeletePrm struct {
	cnr       []byte
	signature []byte
	token     []byte
	key       []byte

	client.InvokePrmOptional
}

// SetCID sets container ID.
func (d *DeletePrm) SetCID(cid []byte) {
	d.cnr = cid
}

// SetSignature sets signature.
func (d *DeletePrm) SetSignature(signature []byte) {
	d.signature = signature
}

// SetToken sets session token.
func (d *DeletePrm) SetToken(token []byte) {
	d.token = token
}

// SetKey sets public key.
func (d *DeletePrm) SetKey(key []byte) {
	d.key = key
}

// Delete removes the container from FrostFS system
// through Container contract call.
//
// Returns valid until block and any error encountered that caused
// the removal to interrupt.
//
// If TryNotary is provided, calls notary contract.
func (c *Client) Delete(p DeletePrm) (uint32, error) {
	if len(p.signature) == 0 && !p.IsControl() {
		return 0, errNilArgument
	}

	prm := client.InvokePrm{}
	prm.SetMethod(deleteMethod)
	prm.SetArgs(p.cnr, p.signature, p.key, p.token)
	prm.InvokePrmOptional = p.InvokePrmOptional

	res, err := c.client.Invoke(prm)
	if err != nil {
		return 0, fmt.Errorf("could not invoke method (%s): %w", deleteMethod, err)
	}
	return res.VUB, nil
}