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

package main

import (
	"context"
	"fmt"
	"log"
	"os"
	"os/signal"
	"regexp"
	"strings"

	"github.com/spf13/cobra"
	"google.golang.org/protobuf/types/known/fieldmaskpb"

	apb "source.monogon.dev/metropolis/proto/api"
	cpb "source.monogon.dev/metropolis/proto/common"
)

type configurableClusterKey struct {
	key         string
	description string
	set         func(value []string) (*apb.ConfigureClusterRequest, error)
	get         func(c *cpb.ClusterConfiguration) (string, error)
}

var configurableClusterKeys = []configurableClusterKey{
	{
		key:         "kubernetes.node_labels_to_synchronize",
		description: "list of label regexes to sync from Metropolis to Kubernetes nodes",
		set: func(value []string) (*apb.ConfigureClusterRequest, error) {
			res := &apb.ConfigureClusterRequest{
				NewConfig: &cpb.ClusterConfiguration{
					Kubernetes: &cpb.ClusterConfiguration_Kubernetes{},
				},
				UpdateMask: &fieldmaskpb.FieldMask{
					Paths: []string{"kubernetes.node_labels_to_synchronize"},
				},
			}
			for _, v := range value {
				_, err := regexp.Compile(v)
				if err != nil {
					return nil, fmt.Errorf("%q is not a valid regexp: %w", v, err)
				}
				res.NewConfig.Kubernetes.NodeLabelsToSynchronize = append(res.NewConfig.Kubernetes.NodeLabelsToSynchronize, &cpb.ClusterConfiguration_Kubernetes_NodeLabelsToSynchronize{
					Regexp: v,
				})
			}
			return res, nil
		},
		get: func(c *cpb.ClusterConfiguration) (string, error) {
			var res []string
			if kc := c.Kubernetes; kc != nil {
				for _, r := range kc.NodeLabelsToSynchronize {
					res = append(res, fmt.Sprintf("%q", r.Regexp))
				}
			}
			return strings.Join(res, ", "), nil
		},
	},
}

var clusterConfigureCommand = &cobra.Command{
	Use:   "configure <set/get> <field>",
	Short: "Gets/sets values in the cluster configuration structure",
	Long: `Gets/sets values in the cluster configuration structure.

The cluster is configured through a ClusterConfiguration structure, of which
a subset of fields can be modified. To set a field's value, use:

    cluster configure set <field> <value>

To get a field's current value, use the:

    cluster configure get <field>

Available configuration fields:

`,
	Args: PrintUsageOnWrongArgs(cobra.MinimumNArgs(2)),
	RunE: func(cmd *cobra.Command, args []string) error {
		mode := strings.ToLower(args[0])
		isSet := false
		switch mode {
		case "set":
			isSet = true
		case "get":
		default:
			return fmt.Errorf("invalid mode %q: must be set or get", mode)
		}

		var key *configurableClusterKey
		for _, k := range configurableClusterKeys {
			if k.key == args[1] {
				key = &k
				break
			}
		}
		if key == nil {
			return fmt.Errorf("unknown field %q, see help for list of supported fields", args[1])
		}

		ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)
		cc, err := dialAuthenticated(ctx)
		if err != nil {
			return fmt.Errorf("while dialing node: %w", err)
		}
		mgmt := apb.NewManagementClient(cc)

		if isSet {
			req, err := key.set(args[2:])
			if err != nil {
				return err
			}
			res, err := mgmt.ConfigureCluster(ctx, req)
			if err != nil {
				return fmt.Errorf("could not mutate config: %w", err)
			}
			newValue, err := key.get(res.ResultingConfig)
			if err != nil {
				return fmt.Errorf("could not extract value from new config: %w", err)
			}
			log.Printf("New value: %s", newValue)
		} else {
			if len(args[2:]) > 0 {
				return fmt.Errorf("get <field> takes no extra arguments")
			}
			ci, err := mgmt.GetClusterInfo(ctx, &apb.GetClusterInfoRequest{})
			if err != nil {
				return fmt.Errorf("could not get cluster information: %w", err)
			}
			newValue, err := key.get(ci.ClusterConfiguration)
			if err != nil {
				return fmt.Errorf("could not extract value from new config: %w", err)
			}
			log.Printf("Value: %s", newValue)
		}
		return nil
	},
}

func init() {
	for _, key := range configurableClusterKeys {
		clusterConfigureCommand.Long += fmt.Sprintf("  - %s: %s", key.key, key.description)
	}
	clusterCmd.AddCommand(clusterConfigureCommand)
}
