package nns

import (
	"math/big"
	"strings"

	"git.frostfs.info/TrueCloudLab/frostfs-contract/nns"
	client "git.frostfs.info/TrueCloudLab/frostfs-contract/rpcclient/nns"
	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-adm/internal/commonflags"
	commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
	"github.com/spf13/cobra"
)

const (
	verboseDesc = "Include additional information about CNAME record."
)

func initTokensCmd() {
	Cmd.AddCommand(tokensCmd)
	tokensCmd.Flags().StringP(commonflags.EndpointFlag, commonflags.EndpointFlagShort, "", commonflags.EndpointFlagDesc)
	tokensCmd.Flags().String(commonflags.AlphabetWalletsFlag, "", commonflags.AlphabetWalletsFlagDesc)
	tokensCmd.Flags().BoolP(commonflags.Verbose, commonflags.VerboseShorthand, false, verboseDesc)
}

func listTokens(cmd *cobra.Command, _ []string) {
	c, _, _ := getRPCClient(cmd)
	it, err := c.Tokens()
	commonCmd.ExitOnErr(cmd, "unable to get tokens: %w", err)
	for toks, err := it.Next(10); err == nil && len(toks) > 0; toks, err = it.Next(10) {
		for _, token := range toks {
			output := string(token)
			if verbose, _ := cmd.Flags().GetBool(commonflags.Verbose); verbose {
				cname, err := getCnameRecord(c, token)
				commonCmd.ExitOnErr(cmd, "", err)
				if cname != "" {
					output += " (CNAME: " + cname + ")"
				}
			}
			cmd.Println(output)
		}
	}
}

func getCnameRecord(c *client.Contract, token []byte) (string, error) {
	items, err := c.GetRecords(string(token), big.NewInt(int64(nns.CNAME)))

	// GetRecords returns the error "not an array" if the domain does not contain records.
	if err != nil && strings.Contains(err.Error(), "not an array") {
		return "", nil
	}

	if err != nil {
		return "", err
	}

	if len(items) == 0 {
		return "", nil
	}

	record, err := items[0].TryBytes()
	if err != nil {
		return "", err
	}

	return string(record), nil
}