package config

import (
	"flag"
	"fmt"
	"os"
	"sync"
)

const (
	defaultAddr             = ":8080"
	defaultInternalGRPCAddr = "127.0.0.1:8081"
	defaultLogLevel         = "info"
	defaultNSPrefix         = "nightly-ms-"
	defaultRegion           = "us-west-2"
)

var (
	conf     *Config
	confOnce sync.Once
)

type Config struct {
	flagSet *flag.FlagSet

	// LogLevel is the log level.
	LogLevel string `toml:"log-level" json:"log-level"`

	// Addr is the address to listen on.
	Addr string `toml:"addr" json:"addr"`

	// InternalGRPCAddr is the address of internal grpc server.
	InternalGRPCAddr string `toml:"internal-grpc-addr" json:"internal-grpc-addr"`

	// Kubeconfig is the path to Kubeconfig.
	Kubeconfig string `toml:"kubeconfig" json:"kubeconfig"`

	// NamespacePrefix is the namespace prefix of objects managed by cluster-server
	NamespacePrefix string `toml:"namespacePrefix" json:"namespacePrefix"`

	// Provider is the cloud provider.
	Provider string `toml:"provider" json:"provider"`

	// Region is the region label of objects managed by cluster-controller
	Region string `toml:"region" json:"region"`

	// Cluster Proxy uses Auth0 for authentication
	Auth0Domain       string `toml:"auth0Domain" json:"auth0Domain"`
	Auth0Audience     string `toml:"auth0Audience" json:"auth0Audience"`
	Auth0ClientID     string `toml:"auth0ClientID" json:"auth0ClientID"`
	Auth0ClientSecret string `toml:"auth0ClientSecret" json:"auth0ClientSecret"`

	OverrideHelperImage string `toml:"overrideHelperImage" json:"overrideHelperImage"`
	OverrideRegistry    string `toml:"overrideRegistry" json:"overrideRegistry"`
	OverrideRepoPrefix  string `toml:"overrideRepoPrefix" json:"overrideRepoPrefix"`

	UseSelfSignedCertForTiDBComponents bool `toml:"useSelfSignedCertForTiDBComponents" json:"useSelfSignedCertForTiDBComponents"`

	// ShortLivedComponentCert makes the PCA-issued cluster certificates
	// short-lived (keeping the AWS Private CA issuer). Enable it when the
	// environment's Private CA runs in SHORT_LIVED_CERTIFICATE mode, which cannot
	// issue the default long-lived certificate.
	ShortLivedComponentCert bool `toml:"shortLivedComponentCert" json:"shortLivedComponentCert"`
}

func InitConfig(args []string) error {
	var err error
	confOnce.Do(func() {
		conf = &Config{
			flagSet:          flag.NewFlagSet("http-service", flag.ContinueOnError),
			LogLevel:         defaultLogLevel,
			Addr:             defaultAddr,
			InternalGRPCAddr: defaultInternalGRPCAddr,
			NamespacePrefix:  defaultNSPrefix,
			Region:           defaultRegion,
		}

		conf.flagSet.StringVar(&conf.LogLevel, "L", conf.LogLevel, "log level")
		conf.flagSet.StringVar(&conf.Addr, "addr", conf.Addr, "address to listen on")
		conf.flagSet.StringVar(&conf.InternalGRPCAddr, "internal-grpc-addr", conf.InternalGRPCAddr, "address of internal grpc server")
		conf.flagSet.StringVar(&conf.Kubeconfig, "kubeconfig", conf.Kubeconfig, "path to kubeconfig of the infra API server")
		conf.flagSet.StringVar(&conf.NamespacePrefix, "ns-prefix", conf.NamespacePrefix, "the namespace prefix of objects managed by cluster-server.")
		conf.flagSet.StringVar(&conf.Provider, "provider", conf.Provider, "cloud provider, e.g. `aws`, `gcp`, `kind`, default is `kind`")
		conf.flagSet.StringVar(&conf.Region, "region", conf.Region, "the region label of objects managed by cluster-controller.")
		conf.flagSet.StringVar(&conf.Auth0Domain, "auth0-domain", conf.Auth0Domain, "Auth0 domain")
		conf.flagSet.StringVar(&conf.Auth0Audience, "auth0-audience", conf.Auth0Audience, "Auth0 audience")
		conf.flagSet.BoolVar(&conf.UseSelfSignedCertForTiDBComponents, "use-self-signed-cert-for-tidb-components", false, "whether use self signed cert for tidb components")
		conf.flagSet.BoolVar(&conf.ShortLivedComponentCert, "short-lived-component-cert", false, "whether to make PCA-issued cluster certificates short-lived (for a SHORT_LIVED_CERTIFICATE-mode Private CA)")
		conf.flagSet.StringVar(&conf.OverrideHelperImage, "override-helper-image", conf.OverrideHelperImage, "override helper image with this image.")
		conf.flagSet.StringVar(&conf.OverrideRegistry, "override-registry", conf.OverrideRegistry, "override image registry with this.")
		conf.flagSet.StringVar(&conf.OverrideRepoPrefix, "override-repo-prefix", conf.OverrideRepoPrefix, "override image repo prefix with this.")
		err = conf.flagSet.Parse(args)

		proxyAuth0ClientId, ok1 := os.LookupEnv("PROXY_AUTH0_CLIENT_ID")
		proxyAuth0ClientSecret, ok2 := os.LookupEnv("PROXY_AUTH0_CLIENT_SECRET")
		if (!ok1 || !ok2) && err == nil {
			err = fmt.Errorf("PROXY_AUTH0_CLIENT_ID and PROXY_AUTH0_CLIENT_SECRET must be set")
		}
		conf.Auth0ClientID = proxyAuth0ClientId
		conf.Auth0ClientSecret = proxyAuth0ClientSecret
	})
	return err
}

func GetConfig() *Config {
	return conf
}
