package main

import (
	"context"
	"dataapps/commons/sentry"
	"flag"
	"fmt"
	"github.com/tidbcloud/pkgv2/version"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"github.com/tidbcloud/tiinf/monitor/titracing"
	"github.com/tidbcloud/tiinf/transport/http/tigin"
	"go.uber.org/zap"

	"dataapps/api"
	"dataapps/commons/config"
	"dataapps/commons/database"
	"dataapps/internal/controller/sqleditor"
)

const (
	componentName     = "chat2queryapi"
	defaultConfigPath = "/etc/dbaas/config.yaml"
)

func main() {
	var configPath string
	flag.StringVar(&configPath, "config-path", defaultConfigPath, "DBaaS configuration file path")
	flag.Parse()
	ctx := context.Background()

	// Load config
	err := config.InitConfig(configPath)
	if err != nil {
		panic(fmt.Sprintf("Initialize configuration failed, err: %+v", err))
	}

	setup(ctx)

	// Connect database
	centralConfig := config.Global()
	database.Connect(ctx, centralConfig)

	startup(ctx, centralConfig)
}

func internalSvc(ctx context.Context, centralConfig *config.CentralConfig) {
	serverConfig := centralConfig.ServerConfig

	engine := gin.Default()

	engine.POST("/api/v1/chat2data", sqleditor.InternalChat2Data)

	addr := serverConfig.Chat2QueryInternalAddr
	tilog.Info(ctx, "start to serve chat2query internal service", zap.String("addr", addr))
	err := engine.Run(addr)
	tilog.Error(ctx, "failed to serve chat2query internal service", zap.Error(err))
}

func startup(ctx context.Context, centralConfig *config.CentralConfig) {
	serverConfig := centralConfig.ServerConfig

	/* metrics */
	mEng := gin.Default()
	mEng.Any("/metrics", prometheusHandler())
	go mEng.Run("0.0.0.0:9091") //nolint:errcheck // no need check error

	// internal api service
	go internalSvc(ctx, centralConfig)

	ginEng := tigin.Default()
	api.DataApiRouters(ginEng)
	addr := serverConfig.Chat2QueryApiHttpListenAddr
	tilog.Info(ctx, "serving chat2queryapi HTTP Service", zap.String("address", addr))
	panic(fmt.Sprintf("chat2queryapi HTTP Service died %+v", ginEng.Run(addr)))
}

func setup(ctx context.Context) {
	//sentry
	err := sentry.SetupLoggerAndSentry(config.Global().SentryConf.DSN, config.Global().SentryConf.Environment, config.Global().SentryConf.LogLevel)
	if err != nil {
		panic(fmt.Sprintf("Initialize logger and sentry failed: %+v", err))
	}
	tilog.Info(context.Background(), fmt.Sprintf("Starting %s service", componentName),
		zap.String("gitHash", version.GitHash),
		zap.String("logLevel", config.Global().ServerConfig.LogLevel))
	// jaeger
	if _, err := titracing.InitJaeger(componentName); err != nil {
		tilog.Error(ctx, "init tiinf jaeger provider failed", zap.Error(err))
		panic(fmt.Sprintf("failed to init tracing, err=%v", err))
	}
}

func prometheusHandler() gin.HandlerFunc {
	h := promhttp.Handler()

	return func(c *gin.Context) {
		h.ServeHTTP(c.Writer, c.Request)
	}
}
