package billing

import (
	"encoding/base64"
	"encoding/json"

	"github.com/gin-gonic/gin"

	srvv1 "github.com/pingcap-inc/pchub/internal/apiserver/service/v1"
	"github.com/pingcap-inc/pchub/internal/apiserver/store"
	"github.com/pingcap-inc/pchub/internal/pkg/code"
	modelv1 "github.com/pingcap-inc/pchub/model/v1"
	bfao "github.com/pingcap-inc/pchub/model/v1/fao/billing"
	"github.com/pingcap-inc/pchub/pkg/errors"
	"github.com/pingcap-inc/pchub/pkg/log"
	"github.com/pingcap-inc/pchub/pkg/util/ginres"
)

type BillingController struct {
	srv srvv1.Service
}

func NewBillingController(store store.Factory) *BillingController {
	return &BillingController{
		srv: srvv1.NewService(store),
	}
}

func (b *BillingController) List(c *gin.Context) {
	log.L(c).Info("BillingController.List function called.")

	params := ginres.ParseQuery(c, "fao", "page", "psize")

	lParam, err := modelv1.NewListParam().Parse(c, params)
	if err != nil {
		ginres.WriteResponse(c, err, nil)

		return
	}

	faoStr, err := base64.StdEncoding.DecodeString(params["fao"])
	if err != nil {
		log.L(c).Error("Fail to decode fao using base64.StdEncoding.DecodeString, faoBase64: " + params["fao"] + ", err: " + err.Error())
		ginres.WriteResponse(c, errors.WithCode(code.ErrValidation, err.Error()), nil)

		return
	}

	var fao bfao.BillingFAO
	if string(faoStr) != "" {
		log.L(c).Info("fao: " + string(faoStr))

		if err = json.Unmarshal(faoStr, &fao); err != nil {
			log.L(c).Error("Fail to unmarshal fao, fao: " + string(faoStr) + ", err: " + err.Error())
			ginres.WriteResponse(c, errors.WithCode(code.ErrValidation, err.Error()), nil)

			return
		}
	}

	if err = fao.ValidateComplete(c); err != nil {
		ginres.WriteResponse(c, err, nil)

		return
	}

	res, err := b.srv.Billing().ListGroupByResource(c, lParam, fao)
	if err != nil {
		ginres.WriteResponse(c, err, nil)

		return
	}

	ginres.WriteResponse(c, nil, res)
}

func (b *BillingController) CheckCostAlerts(c *gin.Context) {
	log.L(c).Info("BillingController.CheckCostAlerts function called.")
	ginres.WriteResponse(c, nil, "Start check billing-alerts")

	err := b.srv.Billing().CheckCostAlerts(c)
	if err != nil {
		log.L(c).Errorf("Error when run check billing-alerts: %s", err.Error())

		return
	}
	log.L(c).Info("Check billing-alerts successfully")
}
