package cli

import (
	"os"
	"strings"

	"github.com/replicatedhq/troubleshoot/cmd/internal/util"
	"github.com/replicatedhq/troubleshoot/pkg/k8sutil"
	"github.com/replicatedhq/troubleshoot/pkg/logger"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"k8s.io/klog/v2"
)

func RootCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:          "collect [url]",
		Args:         cobra.MinimumNArgs(1),
		Short:        "Run a collector",
		Long:         `Run a collector and output the results.`,
		SilenceUsage: true,
		// PersistentPreRun/PersistentPostRun (rather than PreRun/PostRun) so this
		// setup also runs for the per-collector subcommands, not just `collect [url]`.
		PersistentPreRun: func(cmd *cobra.Command, args []string) {
			v := viper.GetViper()
			v.BindPFlags(cmd.Flags())

			logger.SetupLogger(v)

			if err := util.StartProfiling(); err != nil {
				klog.Errorf("Failed to start profiling: %v", err)
			}
		},
		RunE: func(cmd *cobra.Command, args []string) error {
			v := viper.GetViper()

			if err := checkAndSetChroot(v.GetString("chroot")); err != nil {
				return err
			}

			return runCollect(v, args[0])
		},
		PersistentPostRun: func(cmd *cobra.Command, args []string) {
			if err := util.StopProfiling(); err != nil {
				klog.Errorf("Failed to stop profiling: %v", err)
			}
		},
	}

	cobra.OnInitialize(initConfig)

	cmd.AddCommand(util.VersionCmd())

	// Per-collector subcommands: run a single collector and print its native
	// result JSON. Each has its own flags and help. These let a collector run
	// inside a Pod via the troubleshoot image (e.g. as a runPod collector), so
	// the check executes from within the cluster rather than wherever the CLI runs.
	cmd.AddCommand(HTTPCmd())
	cmd.AddCommand(PostgresCmd())
	cmd.AddCommand(MysqlCmd())
	cmd.AddCommand(MssqlCmd())
	cmd.AddCommand(RedisCmd())
	cmd.AddCommand(ClickhouseCmd())

	cmd.Flags().StringSlice("redactors", []string{}, "names of the additional redactors to use")
	cmd.Flags().Bool("redact", true, "enable/disable default redactions")
	cmd.Flags().String("format", "json", "output format, one of json or raw.")
	cmd.Flags().String("collector-image", "", "the full name of the collector image to use")
	cmd.Flags().String("collector-pull-policy", "", "the pull policy of the collector image")
	cmd.Flags().String("selector", "", "selector (label query) to filter remote collection nodes on.")
	cmd.Flags().Bool("collect-without-permissions", false, "always generate a support bundle, even if it some require additional permissions")
	cmd.PersistentFlags().Bool("debug", false, "enable debug logging")
	cmd.Flags().String("chroot", "", "Chroot to path")

	// hidden in favor of the `insecure-skip-tls-verify` flag
	cmd.Flags().Bool("allow-insecure-connections", false, "when set, do not verify TLS certs when retrieving spec and reporting results")
	cmd.Flags().MarkHidden("allow-insecure-connections")

	viper.BindPFlags(cmd.Flags())

	viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))

	k8sutil.AddFlags(cmd.PersistentFlags())

	// Initialize klog flags
	logger.InitKlogFlags(cmd)

	// CPU and memory profiling flags
	util.AddProfilingFlags(cmd)

	return cmd
}

func InitAndExecute() {
	if err := RootCmd().Execute(); err != nil {
		os.Exit(1)
	}
}

func initConfig() {
	viper.SetEnvPrefix("TROUBLESHOOT")
	viper.AutomaticEnv()
}
