package main

import (
	"context"
	"flag"

	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/pingcap-inc/clinic/pkg/api"
	"github.com/pingcap-inc/clinic/pkg/compute_engine"
	"github.com/pingcap-inc/clinic/pkg/config"
	"github.com/pingcap-inc/clinic/pkg/db"
	unstableplance "github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/compute_engine"
	perftask "github.com/pingcap-inc/clinic/pkg/ngm/performance_insight/task"
	"github.com/pingcap-inc/clinic/pkg/task_manager"
	"github.com/pingcap-inc/clinic/pkg/task_manager/task"
	"github.com/pingcap-inc/clinic/pkg/task_manager/task/healthcheck"
	_import "github.com/pingcap-inc/clinic/pkg/task_manager/task/import"
	"github.com/pingcap-inc/clinic/pkg/task_manager/task/report"
)

var cfgPath string

func main() {
	// task manager
	flag.StringVar(&cfgPath, "c", "./", "impotered -c=/path/to/config.yaml")
	flag.Parse()

	// no need to load dashboard config
	cfg, err := config.InitConfig(cfgPath)
	if err != nil {
		panic(err)
	}

	if err != cfg.LoadDashboard() {
		log.Fatal("load dashboard config failed", zap.Error(err))
	}

	err = db.Initialize(cfg.DBConfig, true)
	if err != nil {
		log.Error("init db failed", zap.Error(err))
		panic(err)
	}

	kc, err := task.NewK8sClient(cfg.K8sConfig)
	if err != nil {
		log.Error("new k8s client failed", zap.Error(err))
		panic(err)
	}

	globalLimit := task.NewGlobalLimit(kc)

	compute_engine.GlobalCMClient = compute_engine.NewCMClient(cfg)

	engine := gin.Default()

	pprof.Register(engine)

	api.InitMetricsApi(engine)

	// for normal rebuild event, such as import metrics, log, configuration to vm, es and ?
	scanner := _import.NewScannerService(kc, globalLimit)
	if !cfg.DisableInNewDeployment {
		scanner.Start()
	} else {
		log.Info("Scanner dsiabled")
	}

	// for reporter related event, such as generate health report etc
	reportScanner := report.NewReportScannerService(kc, globalLimit)
	if !cfg.DisableInNewDeployment {
		reportScanner.Start()
	} else {
		log.Info("Reporter scanner dsiabled")
	}

	if cfg.EnablePerformanceInsight {
		perfInsightScanner := perftask.NewPerformanceInsightScanner(
			unstableplance.NewComputerEngineClient(cfg.GetComputeEngineEndPoint(), cfg.CentralO11yConfig.Env))
		if err := perfInsightScanner.Start(); err != nil {
			log.Panic("start performance insight scanner failed", zap.Error(err))
		}
	}

	// Start health check scanner
	healthCheckScanner := healthcheck.NewScannerService(cfg)
	if !cfg.DisableInNewDeployment {
		healthCheckScanner.Start()
	} else {
		log.Info("Health check scanner disabled")
	}

	if err := task_manager.NewAPIService(&task_manager.APIServiceParams{
		Gin:     engine,
		Ctx:     context.Background(),
		Cfg:     cfg,
		Scanner: scanner,
	}).Start(); err != nil {
		log.Fatal("can not start server", zap.Error(err))
	}

	log.Panic("start server failed", zap.Error(engine.Run(cfg.ServerConfig.Addr)))
}
