package main

import (
	"context"
	"flag"
	"fmt"
	"time"

	"github.com/tidbcloud/account/commons/eventbus"

	"github.com/tidbcloud/account/central/events/receive"

	"github.com/tidbcloud/account/internel/controllers/openapi"

	"github.com/gin-gonic/gin"
	centralapi "github.com/tidbcloud/account/central/api"
	"github.com/tidbcloud/account/central/server"
	"github.com/tidbcloud/account/central/utils"
	"github.com/tidbcloud/account/commons/config"
	grpc_errcode "github.com/tidbcloud/account/pkg/grpc/middleware/errcode"
	"github.com/tidbcloud/account/pkg/version"
	"github.com/tidbcloud/idl/pbgen/openapi/openapi/cbp"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	auditlogsdk "github.com/tidbcloud/tiinf/sdk/auditlog"
	"go.uber.org/zap"
)

const (
	componentName     = "account-openapi"
	defaultConfigPath = "/etc/dbaas/config.yaml"
)

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

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

	err = utils.SetupLoggerAndSentry()
	if err != nil {
		panic(fmt.Sprintf("Initialize logger and sentry failed: %+v", err))
	}

	ctx := context.Background()
	if !config.IsLocalEnv() {
		err = auditlogsdk.InitAuditLogSDK(ctx, time.Second*5)
		if err != nil {
			tilog.Panic(ctx, "failed to init auditlog sdk", zap.Error(err))
		}
	}

	tilog.Info(ctx, fmt.Sprintf("starting %s service", componentName),
		zap.String("gitHash", version.GitHash),
		zap.String("logLevel", config.Global().ServerConfig.LogLevel))

	s, err := server.NewServer(configPath, server.GRPCAuthTypeOpenAPI, grpc_errcode.ErrorFormatOpenAPI)
	if err != nil {
		panic(fmt.Sprintf("Failed to create server: %+v", err))
	}

	if !config.IsLocalEnv() {
		err = eventbus.Get().Run()
		if err != nil {
			tilog.Fatal(ctx, "Initialize event bus handler failed", zap.Error(err))
		}
	}

	registerGRPCServices(s)
	err = registerHTTPHandlers(s)
	if err != nil {
		panic(fmt.Sprintf("Register HTTP handlers failed: %+v", err))
	}
	initHTTPRouter(s)
	server.StartOpenApiGrpcGateway(s)
	err = s.Run()
	if err != nil {
		panic(fmt.Sprintf("Run server failed: %+v", err))
	}
	go receive.RedisSubscribe(context.Background())
}

func registerGRPCServices(s *server.Server) {
	cbp.RegisterProjectServer(s.TiInf.GrpcServer(), openapi.NewProjectService())
}

func registerHTTPHandlers(s *server.Server) error {
	return s.HTTPGateway.Register(
		context.Background(),
		cbp.RegisterProjectHandler,
	)
}

func initHTTPRouter(s *server.Server) {
	ginEng := s.HTTPGateway.Engine()

	// Register handlers
	ginEng.Any("/healthz", func(c *gin.Context) {
		c.Status(200)
	})

	centralapi.RegisterScimRouter(ginEng)
	centralapi.RegisterProjectRouter(ginEng)
	centralapi.RegisterMspCustomerRouter(ginEng)
	centralapi.RegisterApiKeyRouter(ginEng)
	centralapi.RegisterDbusertRouter(ginEng)
	centralapi.RegisterSqlUserRouter(ginEng)
	centralapi.RegisterUserRouter(ginEng)
	centralapi.RegisterUsersRouter(ginEng)

}
