package app

import (
	"net/http"

	"github.com/gin-contrib/pprof"
	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/tiinf/sdk/cors"
	"github.com/tidbcloud/tiinf/tiinf"
	"github.com/tidbcloud/tiinf/transport/http/tigin"

	console "github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/bff"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/common"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/compat"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/inner"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/app/openapi"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/apimiddleware/grpcerror"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/apimiddleware/response"
	"github.com/tidbcloud/tidb-management-service/tidb-mgmt-portal/pkg/version"
	"github.com/tidbcloud/tidb-management-service/utilities/httputil"
)

func Register(eng *gin.Engine) error {
	// Set up tiinf gin engine.
	eng.Handlers = make([]gin.HandlerFunc, 0)
	serviceName, err := tiinf.ServiceNameFromEnv()
	if err != nil {
		return err
	}
	eng.Use(
		gin.Recovery(),
		httputil.GinServerPayloadLogger,
		tigin.RecordMetrics,
		httputil.NewGinServerTracer(serviceName),
		tigin.SetResponseTraceID,
	)

	pprof.Register(eng)

	eng.Use(
		cors.GinNew(common.GetCorsOptions()),
		response.WriterWrapperHandler,    // modify response body middleware
		grpcerror.ModifyGrpcErrorHandler, // modify grpc error middleware
	)

	eng.Any("/healthz", func(c *gin.Context) {
		c.Status(200)
	})
	eng.Any("/version", gin.WrapF(version.Handler))

	eng.GET("/ping", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "pong",
		})
	})

	// init internal compat handler
	if err := compat.SetupCompatApiHandler(eng, 0); err != nil {
		return err
	}

	if err := inner.SetupInnerApiHandler(eng, 0); err != nil {
		return err
	}

	if err := console.SetupConsoleApiHandler(eng, 0); err != nil {
		return err
	}
	if err := console.SetupOneConsoleApiHandler(eng, 0); err != nil {
		return err
	}

	// only dedicated or serverless openapi handlers are registered here
	if err := openapi.SetupOpenApiHandler(eng, 0); err != nil {
		return err
	}

	// init TiDBX handler
	if err := openapi.SetupTiDBXApiHandler(eng, 0); err != nil {
		return err
	}
	// init TiDB Zero handler
	if err := openapi.SetupTiDBZeroApiHandler(eng, 0); err != nil {
		return err
	}
	return nil
}
