package tepapis

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/pingcap/tep/db/entity"
	"github.com/pingcap/tep/pkg/apis/apiserver/v1alpha1"
	"github.com/pingcap/tep/pkg/apis/tepserver/types"
	"github.com/pingcap/tep/pkg/tepserver/filters"
	"github.com/pingcap/tep/pkg/utils"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"net/http"
	"time"
)

func (api *API) Logout(c *gin.Context) {
	startTime := time.Now()
	filters.Logout(c)
	utils.SendMsg(c, &metav1.TypeMeta{
		APIVersion: v1alpha1.SchemeGroupVersion.String(),
		Kind:       utils.TEPKindResponse,
	}, utils.NewAPIStatus(http.StatusOK, ""))
	utils.AddEventAndLogError(api.Server.DB, &utils.Event{
		UserID:         utils.GetUsername(c),
		Payload:        "Logout",
		OperationType:  entity.AdminOperation,
		ManagementType: entity.UserManagement,
		CostTime:       time.Now().Sub(startTime).Nanoseconds(),
	})
}

func (api *API) Login(c *gin.Context) {
	startTime := time.Now()
	login := &types.Login{}
	if err := c.ShouldBindJSON(login); err != nil {
		msg := fmt.Sprintf("invalid request body: %v", err)
		utils.SendMsg(c, nil, utils.NewAPIStatus(http.StatusBadRequest, msg))
		return
	}
	token, err := filters.Login(c, login.Username, login.Password)
	if err != nil {
		// Return 200 OK instead of 401 Unauthorized on authentication failure,
		// this is by intent, to make front end's error handling simpler
		utils.SendMsg(c, &metav1.Status{
			TypeMeta: metav1.TypeMeta{
				APIVersion: v1alpha1.SchemeGroupVersion.String(),
				Kind:       utils.TEPKindStatus,
			},
			Message: err.Error(),
			Code:    http.StatusUnauthorized,
		}, utils.NewAPIStatus(http.StatusOK, ""))
	} else {
		utils.SendMsg(c, &types.LoginResponse{
			APIVersion: v1alpha1.SchemeGroupVersion.String(),
			Kind:       utils.TEPKindResponse,
			AuthToken:  token,
		}, utils.NewAPIStatus(http.StatusOK, ""))
	}
	utils.AddEventAndLogError(api.Server.DB, &utils.Event{
		UserID:         login.Username,
		Payload:        "Login",
		OperationType:  entity.AdminOperation,
		ManagementType: entity.UserManagement,
		CostTime:       time.Now().Sub(startTime).Nanoseconds(),
		Result:         fmt.Sprintf("%v", err == nil),
	})
}

func (api *API) Dummy(c *gin.Context) {
	utils.SendMsg(c, &metav1.TypeMeta{
		APIVersion: v1alpha1.SchemeGroupVersion.String(),
		Kind:       utils.TEPKindResponse,
	}, utils.NewAPIStatus(http.StatusOK, ""))
}
