package app

import (
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/prometheus/client_golang/prometheus/promhttp"
	"go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin"
	"go.uber.org/dig"

	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/apiserver/middlewares"
	"github.com/tidbcloud/aisupport/packages/sdk-go/infra/logger"
	"github.com/tidbcloud/aisupport/services/ticket-manager/config"
)

const (
	APIRoutePath    apiserver.RoutePath = "/api/v1/ticketmanager"
	PublicRoutePath apiserver.RoutePath = "/public/v1/ticketmanager"
)

type HandlerResult struct {
	dig.Out

	Handler apiserver.Handler `group:"apiHandlers"`
}

type APIServerParam struct {
	dig.In

	Config   *config.RootConfig
	Handlers []apiserver.Handler `group:"apiHandlers"`
}

// NewAPIServer return a api server for ticket manager
//
//	@title			Ticket Manager API
//	@version		1.0
//	@description	ticket maganger
//	@query.collection.format	multi
func NewAPIServer(param APIServerParam) (*apiserver.APIServer, error) {
	logger := logger.Logger.WithName("APIServer")

	return apiserver.NewAPIServer(apiserver.APIServerParam{
		Address: param.Config.APIServer.Address,
		RoutePaths: []apiserver.RoutePath{
			APIRoutePath,
			PublicRoutePath,
		},
		Logger:   logger,
		Handlers: param.Handlers,

		PreInitRoute: func(root gin.IRouter) error {
			logMW := middlewares.LogMetricMiddlewareBuilder{
				Request: middlewares.RequestLoggerOptions{
					Logger: logger,
					FilterFunc: func(c *gin.Context) bool {
						if c.Request.Method == http.MethodOptions {
							return true
						}
						if c.FullPath() == "/healthz" || c.FullPath() == "/metrics" {
							return true
						}
						return false
					},
				},
			}

			root.Use(
				otelgin.Middleware("ticket-manager"),
				logMW.Build(),
				middlewares.RecoveryMiddleware(logger),
				middlewares.CorsMiddleware(),
			)
			root.GET("/healthz", gin.WrapF(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(200) }))
			root.GET("/metrics", gin.WrapH(promhttp.Handler()))
			return nil
		},
	})
}
