package regionalapi

import (
	"encoding/json"
	"net/http"
	"net/http/httptest"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"

	"github.com/tidbcloud/observability/pkg/common/configs"
	"github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/message"
	"github.com/tidbcloud/observability/pkg/common/structs"
)

func Test_buildObservabilityVcpuURL(t *testing.T) {
	got := buildObservabilityVcpuURL("http://prom:9090", `sum(kube_node_status_capacity{resource="cpu",unit="core"})`, "1000", "2000", "60")
	assert.Equal(t, "http://prom:9090/api/v1/query_range?end=2000&query=sum%28kube_node_status_capacity%7Bresource%3D%22cpu%22%2Cunit%3D%22core%22%7D%29&start=1000&step=60", got)
}

func Test_GetByocObservabilityVcpu(t *testing.T) {
	gin.SetMode(gin.TestMode)

	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "/api/v1/query_range", r.URL.Path)
		assert.Equal(t, observabilityVcpuPromQL, r.URL.Query().Get("query"))
		assert.Equal(t, "1000", r.URL.Query().Get("start"))
		assert.Equal(t, "2000", r.URL.Query().Get("end"))
		assert.Equal(t, "60", r.URL.Query().Get("step"))
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"matrix","result":[]}}`))
	}))
	defer backend.Close()

	configs.Init(structs.ServiceInfo{SelfMonitorEndpoint: backend.URL})

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/external/byoc/orgs/100/byocVcpuPools/observabilityVcpu?start=1000&end=2000&step=60", nil)
	c.Params = gin.Params{{Key: "bizType", Value: "byoc"}}

	GetByocObservabilityVcpu(c)

	assert.Equal(t, http.StatusOK, w.Code)
	assert.Contains(t, w.Body.String(), `"resultType":"matrix"`)
}

func Test_GetByocObservabilityVcpu_MissingParams(t *testing.T) {
	gin.SetMode(gin.TestMode)

	configs.Init(structs.ServiceInfo{SelfMonitorEndpoint: "http://prom:9090"})

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/external/byoc/orgs/100/byocVcpuPools/observabilityVcpu?start=1000&step=60", nil)
	c.Params = gin.Params{{Key: "bizType", Value: "byoc"}}

	GetByocObservabilityVcpu(c)

	assert.Equal(t, errors.ParameterInvalid.GetHttpCode(), w.Code)
	var resp message.Result
	assert.NoError(t, json.Unmarshal(w.Body.Bytes(), &resp))
	assert.Contains(t, resp.Message, "End")
}

func Test_GetByocObservabilityVcpu_DefaultStepWhenMissing(t *testing.T) {
	gin.SetMode(gin.TestMode)

	backend := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		assert.Equal(t, "/api/v1/query_range", r.URL.Path)
		assert.Equal(t, "30s", r.URL.Query().Get("step"))
		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)
		_, _ = w.Write([]byte(`{"status":"success","data":{"resultType":"matrix","result":[]}}`))
	}))
	defer backend.Close()

	configs.Init(structs.ServiceInfo{SelfMonitorEndpoint: backend.URL})

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/external/byoc/orgs/100/byocVcpuPools/observabilityVcpu?start=1000&end=2000", nil)
	c.Params = gin.Params{{Key: "bizType", Value: "byoc"}}

	GetByocObservabilityVcpu(c)

	assert.Equal(t, http.StatusOK, w.Code)
}

func Test_GetByocObservabilityVcpu_RejectNonByocBizType(t *testing.T) {
	gin.SetMode(gin.TestMode)

	configs.Init(structs.ServiceInfo{SelfMonitorEndpoint: "http://prom:9090"})

	w := httptest.NewRecorder()
	c, _ := gin.CreateTestContext(w)
	c.Request = httptest.NewRequest(http.MethodGet, "/api/v1/external/tidbcloud/orgs/100/byocVcpuPools/observabilityVcpu?start=1000&end=2000&step=60", nil)
	c.Params = gin.Params{{Key: "bizType", Value: "tidbcloud"}}

	GetByocObservabilityVcpu(c)

	assert.Equal(t, errors.UnsupportedBizType.GetHttpCode(), w.Code)
}

func Test_GetByocObservabilityVcpu_RouteRegistered(t *testing.T) {
	w := httptest.NewRecorder()
	req, _ := http.NewRequest(http.MethodGet, "/api/v1/external/byoc/orgs/100/byocVcpuPools/observabilityVcpu?start=1&end=2", nil)
	testEngine.ServeHTTP(w, req)

	assert.NotEqual(t, http.StatusNotFound, w.Code, "byoc observability vcpu route should be registered")
}
