package tlstool

import (
	"crypto/tls"
	"errors"
	"fmt"
)

func ServerConfig(certFile, keyFile string) (*tls.Config, error) {
	cert, err := tls.LoadX509KeyPair(certFile, keyFile)
	if err != nil {
		return nil, fmt.Errorf("loading certificate (%s) and key (%s) files: %w", certFile, keyFile, err)
	}
	return &tls.Config{
		Certificates: []tls.Certificate{cert},
		CipherSuites: secureCipherSuites(),
		MinVersion:   tls.VersionTLS12,
	}, nil
}

// MaybeServerConfig is like ServerConfig but returns (nil, nil) if certFile and keyFile are empty.
func MaybeServerConfig(certFile, keyFile string) (*tls.Config, error) {
	switch {
	case certFile != "" && keyFile != "":
		config, err := ServerConfig(certFile, keyFile)
		if err != nil {
			return nil, err
		}
		return config, nil
	case certFile == "" && keyFile == "":
		return nil, nil
	default:
		return nil, fmt.Errorf("both certificate file (%s) and key file (%s) must be either specified or not", certFile, keyFile)
	}
}

func MaybeServerConfigWithMTLS(certFile, keyFile, mtlsClientCAFile string, mtlsEnabled bool) (*tls.Config, error) {
	config, err := MaybeServerConfig(certFile, keyFile)
	if err != nil {
		return nil, err
	}
	mtlsEnabled = mtlsEnabled || mtlsClientCAFile != ""
	if !mtlsEnabled {
		return config, nil // nil, nil is ok
	}
	if config == nil {
		return nil, errors.New("certificate file and key file must be specified for mTLS to be used")
	}
	config.ClientAuth = tls.RequireAndVerifyClientCert
	if mtlsClientCAFile == "" {
		return config, nil
	}
	cert, err := LoadCACert(mtlsClientCAFile)
	if err != nil {
		return nil, err
	}
	config.ClientCAs = cert

	return config, nil
}
