package handler

import (
	"net/http"

	"github.com/labstack/echo/v4"
	"github.com/pingcap/tidb-operator/pkg/apis/pingcap/v1alpha1"
	echoSwagger "github.com/swaggo/echo-swagger"

	"github.com/pingcap/test-infra/common/errors"

	_ "github.com/pingcap/test-infra/services/rms/tc-validator/docs"
	"github.com/pingcap/test-infra/services/rms/tc-validator/middleware"
)

type Handler struct{}

func NewHandler() *Handler {
	return &Handler{}
}

// @Title tc-validator API
// @Version 1.0
// @BasePath /api/v1
// @produce	application/json
// @consumes application/json
func NewHTTPServer(h *Handler) *echo.Echo {
	e := echo.New()
	middleware.UseCommonMiddlewares(e)

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

	v1 := e.Group("/api/v1")
	{
		v1.POST("/validate", h.ValidateTc)
	}
	return e
}

// ValidateRequestBody wraps v1alpha1.TidbClusterSpec and v1alpha1.TidbMonitorSpec
type ValidateRequestBody struct {
	TC *v1alpha1.TidbClusterSpec `json:"tc"`
	TM *v1alpha1.TidbMonitorSpec `json:"tm"`
}

// ValidateTc ...
// @Summary validate tidb-cluster specification
// @Tags validate
// @Accept json
// @Produce json
// @Param resource body ValidateRequestBody true "tidbClusterSpec"
// @Success 200 {object} string
// @Failure 400 {object} errors.StatusError
// @Router /credential/ [post]
func (h Handler) ValidateTc(ctx echo.Context) error {
	var spec ValidateRequestBody
	if err := ctx.Bind(&spec); err != nil {
		ctx.Logger().Errorf("validate tc error: %v", err)
		return WriteStatusError(ctx, errors.NewBadRequest(err.Error()))
	}
	if spec.TC == nil {
		return WriteStatusError(ctx, errors.NewBadRequest("tc must be non-empty"))
	}
	if spec.TM == nil {
		return WriteStatusError(ctx, errors.NewBadRequest("tm must be non-empty"))
	}
	return ctx.JSON(http.StatusOK, nil)
}

// WriteStatusError write the http status and the error string on the response. err can be nil.
func WriteStatusError(ctx echo.Context, err *errors.StatusError) error {
	return ctx.JSON(int(err.Code), err)
}
