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

package main

import (
	"bytes"
	"context"
	"crypto/ed25519"
	_ "embed"
	"fmt"
	"os"
	"os/signal"

	"github.com/bazelbuild/rules_go/go/runfiles"
	"github.com/spf13/cobra"
	"google.golang.org/protobuf/encoding/prototext"

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

	"source.monogon.dev/metropolis/cli/flagdefs"
	"source.monogon.dev/metropolis/cli/metroctl/core"
	common "source.monogon.dev/metropolis/node"
	"source.monogon.dev/osbase/blkio"
	"source.monogon.dev/osbase/fat32"
)

var installCmd = &cobra.Command{
	Short: "Contains subcommands to install Metropolis via different media.",
	Use:   "install",
}

// bootstrap is a flag controlling node parameters included in the installer
// image. If set, the installed node will bootstrap a new cluster. Otherwise,
// it will try to connect to the cluster which endpoints were provided with
// the --endpoints flag.
var bootstrap = installCmd.PersistentFlags().Bool("bootstrap", false, "Create a bootstrap installer image.")
var bootstrapTPMMode = flagdefs.TPMModePflag(installCmd.PersistentFlags(), "bootstrap-tpm-mode", cpb.ClusterConfiguration_TPM_MODE_REQUIRED, "TPM mode to set on cluster")
var bootstrapStorageSecurityPolicy = flagdefs.StorageSecurityPolicyPflag(installCmd.PersistentFlags(), "bootstrap-storage-security", cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION_AND_AUTHENTICATION, "Storage security policy to set on cluster")
var bundlePath = installCmd.PersistentFlags().StringP("bundle", "b", "", "Path to the Metropolis bundle to be installed")
var nodeParamPath = installCmd.PersistentFlags().String("node-params", "", "Path to the metropolis.proto.api.NodeParameters prototext file (advanced usage only)")

func makeNodeParams() (*api.NodeParameters, error) {
	ctx, _ := signal.NotifyContext(context.Background(), os.Interrupt)

	if err := os.MkdirAll(flags.configPath, 0700); err != nil && !os.IsExist(err) {
		return nil, fmt.Errorf("failed to create config directory: %w", err)
	}

	var params *api.NodeParameters
	if *nodeParamPath != "" {
		nodeParamsRaw, err := os.ReadFile(*nodeParamPath)
		if err != nil {
			return nil, fmt.Errorf("failed to read node-params file: %w", err)
		}
		if err := prototext.Unmarshal(nodeParamsRaw, params); err != nil {
			return nil, fmt.Errorf("failed to parse node-params: %w", err)
		}
	} else {
		params = &api.NodeParameters{}
	}

	if *bootstrap {
		if flags.cluster == "" {
			return nil, fmt.Errorf("when bootstrapping a cluster, the --cluster parameter is required")
		}
		if err := common.ValidateClusterDomain(flags.cluster); err != nil {
			return nil, fmt.Errorf("invalid cluster domain: %w", err)
		}

		// TODO(lorenz): Have a key management story for this
		priv, err := core.GetOrMakeOwnerKey(flags.configPath)
		if err != nil {
			return nil, fmt.Errorf("failed to generate or get owner key: %w", err)
		}
		pub := priv.Public().(ed25519.PublicKey)
		params.Cluster = &api.NodeParameters_ClusterBootstrap_{
			ClusterBootstrap: &api.NodeParameters_ClusterBootstrap{
				OwnerPublicKey: pub,
				InitialClusterConfiguration: &cpb.ClusterConfiguration{
					ClusterDomain:         flags.cluster,
					StorageSecurityPolicy: *bootstrapStorageSecurityPolicy,
					TpmMode:               *bootstrapTPMMode,
				},
			},
		}
	} else {
		cc, err := newAuthenticatedClient(ctx)
		if err != nil {
			return nil, fmt.Errorf("while creating client: %w", err)
		}
		mgmt := api.NewManagementClient(cc)
		resT, err := mgmt.GetRegisterTicket(ctx, &api.GetRegisterTicketRequest{})
		if err != nil {
			return nil, fmt.Errorf("while receiving register ticket: %w", err)
		}
		resI, err := mgmt.GetClusterInfo(ctx, &api.GetClusterInfoRequest{})
		if err != nil {
			return nil, fmt.Errorf("while receiving cluster directory: %w", err)
		}

		params.Cluster = &api.NodeParameters_ClusterRegister_{
			ClusterRegister: &api.NodeParameters_ClusterRegister{
				RegisterTicket:   resT.Ticket,
				ClusterDirectory: resI.ClusterDirectory,
				CaCertificate:    resI.CaCertificate,
			},
		}
	}
	return params, nil
}

func external(name, datafilePath string, flag *string) (fat32.SizedReader, error) {
	if flag == nil || *flag == "" {
		rPath, err := runfiles.Rlocation(datafilePath)
		if err != nil {
			return nil, fmt.Errorf("no %s specified", name)
		}
		df, err := os.ReadFile(rPath)
		if err != nil {
			return nil, fmt.Errorf("can't read file: %w", err)
		}
		return bytes.NewReader(df), nil
	}

	f, err := blkio.NewFileReader(*flag)
	if err != nil {
		return nil, fmt.Errorf("failed to open specified %s: %w", name, err)
	}

	return f, nil
}

func init() {
	rootCmd.AddCommand(installCmd)
}
