// 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 := newAuthenticatedClient(ctx)
		if err != nil {
			return fmt.Errorf("while creating client: %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)
}
