package main

import (
	"context"
	"database/sql"
	"dataservices/api"
	"dataservices/commons/config"
	"dataservices/commons/database"
	"dataservices/commons/eventbus"
	"dataservices/commons/logger"
	"dataservices/commons/metrics"
	"dataservices/ddb"
	"flag"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"github.com/tidbcloud/tiinf/tiinf"
	tigrpc "github.com/tidbcloud/tiinf/transport/tigrpc/server"
	"go.uber.org/zap"
)

const (
	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()
	err := config.InitConfig(configPath)
	if err != nil {
		tilog.Fatal(ctx, "Initialize configuration failed", zap.Error(err))
	}

	cfg := config.Global()
	tilog.Info(context.Background(), "service config", logger.Redact("config", cfg), zap.String("env", config.CurrentEnv()))
	db := database.Connect(
		ctx,
		cfg.MysqlConf.User,
		cfg.MysqlConf.Password,
		cfg.MysqlConf.Host,
		cfg.MysqlConf.Port,
		cfg.MysqlConf.Database,
		cfg.MysqlConf.CharSet,
		cfg.MysqlConf.TimeZone,
	)
	eventbusStartup(ctx, db)
	if !cfg.ServerConf.LocalMode {
		if err := ddb.Init(ctx, cfg); err != nil {
			tilog.Fatal(ctx, "Initialize dynamodb client failed", zap.Error(err))
		}
	}

	metrics.RegisterCentralMetrics()

	inf := tiinf.NewInf()
	err = inf.Init(
		tiinf.WithConfigFile(configPath),
		tiinf.WithGrpcOptions(
			tigrpc.WithUnaryInterceptors(
				api.ErrorConvertUnaryServerInterceptor(),
			),
		),
	)
	if err != nil {
		tilog.Fatal(ctx, "Initialize tiinf failed", zap.Error(err))
	}

	api.RegisterGrpcServices(inf.GrpcServer())
	tiinfCfg, err := tiinf.ParseConfigFromFile(configPath)
	if err != nil {
		tilog.Fatal(ctx, "Parse tiinf config failed", zap.Error(err))
	}
	err = api.SetupHttpServer(inf.GinEngine(), *tiinfCfg)
	if err != nil {
		tilog.Fatal(ctx, "Setup HTTP server failed", zap.Error(err))
	}

	err = inf.Run()
	if err != nil {
		tilog.Fatal(ctx, "Run tiinf failed", zap.Error(err))
	}
}

func eventbusStartup(ctx context.Context, db *sql.DB) {
	if config.IsLocalMode() {
		return
	}
	bus := eventbus.Init("dataservice_adminapi", db)
	if err := bus.Run(); err != nil {
		tilog.Fatal(ctx, "Eventbus run failed", zap.Error(err))
	}
}
