package regionalapi

import (
	"fmt"
	"net/http"
	"net/url"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/pingcap/log"
	"go.uber.org/zap"

	"github.com/tidbcloud/observability/pkg/common/configs"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/message"
	"github.com/tidbcloud/observability/pkg/regionalapi/apiinterceptor"
)

const observabilityVcpuPromQL = `sum(kube_node_status_capacity{resource="cpu",unit="core"})`
const defaultObservabilityVcpuStep = "30s"

// GetByocObservabilityVcpu queries regional self-monitoring prometheus and returns raw query_range result.
func GetByocObservabilityVcpu(c *gin.Context) {
	if !strings.EqualFold(c.Param("bizType"), constants.DefaultByocBizType) {
		apiinterceptor.Fail(c, errors.New(errors.UnsupportedBizType, "only byoc bizType is supported"))
		return
	}

	var params message.GetByocObservabilityVcpuReq
	if err := c.ShouldBindQuery(&params); err != nil {
		apiinterceptor.Fail(c, errors.New(errors.ParameterInvalid, err.Error()))
		return
	}
	if params.Step == "" {
		params.Step = defaultObservabilityVcpuStep
	}

	endpoint := strings.TrimRight(configs.GetServiceInfo().SelfMonitorEndpoint, "/")
	if endpoint == "" {
		apiinterceptor.Fail(c, errors.New(errors.UnrecognizedError, "self monitor endpoint is not configured"))
		return
	}

	targetURL := buildObservabilityVcpuURL(endpoint, observabilityVcpuPromQL, params.Start, params.End, params.Step)
	req, err := http.NewRequestWithContext(c, http.MethodGet, targetURL, nil)
	if err != nil {
		apiinterceptor.Fail(c, errors.New(errors.UnrecognizedError, err.Error()))
		return
	}

	resp, err := http.DefaultClient.Do(req)
	if err != nil {
		log.Error("query self monitor prometheus failed", zap.Error(err))
		apiinterceptor.Fail(c, errors.New(errors.UnrecognizedError, err.Error()))
		return
	}
	defer resp.Body.Close()

	for k := range resp.Header {
		for j := range resp.Header[k] {
			c.Header(k, resp.Header[k][j])
		}
	}
	c.DataFromReader(resp.StatusCode, resp.ContentLength, resp.Header.Get("Content-Type"), resp.Body, make(map[string]string))
}

func buildObservabilityVcpuURL(endpoint, promQL, start, end, step string) string {
	values := url.Values{}
	values.Set("query", promQL)
	values.Set("start", start)
	values.Set("end", end)
	values.Set("step", step)
	return fmt.Sprintf("%s/api/v1/query_range?%s", endpoint, values.Encode())
}
