package main

import (
	"flag"
	"sync"
	"time"
)

const (
	defaultAddr             = ":8080"
	defaultInternalGRPCAddr = "127.0.0.1:8081"
	defaultLogLevel         = "info"
	defaultProvider         = "kind"
	defaultLogHealthCheck   = false
	defaultAuditEnabled     = false
	defaultAuditFilePath    = ""
	defaultAuditIncludeGet  = false
	defaultAuditMaxBodySize = 0

	defaultTLSCertFile = ""
	defaultTLSKeyFile  = ""

	defaultPrivilegedTiDBDeactivationWait = 30 * time.Second
)

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"`

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

	// Region is the cloud region.
	Region string `toml:"region" json:"region"`

	// DataplaneKubeConfig is the path to the kubeconfig of dataplane k8s. It is usually used
	// for running cluster-agent locally for development
	DataplaneKubeConfig string `toml:"dataplane-kubeconfig" json:"dataplane-kubeconfig"`

	// LogHealthCheck controls whether successful health-check logs are emitted.
	LogHealthCheck bool `toml:"log-health-check" json:"log-health-check"`

	AuditEnabled            bool   `toml:"audit-enabled" json:"audit-enabled"`
	AuditFilePath           string `toml:"audit-file-path" json:"audit-file-path"`
	AuditIncludeGetRequests bool   `toml:"audit-include-get-requests" json:"audit-include-get-requests"`
	AuditMaxBodySize        int    `toml:"audit-max-body-size" json:"audit-max-body-size"`

	// TLSCertFile is the path to the TLS certificate file for HTTPS server.
	TLSCertFile string `toml:"tls-cert-file" json:"tls-cert-file"`
	// TLSKeyFile is the path to the TLS private key file for HTTPS server.
	TLSKeyFile string `toml:"tls-key-file" json:"tls-key-file"`

	// PrivilegedTiDBDeactivationWait is how long the cluster-agent waits after a
	// privileged TiDB SQL exec before deleting the pod. Lower values improve
	// throughput when many reset_password requests target different keyspaces;
	// higher values give the auditlog sidecar more time to flush.
	PrivilegedTiDBDeactivationWait time.Duration `toml:"privileged-tidb-deactivation-wait" json:"privileged-tidb-deactivation-wait"`
}

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,
			Provider:                       defaultProvider,
			LogHealthCheck:                 defaultLogHealthCheck,
			AuditEnabled:                   defaultAuditEnabled,
			AuditFilePath:                  defaultAuditFilePath,
			AuditIncludeGetRequests:        defaultAuditIncludeGet,
			AuditMaxBodySize:               defaultAuditMaxBodySize,
			TLSCertFile:                    defaultTLSCertFile,
			TLSKeyFile:                     defaultTLSKeyFile,
			PrivilegedTiDBDeactivationWait: defaultPrivilegedTiDBDeactivationWait,
		}

		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.Provider, "provider", conf.Provider, "cloud provider, e.g. `aws`, `gcp`, `kind`, default is `kind`")
		conf.flagSet.StringVar(&conf.Region, "region", conf.Region, "cloud region, e.g. `us-west-2` for aws")
		conf.flagSet.StringVar(&conf.DataplaneKubeConfig, "dataplane-kubeconfig", "", "kubeconfig of dataplane k8s, e.g. `~/.kube/config`")
		conf.flagSet.BoolVar(&conf.LogHealthCheck, "log-health-check", conf.LogHealthCheck, "whether to log successful health-check requests")
		conf.flagSet.BoolVar(&conf.AuditEnabled, "audit-enabled", conf.AuditEnabled, "enable HTTP API audit logging")
		conf.flagSet.StringVar(&conf.AuditFilePath, "audit-file-path", conf.AuditFilePath, "file path for HTTP API audit log")
		conf.flagSet.BoolVar(&conf.AuditIncludeGetRequests, "audit-include-get-requests", conf.AuditIncludeGetRequests, "include GET requests in HTTP API audit log")
		conf.flagSet.IntVar(&conf.AuditMaxBodySize, "audit-max-body-size", conf.AuditMaxBodySize, "maximum captured request body size for API audit; <= 0 disables body capture")
		conf.flagSet.StringVar(&conf.TLSCertFile, "tls-cert-file", conf.TLSCertFile, "path to TLS certificate file for HTTPS server")
		conf.flagSet.StringVar(&conf.TLSKeyFile, "tls-key-file", conf.TLSKeyFile, "path to TLS private key file for HTTPS server")
		conf.flagSet.DurationVar(&conf.PrivilegedTiDBDeactivationWait, "privileged-tidb-deactivation-wait", conf.PrivilegedTiDBDeactivationWait,
			"delay after a privileged TiDB SQL exec before deleting the pod (e.g. 5s, 30s); lower values improve throughput when many reset_password requests target different keyspaces")
		err = conf.flagSet.Parse(args)
	})
	return err
}

func GetConfig() *Config {
	return conf
}
