package billing

import (
	"net/http"
	"net/http/httputil"

	"github.com/gin-gonic/gin"
	"github.com/go-logr/logr"
	ctrl "github.com/tidbcloud/devops/pkg/controller"
	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/consts"
	"go.uber.org/dig"
)

type ControllerParam struct {
	dig.In

	Conf   *config.RootConfig
	Logger logr.Logger
}

type BillingController struct {
	billingAddr string
	logger      logr.Logger
	rateLimit   *proxyRateLimiter
}

func (c *BillingController) Name() string {
	return "BillingController"
}

func NewBillingController(p ControllerParam) ctrl.Controller {
	logger := p.Logger.WithName("BillingController")
	return &BillingController{
		billingAddr: p.Conf.DbaasAddr.BillingServiceAddr,
		logger:      logger,
		rateLimit:   newProxyRateLimiter(p.Conf.Controllers.BillingProxy.RateLimit, logger.WithName("RateLimit")),
	}
}

func (c *BillingController) RegisterAPI(suite *ctrl.Suite) error {
	r := suite.Router
	{
		r.Any("/billing-proxy/*any", c.rateLimit.Middleware(), c.BillingProxy)
	}
	return nil
}

func (c *BillingController) BillingProxy(ctx *gin.Context) {
	c.logger.Info("handle billing proxy", "method", ctx.Request.Method, "path", ctx.Request.URL.Path, "user", ctx.GetString(consts.CtxOperator))

	proxyPath := ctx.Params.ByName("any")
	director := func(req *http.Request) {
		req.URL.Scheme = "http"
		req.URL.Host = c.billingAddr
		req.URL.Path = proxyPath
		req.Header.Set("X-BILLING-REQUEST-SOURCE", "ops")
		req.Header.Set("X-ACCOUNT-USER-EMAIL", ctx.GetString(consts.CtxOperator))
	}
	proxy := &httputil.ReverseProxy{Director: director}
	modifyFunc := func(resp *http.Response) error {
		resp.Header.Del("Access-Control-Allow-Origin")
		return nil
	}
	proxy.ModifyResponse = modifyFunc
	proxy.ServeHTTP(ctx.Writer, ctx.Request)
}
