package forwarder

import (
	"fmt"

	"github.com/spf13/cobra"
	"sigs.k8s.io/yaml"
)

type Tool struct {
	cmd                   *cobra.Command
	listForwardersParams  ListForwardersParams
	createForwarderParams CreateForwarderParams
	deleteForwarderParams DeleteForwarderParams
}

func NewTool() *Tool {
	tool := &Tool{}
	tool.cmd = &cobra.Command{
		Use:     "forwarder",
		Short:   "Forwarder operation",
		Aliases: []string{"forw"},
	}
	listForwardersCmd := &cobra.Command{
		Use:   "list",
		Args:  cobra.ExactArgs(1),
		Short: "List forwarders",
		Run:   tool.ListForwarders,
	}
	tool.cmd.AddCommand(listForwardersCmd)

	createForwarderCmd := &cobra.Command{
		Use:   "create",
		Args:  cobra.ExactArgs(1),
		Short: "Create or update forwarder",
		Run:   tool.CreateForwarder,
	}
	createForwarderCmd.Flags().StringVarP(&tool.createForwarderParams.Type, "type", "T", "tcp", "Type of forwarding: tcp, udp")
	createForwarderCmd.Flags().Uint32VarP(&tool.createForwarderParams.Lport, "lport", "L", 0, "Listening port")
	createForwarderCmd.Flags().Uint32VarP(&tool.createForwarderParams.Dport, "dport", "D", 0, "Destination port")
	createForwarderCmd.Flags().StringArrayVarP(&tool.createForwarderParams.Addresses, "dests", "A", []string{}, "Destination address list")
	createForwarderCmd.MarkFlagRequired("type")
	createForwarderCmd.MarkFlagRequired("lport")
	createForwarderCmd.MarkFlagRequired("dport")
	createForwarderCmd.MarkFlagRequired("dests")
	tool.cmd.AddCommand(createForwarderCmd)

	deleteForwarderCmd := &cobra.Command{
		Use:   "delete",
		Args:  cobra.ExactArgs(1),
		Short: "Delete forwarder",
		Run:   tool.DeleteForwarder,
	}
	deleteForwarderCmd.Flags().StringVarP(&tool.deleteForwarderParams.Type, "type", "T", "tcp", "Forwarder type: tcp")
	deleteForwarderCmd.Flags().Uint32VarP(&tool.deleteForwarderParams.Lport, "lport", "L", 0, "Listening port")
	deleteForwarderCmd.MarkFlagRequired("lport")
	deleteForwarderCmd.MarkFlagRequired("type")
	tool.cmd.AddCommand(deleteForwarderCmd)

	return tool
}

func (tool *Tool) GetCmd() *cobra.Command {
	return tool.cmd
}

func printResponse(res any, err error) {
	type Response struct {
		Error   bool   `json:"error"             json:"error"`
		Message string `json:"message,omitempty" json:"message,omitempty"`
		Result  any    `json:"result,omitempty"  json:"result,omitempty"`
	}
	resp := Response{}
	if err != nil {
		resp.Error = true
		resp.Message = err.Error()
	} else {
		resp.Result = res
	}
	respBytes, _ := yaml.Marshal(resp)
	fmt.Printf("---\n%s\n", string(respBytes))
}
