// Package component implements reusable bits for cloud service components. Each
// component is currently defined as being a standalone Go binary with its own
// internal gRPC listener. Subsequent listeners (eg. public gRPC or HTTP) can be
// defined by users of this library.
package component

import (
	"crypto/tls"
	"crypto/x509"
	"flag"
	"os"
	"path/filepath"

	"github.com/adrg/xdg"
	"google.golang.org/grpc"
	"google.golang.org/grpc/credentials"
	"k8s.io/klog/v2"
)

// Configuration is the common configuration of a component.
type Configuration struct {
	// GRPCKeyPath is the filesystem path of the x509 key used to serve internal
	// gRPC traffic.
	GRPCKeyPath string
	// GRPCCertificatePath is the filesystem path of the x509 certificate used to
	// serve internal gRPC traffic.
	GRPCCertificatePath string
	// GRPCCAPath is the filesystem path of of the x509 CA certificate used to
	// verify incoming connections on internal gRPC traffic.
	GRPCCAPath string
	// GRPCListenAddress is the address on which the component should server
	// internal gRPC traffic.
	GRPCListenAddress string

	// DevCerts, if enabled, automatically generates development CA and component
	// certificates/keys at DevCertsPath, uses these to serve traffic.
	DevCerts bool
	// DevCertsPath sets the prefix in which DevCerts are generated. All components
	// should have the same path set so that they reuse the CA certificate.
	DevCertsPath string

	// ComponentName is the name of this component, which should be [a-z0-9+]. It's
	// used to prefix all flags set by the Configuration.
	ComponentName string
}

// RegisterFlags registers the component configuration to be provided by flags.
// This must be called exactly once before then calling flags.Parse().
func (c *Configuration) RegisterFlags(componentName string) {
	flag.StringVar(&c.GRPCKeyPath, componentName+"_grpc_key_path", "", "Path to gRPC server/client key for "+componentName)
	flag.StringVar(&c.GRPCCertificatePath, componentName+"_grpc_certificate_path", "", "Path to gRPC server/client certificate for "+componentName)
	flag.StringVar(&c.GRPCCAPath, componentName+"_grpc_ca_certificate_path", "", "Path to gRPC CA certificate for "+componentName)
	flag.StringVar(&c.GRPCListenAddress, componentName+"_grpc_listen_address", ":4242", "Address to listen at for gRPC connections for "+componentName)

	flag.BoolVar(&c.DevCerts, componentName+"_dev_certs", false, "Use developer certificates (autogenerated) for "+componentName)
	flag.StringVar(&c.DevCertsPath, componentName+"_dev_certs_path", filepath.Join(xdg.ConfigHome, "monogon-dev-certs"), "Path for storing developer certificates")

	c.ComponentName = componentName
}

// GRPCServerOptions returns pre-built grpc.ServerOptions that this component
// should use to serve internal gRPC.
func (c *Configuration) GRPCServerOptions() []grpc.ServerOption {
	var certPath, keyPath, caPath string
	if c.DevCerts {
		// Use devcerts if requested.
		certPath, keyPath, caPath = c.GetDevCerts()
	} else {
		// Otherwise, use data from flags.
		if c.GRPCKeyPath == "" {
			klog.Exitf("-grpc_key_path must be set")
		}
		if c.GRPCCertificatePath == "" {
			klog.Exitf("-grpc_certificate_path must be set")
		}
		if c.GRPCCAPath == "" {
			klog.Exitf("-grpc_ca_certificate_path must be set")
		}
		keyPath = c.GRPCKeyPath
		certPath = c.GRPCCertificatePath
		caPath = c.GRPCCAPath
	}

	ca, err := os.ReadFile(caPath)
	if err != nil {
		klog.Exitf("Could not read GRPC CA: %v", err)
	}
	certPool := x509.NewCertPool()
	if !certPool.AppendCertsFromPEM(ca) {
		klog.Exitf("Could not load GRPC CA: %v", err)
	}

	pair, err := tls.LoadX509KeyPair(certPath, keyPath)
	if err != nil {
		klog.Exitf("Could not load GRPC TLS keypair: %v", err)
	}
	tlsConf := &tls.Config{
		Certificates: []tls.Certificate{pair},
		ClientAuth:   tls.RequireAndVerifyClientCert,
		RootCAs:      certPool,
	}
	return []grpc.ServerOption{
		grpc.Creds(credentials.NewTLS(tlsConf)),
	}
}
