// Copyright The Monogon Project Authors.
// SPDX-License-Identifier: Apache-2.0

package main

import (
	"context"
	"crypto/x509"
	"os"
	"path/filepath"

	"github.com/adrg/xdg"
	"github.com/spf13/cobra"

	"source.monogon.dev/go/logging"
	"source.monogon.dev/metropolis/cli/metroctl/core"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:           "metroctl",
	Short:         "metroctl controls Metropolis nodes and clusters.",
	SilenceUsage:  true,
	SilenceErrors: true,
}

type metroctlFlags struct {
	// cluster is the domain name identifying the target cluster.
	cluster string
	// clusterEndpoints is a list of the targeted cluster's endpoints, used by
	// commands that perform RPC on it.
	clusterEndpoints []string
	// proxyAddr is a SOCKS5 proxy address the cluster will be accessed through.
	proxyAddr string
	// configPath overrides the default XDG config path
	configPath string
	// verbose, if set, will make this utility log additional runtime
	// information.
	verbose bool
	// format refers to how the output data, except logs, is formatted.
	format string
	// filter specifies a CEL filter used to narrow down the set of output
	// objects.
	filter string
	// output is an optional output file path the resulting data will be saved
	// at. If unspecified, the data will be written to stdout.
	output string
	// acceptAnyCA will persist the first encountered (while connecting) CA
	// certificate of the cluster as the trusted CA certificate for this cluster.
	// This is unsafe and should only be used for testing.
	acceptAnyCA bool
	// columns is a comma-separated list of column names which selects which columns
	// will be output to the user. An empty string means all columns will be
	// displayed.
	columns string
}

var flags metroctlFlags

func init() {
	rootCmd.PersistentFlags().StringVar(&flags.cluster, "cluster", "", "Cluster domain")
	rootCmd.PersistentFlags().StringSliceVar(&flags.clusterEndpoints, "endpoints", nil, "A list of the target cluster's endpoints.")
	rootCmd.PersistentFlags().StringVar(&flags.proxyAddr, "proxy", "", "SOCKS5 proxy address")
	rootCmd.PersistentFlags().StringVar(&flags.configPath, "config", filepath.Join(xdg.ConfigHome, "metroctl"), "An alternative cluster config path")
	rootCmd.PersistentFlags().BoolVar(&flags.verbose, "verbose", false, "Log additional runtime information")
	rootCmd.PersistentFlags().StringVar(&flags.format, "format", "plaintext", "Data output format")
	rootCmd.PersistentFlags().StringVar(&flags.filter, "filter", "", "The object filter applied to the output data")
	rootCmd.PersistentFlags().StringVar(&flags.columns, "columns", "", "Comma-separated list of column names to show. If not set, all columns will be shown")
	rootCmd.PersistentFlags().StringVarP(&flags.output, "output", "o", "", "Redirects output to the specified file")
	rootCmd.PersistentFlags().BoolVar(&flags.acceptAnyCA, "insecure-accept-and-persist-first-encountered-ca", false, "Accept the first encountered CA while connecting as the trusted CA for future metroctl connections with this config path. This is very insecure and should only be used for testing.")
	rootCmd.SetFlagErrorFunc(func(cmd *cobra.Command, err error) error {
		cmd.PrintErr(cmd.UsageString())
		return err
	})
}

func PrintUsageOnWrongArgs(pArgs cobra.PositionalArgs) cobra.PositionalArgs {
	return func(cmd *cobra.Command, args []string) error {
		err := pArgs(cmd, args)
		if err != nil {
			cmd.PrintErr(cmd.UsageString())
		}
		return err
	}
}

func main() {
	cobra.CheckErr(rootCmd.Execute())
}

type acceptall struct{}

func (a *acceptall) Ask(ctx context.Context, _ *core.ConnectOptions, _ *x509.Certificate) (bool, error) {
	return true, nil
}

// connectOptions returns core.ConnectOptions as defined by the metroctl flags
// currently set.
func connectOptions() *core.ConnectOptions {
	var tofu core.CertificateTOFU
	if flags.acceptAnyCA {
		tofu = &acceptall{}
	}
	logger := logging.NewWriterBackend(os.Stderr)
	if !flags.verbose {
		logger.MinimumSeverity = logging.WARNING
	}
	return &core.ConnectOptions{
		ConfigPath:     flags.configPath,
		ProxyServer:    flags.proxyAddr,
		Endpoints:      flags.clusterEndpoints,
		ResolverLogger: logger,
		TOFU:           tofu,
	}
}
