package main

import (
	"flag"
	"path/filepath"

	"github.com/tidbcloud/observability/pkg/dataapi"

	"k8s.io/client-go/rest"
	"k8s.io/client-go/tools/clientcmd"

	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/tidbcloud/observability/pkg/resourcemanager"
	"k8s.io/client-go/util/homedir"

	"github.com/tidbcloud/observability/pkg/common/configs"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"github.com/tidbcloud/observability/pkg/common/metrics"
	"github.com/tidbcloud/observability/pkg/common/structs"
	"github.com/tidbcloud/observability/pkg/common/utils"
	"github.com/tidbcloud/observability/pkg/resourceworker/providers"
	"github.com/tidbcloud/observability/pkg/resourceworker/worker"
	controller_metrics "sigs.k8s.io/controller-runtime/pkg/metrics"
)

func main() {
	ctx := utils.SetupSignalHandler()

	flag.IntVar(&port, "port", constants.DefaultObservabilityRegionalServerPort, "listening port")
	flag.IntVar(&metricsPort, "metrics-port", constants.DefaultObservabilityRegionalDataServerMetricsPort, "listening metrics port")
	flag.StringVar(&vendor, "vendor", string(constants.AWS), "vendor")
	flag.BoolVar(&clientMode, "client-mode", true, "client mode (true: in-cluster, false: out-of-cluster)")
	// specify the kube config absolute path, required if the clientMode value is false.
	flag.StringVar(&kubeConfigPath, "kube-config-path", filepath.Join(homedir.HomeDir(), ".kube", "config"), "(optional) absolute path to the kube config file")
	flag.StringVar(&logLevel, "log-level", "info", "log level. default: info")
	flag.StringVar(&logDir, "log-dir", "./logs", "log dir. default: ./logs")
	flag.StringVar(&vmConfigPath, "vmConfigPath", "./config/vmconfig.yaml", "vm info config path. default: ./config/vmconfig.yaml")
	flag.StringVar(&accountInfoPath, "accountInfo", "./config/accountinfo.yaml", "account info config path. default: ./config/accountinfo.yaml")
	flag.StringVar(&bizTypeConfigPath, "bizTypeConfigPath", "./config/biztypeconfig.yaml", "bizType config file path. default: ./config/biztypeconfig.yaml")

	flag.Parse()
	// init log
	utils.InitLog(logLevel)
	log.Info("o11y data server running in vendor", zap.String("Vendor", vendor))
	// If clientMode is false (out-of-cluster) and the kubeConfigPath file does not exist, then exit
	if !clientMode && !utils.IsFile(kubeConfigPath) {
		log.Panic("please check if parameter `client-mode` or `kube-config-path` is correct.")
	}

	// build kube config
	var kubeConfig *rest.Config
	var err error
	if clientMode {
		// creates the in-cluster config
		kubeConfig, err = rest.InClusterConfig()
	} else {
		// creates the out-of-cluster config
		kubeConfig, err = clientcmd.BuildConfigFromFlags("", kubeConfigPath)
	}
	if err != nil {
		log.Panic("init kubeconfig failed", zap.Error(err))
	}
	//Load AZconfig from file
	vmConfig := configs.LoadVMConfig(vmConfigPath)
	accountInfo := configs.LoadAccountInfo(accountInfoPath)
	bizTypeConfigs := configs.LoadBizTypeConfigs(bizTypeConfigPath)

	region := accountInfo.Region
	logicalRegion := region
	if accountInfo.LogicalRegionName != "" {
		logicalRegion = accountInfo.LogicalRegionName
	}
	env := accountInfo.Env
	serviceInfo := structs.ServiceInfo{
		ServerName:        constants.ObservabilityRegionalDataServer,
		Port:              port,
		MetricsPort:       metricsPort,
		DefaultOversell:   defaultOversell,
		Vendor:            vendor,
		Region:            region,
		LogicalRegionName: logicalRegion,
		Env:               env,
		LogDir:            logDir,
		LogLevel:          logLevel,
		BizTypeConfigs:    bizTypeConfigs,
		EnableHttps:       false,
		AccountInfo:       accountInfo,
		VMClusterInfo:     vmConfig,
	}
	configs.Init(serviceInfo)

	err = providers.InitClient(serviceInfo)
	if err != nil {
		log.Panic("init provider client failed", zap.Error(err))
	}

	metrics.SetupMetrics(controller_metrics.Registry)

	worker.InitDataServerManager(ctx, serviceInfo)
	//Start Manager must before GetManager
	go worker.StartWorker(ctx)
	kubeConfig.QPS = 50
	kubeConfig.Burst = 100
	resourcemanager.InitReaderWriter(kubeConfig, worker.GetManager(), nil, true)

	dataapi.StartService(ctx, serviceInfo)

}
