package controller

import (
	"net/http"

	"github.com/gin-gonic/gin"

	"github.com/pingcap-inc/security/baseline/api/v1/controller/errors"
	"github.com/pingcap-inc/security/baseline/pkg/log"
)

type ResultMark struct {
	Code    int    `json:"code"`
	Message string `json:"message"`
}

type CommonResult struct {
	ResultMark
	Data interface{} `json:"data"`
}

type PageRequest struct {
	Page     int `form:"page" json:"page" validate:"required,gte=1"`
	PageSize int `form:"page_size" json:"page_size"`
}

type Page struct {
	PageRequest
	Total int64 `json:"total"`
}

var DefaultPageRequest = PageRequest{
	1,
	20,
}

type ResultWithPage struct {
	ResultMark
	Data interface{} `json:"data"`
	Page Page        `json:"page"`
}

func HandleHttpResponse(c *gin.Context, err error,
	withStatusCode func() (errors.BL_ERROR_CODE, string),
	withData func() (interface{}, error), withPage func() Page) {
	if err != nil {
		log.Logger.Error(err.Error())
		c.JSON(http.StatusInternalServerError, Fail(int(errors.BL_INTERNAL_SERVER_ERROR), err.Error()))
		return
	}

	if withStatusCode != nil {
		code, message := withStatusCode()
		if code != errors.BL_SUCCESS {
			log.Logger.Error(message)
			c.JSON(code.GetHttpCode(), Fail(int(code), message))
			return
		}
	}

	data, err := withData()
	if err != nil {
		log.Logger.Error(err.Error())
		c.JSON(http.StatusInternalServerError, Fail(int(errors.BL_UNRECOGNIZED_ERROR), err.Error()))
		return
	}

	if withPage != nil {
		c.JSON(http.StatusOK, SuccessWithPage(data, withPage()))
	} else {
		c.JSON(http.StatusOK, Success(data))
	}
}

func Success(data interface{}) *CommonResult {
	return &CommonResult{ResultMark: ResultMark{0, "OK"}, Data: data}
}

func SuccessWithPage(data interface{}, page Page) *ResultWithPage {
	return &ResultWithPage{ResultMark: ResultMark{0, "OK"}, Data: data, Page: page}
}

func Fail(code int, message string) *CommonResult {
	return &CommonResult{ResultMark{code, message}, struct{}{}}
}
