package control

import (
	"git.frostfs.info/TrueCloudLab/frostfs-api-go/v2/rpc/client"
	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/key"
	commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
	"git.frostfs.info/TrueCloudLab/frostfs-node/pkg/services/control"
	"github.com/mr-tron/base58"
	"github.com/spf13/cobra"
)

var writecacheShardCmd = &cobra.Command{
	Use:   "writecache",
	Short: "Operations with storage node's write-cache",
	Long:  "Operations with storage node's write-cache",
}

var sealWritecacheShardCmd = &cobra.Command{
	Use:   "seal",
	Short: "Flush objects from write-cache and move write-cache to degraded read only mode.",
	Long:  "Flush all the objects from the write-cache to the main storage and move the write-cache to the degraded read only mode: write-cache will be empty and no objects will be put in it.",
	Run:   sealWritecache,
}

func sealWritecache(cmd *cobra.Command, _ []string) {
	pk := key.Get(cmd)

	ignoreErrors, _ := cmd.Flags().GetBool(ignoreErrorsFlag)

	req := &control.SealWriteCacheRequest{Body: &control.SealWriteCacheRequest_Body{
		Shard_ID:     getShardIDList(cmd),
		IgnoreErrors: ignoreErrors,
	}}

	signRequest(cmd, pk, req)

	cli := getClient(cmd, pk)

	var resp *control.SealWriteCacheResponse
	var err error
	err = cli.ExecRaw(func(client *client.Client) error {
		resp, err = control.SealWriteCache(client, req)
		return err
	})
	commonCmd.ExitOnErr(cmd, "rpc error: %w", err)

	verifyResponse(cmd, resp.GetSignature(), resp.GetBody())

	var success, failed uint
	for _, res := range resp.GetBody().GetResults() {
		if res.GetSuccess() {
			success++
			cmd.Printf("Shard %s: OK\n", base58.Encode(res.GetShard_ID()))
		} else {
			failed++
			cmd.Printf("Shard %s: failed with error %q\n", base58.Encode(res.GetShard_ID()), res.GetError())
		}
	}
	cmd.Printf("Total: %d success, %d failed\n", success, failed)
}

func initControlShardsWritecacheCmd() {
	writecacheShardCmd.AddCommand(sealWritecacheShardCmd)

	initControlFlags(sealWritecacheShardCmd)

	ff := sealWritecacheShardCmd.Flags()
	ff.StringSlice(shardIDFlag, nil, "List of shard IDs in base58 encoding")
	ff.Bool(shardAllFlag, false, "Process all shards")
	ff.Bool(ignoreErrorsFlag, true, "Skip invalid/unreadable objects")

	sealWritecacheShardCmd.MarkFlagsMutuallyExclusive(shardIDFlag, shardAllFlag)
}