package api

import (
	"errors"
	"github.com/pingcap/dbaas/cost-metering-service/billing_errors"
	"github.com/pingcap/dbaas/cost-metering-service/forms"
	"github.com/pingcap/dbaas/cost-metering-service/model/billing"
	"github.com/pingcap/dbaas/cost-metering-service/utils/ginutils"

	"github.com/gin-gonic/gin"
)

// @Summary Create Unit
// @Schemes
// @Accept json
// @Produce json
// @Param unit body forms.UnitInfo true "unit"
// @Success 200 {object} forms.UnitInfo
// @Router /units [post]
func (s *API) CreateUnit(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	unitform := &forms.UnitInfo{}
	if err := c.ShouldBindJSON(unitform); err != nil {
		return nil, billing_errors.NewInvalidInputError(err)
	}

	model := &billing.UnitModel{}
	if unitform.CostCenterOrgID == 0 {
		return nil, billing_errors.NewInvalidInputError(errors.New("cost center id must be have"))

	}

	info, err := model.CreateAndUpdateUnit(unitform)
	if err != nil {
		return nil, err
	}
	return info, nil
}

// @Summary Update Unit
// @Schemes
// @Accept json
// @Produce json
// @Param unit_key path string true "UnitKey"
// @Success 200 {object} forms.UnitInfo
// @Router /units/{unit_key} [put]
func (s *API) UpdateUnit(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	uriForm := &UnitURIForm{}

	if err := c.ShouldBindUri(&uriForm); err != nil {
		return nil, billing_errors.NewInvalidInputError(err)
	}

	unitform := &forms.UnitInfo{}
	if err := c.ShouldBindJSON(unitform); err != nil {
		return nil, err
	}

	unitform.UnitKey = uriForm.UnitKey

	model := &billing.UnitModel{}

	info, err := model.CreateAndUpdateUnit(unitform)
	if err != nil {
		return nil, err
	}
	return info, nil
}

// @Summary List Units
// @Schemes
// @Accept json
// @Produce json
// @Success 200 {object} []forms.UnitInfo
// @Router /units [get]
func (s *API) ListUnits(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	model := &billing.UnitModel{}
	units, err := model.GetAllUnits()
	if err != nil {
		return nil, err
	}
	return units, nil
}

type UnitURIForm struct {
	UnitKey string `uri:"unit_key"` //nolint
}

// @Summary Get Unit
// @Schemes
// @Accept json
// @Produce json
// @Param unit_key path string true "UnitKey"
// @Success 200 {object} forms.UnitInfo
// @Router /units/{unit_key} [get]
func (s *API) GetUnit(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	uriForm := &UnitURIForm{}

	if err := c.ShouldBindUri(&uriForm); err != nil {
		return nil, err
	}

	model := &billing.UnitModel{}
	unitInfo, err := model.GetUnit(uriForm.UnitKey)
	if err != nil {
		return nil, err
	}
	return unitInfo, nil
}

// @Summary Delete Unit
// @Schemes
// @Accept json
// @Produce json
// @Param unit_key path string true "UnitKey"
// @Success 200 {object} forms.OKType
// @Router /units/{unit_key} [delete]
func (s *API) DeleteUnit(c *gin.Context) (ginutils.HandlerFuncResult, error) {
	uriForm := &UnitURIForm{}

	if err := c.ShouldBindUri(&uriForm); err != nil {
		return nil, billing_errors.NewInvalidInputError(err)
	}

	model := &billing.UnitModel{}
	err := model.DeleteUnit(uriForm.UnitKey)
	if err != nil {
		return nil, err
	}
	return forms.OK, nil
}

func InitializeUnitRouter(router ginutils.MyRoute) {
	api := &API{}
	router.HandleWithError("GET", "/units", api.ListUnits)
	router.HandleWithError("POST", "/units", api.CreateUnit)
	router.HandleWithError("GET", "/units/:unit_key", api.GetUnit)
	router.HandleWithError("PUT", "/units/:unit_key", api.UpdateUnit)
	router.HandleWithError("DELETE", "/units/:unit_key", api.DeleteUnit)
}
