// 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"
)

// ComponentConfig is the common configuration of a component. It's
// supposed to be instantiated within a Configuration struct of a component.
//
// It can be configured by flags (via RegisterFlags) or manually (eg. in tests).
type ComponentConfig 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 *ComponentConfig) 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 *ComponentConfig) 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)),
	}
}

// GRPCServerOptionsPublic returns pre-built grpc.ServerOptions that this
// component should use to serve public gRPC. Any client will be allowed to
// connect, and it's up to the server implementation to authenticate incoming
// requests.
func (c *ComponentConfig) GRPCServerOptionsPublic() []grpc.ServerOption {
	var certPath, keyPath string
	if c.DevCerts {
		// Use devcerts if requested.
		certPath, keyPath, _ = 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")
		}
		keyPath = c.GRPCKeyPath
		certPath = c.GRPCCertificatePath
	}

	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.RequestClientCert,
	}
	return []grpc.ServerOption{
		grpc.Creds(credentials.NewTLS(tlsConf)),
	}
}
