package util

import (
	"os"

	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/common"
	"git.frostfs.info/TrueCloudLab/frostfs-node/cmd/frostfs-cli/internal/commonflags"
	commonCmd "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common"
	apeutil "git.frostfs.info/TrueCloudLab/frostfs-node/internal/ape"
	"git.frostfs.info/TrueCloudLab/policy-engine/pkg/chain"
	"github.com/spf13/cobra"
)

const (
	fromFlagStr = "from"
	toFlagStr   = "to"
	apeFlagStr  = "ape"
)

var convertEACLCmd = &cobra.Command{
	Use:   "eacl",
	Short: "Convert representation of extended ACL table",
	Run:   convertEACLTable,
}

func initConvertEACLCmd() {
	flags := convertEACLCmd.Flags()

	flags.String(fromFlagStr, "", "File with JSON or binary encoded extended ACL table")
	_ = convertEACLCmd.MarkFlagFilename(fromFlagStr)
	_ = convertEACLCmd.MarkFlagRequired(fromFlagStr)

	flags.String(toFlagStr, "", "File to dump extended ACL table (default: binary encoded)")
	flags.Bool(commonflags.JSON, false, "Dump extended ACL table in JSON encoding")

	flags.Bool(apeFlagStr, false, "Dump converted eACL table to APE chain format")

	convertEACLCmd.MarkFlagsMutuallyExclusive(apeFlagStr, commonflags.JSON)
}

func convertEACLTable(cmd *cobra.Command, _ []string) {
	pathFrom := cmd.Flag(fromFlagStr).Value.String()
	to := cmd.Flag(toFlagStr).Value.String()
	jsonFlag, _ := cmd.Flags().GetBool(commonflags.JSON)
	apeFlag, _ := cmd.Flags().GetBool(apeFlagStr)

	table := common.ReadEACL(cmd, pathFrom)

	var data []byte
	var err error

	if apeFlag {
		var ch *chain.Chain
		ch, err = apeutil.ConvertEACLToAPE(table)
		commonCmd.ExitOnErr(cmd, "convert eACL table to APE chain error: %w", err)
		data = ch.Bytes()
	} else if jsonFlag || len(to) == 0 {
		data, err = table.MarshalJSON()
		commonCmd.ExitOnErr(cmd, "can't JSON encode extended ACL table: %w", err)
	} else {
		data, err = table.Marshal()
		commonCmd.ExitOnErr(cmd, "can't binary encode extended ACL table: %w", err)
	}

	if len(to) == 0 {
		common.PrettyPrintJSON(cmd, table, "eACL")
		return
	}

	err = os.WriteFile(to, data, 0o644)
	commonCmd.ExitOnErr(cmd, "can't write exteded ACL table to file: %w", err)

	cmd.Printf("extended ACL table was successfully dumped to %s\n", to)
}