package api

import (
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"github.com/tidbcloud/cost-collect/pkg/cost"
	"github.com/tidbcloud/cost-collect/pkg/global"
	log2 "github.com/tidbcloud/pkgv2/log"
)

type ProviderCostAPI struct {
	manager *cost.Manager
}

// GetProviderCost bill from cloud provider
func (t ProviderCostAPI) GetProviderCost(c *gin.Context) {
	request := global.Request{}
	err := c.BindJSON(&request)

	if err != nil {
		log.S().Errorf("json error:%s", err)
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: err.Error()})
		return
	}

	// check time format
	_, err = time.Parse(global.TimeTemplate, request.StartTime)
	if err != nil {
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: fmt.Sprintf("keyError:%s,%s", "start_time", err)},
		)
		return
	}
	_, err = time.Parse(global.TimeTemplate, request.EndTime)
	if err != nil {
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: fmt.Sprintf("keyError:%s,%s", "end_time", err)},
		)
		return
	}
	if request.TenantID == 0 {
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: fmt.Sprintf("'tenant_id' is required")},
		)
		return
	}

	ctx := c.Request.Context()
	items, err := t.manager.QueryBill(ctx, request)
	if err != nil {
		c.JSON(http.StatusInternalServerError, global.Response{Code: http.StatusInternalServerError, ErrMessage: err.Error()})
		return
	}

	response := global.Bill{Request: request, Data: items}
	c.JSON(http.StatusOK, global.Response{Code: http.StatusOK, Data: response})
}

// StreamProviderCost bill from cloud provider
func (t ProviderCostAPI) StreamProviderCost(c *gin.Context) {
	request := global.Request{}
	err := c.BindJSON(&request)
	if err != nil {
		log.S().Errorf("json error:%s", err)
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: err.Error()})
		return
	}
	logger := log2.WithContextS(c.Request.Context())
	logger.Infof("request: %+v", request)

	// check time format
	_, err = time.Parse(global.TimeTemplate, request.StartTime)
	if err != nil {
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: fmt.Sprintf("keyError:%s,%s", "start_time", err)},
		)
		return
	}
	_, err = time.Parse(global.TimeTemplate, request.EndTime)
	if err != nil {
		c.JSON(http.StatusBadRequest,
			global.Response{Code: http.StatusBadRequest, ErrMessage: fmt.Sprintf("keyError:%s,%s", "end_time", err)},
		)
		return
	}

	ctx := c.Request.Context()
	if err := t.manager.StreamBill(ctx, request); err != nil {
		c.JSON(http.StatusInternalServerError, global.Response{Code: http.StatusInternalServerError, ErrMessage: err.Error()})
		return
	}

	response := global.Bill{Request: request, Data: nil}
	c.JSON(http.StatusOK, global.Response{Code: http.StatusOK, Data: response})

}

func (t ProviderCostAPI) Load(g *gin.RouterGroup) {
	g.POST("/provider/cost", t.GetProviderCost)
	g.POST("/provider/stream_cost", t.StreamProviderCost)
}

// NewProviderCostAPI new api
func NewProviderCostAPI(manager *cost.Manager) *ProviderCostAPI {
	p := &ProviderCostAPI{manager: manager}
	return p
}
