package handler

import (
	"net/http"

	"github.com/labstack/echo/v4"
	echoSwagger "github.com/swaggo/echo-swagger"

	"github.com/pingcap/test-infra/services/rms/config"
	_ "github.com/pingcap/test-infra/services/rms/docs" // import swag generated docs to serve API doc page
	"github.com/pingcap/test-infra/services/rms/metrics"
	mw "github.com/pingcap/test-infra/services/rms/middleware"
	"github.com/pingcap/test-infra/services/rms/service/resource"
)

type Handler struct {
	Service           resource.ServiceInterface
	StatisticsService resource.StatisticsService
}

func NewHandler(service resource.ServiceInterface, statisticsService resource.StatisticsService) *Handler {
	return &Handler{Service: service, StatisticsService: statisticsService}
}

// NewHTTPServer @Title RMs API
// @Version 1.0
// @BasePath /api/v1
// @produce	application/json
// @consumes application/json
// @securityDefinitions.apikey Bearer
// @in header
// @name Authorization
func NewHTTPServer(h *Handler) *echo.Echo {
	e := echo.New()
	mw.UseCommonMiddlewares(e)

	e.GET("/ping", func(c echo.Context) error { return c.String(http.StatusOK, "pong") })
	e.GET("/swagger/*", echoSwagger.WrapHandler)
	e.GET("/metrics", metrics.Handler())

	v1 := e.Group("/api/v1")
	{
		testbed := v1.Group("/testbed")
		if config.DefaultRMSConfiguration.EnsureAuthenticated {
			testbed.Use(mw.EnsureAuthenticated)
		}
		testbed.GET("", h.GetTestbedDeprecated)
		testbed.GET("/list", h.ListTestbed)
		testbed.POST("", h.CreateTestbed)
		testbed.POST("/restore-monitor", h.RestoreMonitor)
		testbed.POST("/auth", h.AuthTestbedDeprecated)
		testbed.DELETE("", h.DeleteTestbedDeprecated)
		testbed.PUT("/complete", h.CompleteTestbedDeprecated)
		testbed.PUT("/renewal", h.RenewalLeaseDeprecated)

		var authMiddleWare []echo.MiddlewareFunc
		if config.DefaultRMSConfiguration.EnsureAuthenticated {
			authMiddleWare = append(authMiddleWare, mw.EnsureAuthenticated)
		}
		testbeds := v1.Group("/testbeds")
		testbeds.GET("/list", h.ListTestbed, authMiddleWare...)
		testbeds.POST("", h.CreateTestbed, authMiddleWare...)
		testbeds.GET("/:name", h.GetTestbed)
		testbeds.GET("/:name/check", h.CheckTestbed, authMiddleWare...)
		testbeds.POST("/:name/restore-monitor", h.RestoreMonitor, authMiddleWare...)
		testbeds.PUT("/:name/auth", h.AuthTestbed, authMiddleWare...)
		testbeds.PUT("/:name/complete", h.CompleteTestbed, authMiddleWare...)
		testbeds.DELETE("/:name", h.DeleteTestbed, authMiddleWare...)
		testbeds.GET("/:name/lease", h.GetLease, authMiddleWare...)
		testbeds.PUT("/:name/lease/renew", h.RenewLease, authMiddleWare...)
		testbeds.GET("/:name/log_links", h.GetLogLinks, authMiddleWare...)
		testbeds.GET("/:name/shoot-kubeconfig", h.GetShootKubeConfig, authMiddleWare...)

		resourcePool := v1.Group("/resource-pool")
		resourcePool.GET("/status", h.GetResourcePoolStatus)
		resourcePool.GET("/testbeds-resource", h.GetTestbedsResource)
		resourcePool.GET("/testbed-resource-overtime", h.GetTestbedResourceOvertime)

		cert := v1.Group("/credential", mw.EnsureAuthenticated)
		cert.POST("", h.GenerateCredential)
		cert.GET("/aws-ecr", h.GetTemporaryECRImageSyncCredential)

		proxy := v1.Group("/proxy")
		proxy.GET("", h.GetProxy)
	}
	return e
}
