package regionalapi

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

	"github.com/tidbcloud/observability/pkg/common/interceptor"

	"github.com/tidbcloud/observability/pkg/common/configs"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"github.com/tidbcloud/observability/pkg/common/structs"

	"github.com/tidbcloud/observability/pkg/common/errors"
	"github.com/tidbcloud/observability/pkg/common/message"

	"github.com/gin-gonic/gin"

	"github.com/stretchr/testify/assert"
)

func TestRecover(t *testing.T) {
	configs.Init(structs.ServiceInfo{
		DefaultOversell: 1,
		MonitorSpec: map[string]structs.MonitorSpec{
			"default": {
				Cpu:            "1",
				Memory:         "200Mi",
				InitialStorage: "40Gi",
				OverSell:       0.25,
				IsDefault:      true,
			},
			"spec1": {
				Cpu:            "2",
				Memory:         "400Mi",
				InitialStorage: "80Gi",
				OverSell:       0.25,
			},
		},
	})

	testrecover := testEngine.Group("/recover")
	testrecover.Use(gin.CustomRecovery(interceptor.Recover))

	testrecover.GET("/panic/", func(context *gin.Context) {
		panic("something wrong")
	})

	testrecover.GET("/ok/", ServiceInfo)

	t.Run("panic", func(t *testing.T) {

		w := httptest.NewRecorder()

		req, _ := http.NewRequest("GET", "/recover/panic/", nil)

		testEngine.ServeHTTP(w, req)
		assert.Equal(t, http.StatusInternalServerError, w.Code)

		res := w.Result()
		defer res.Body.Close()

		data, err := io.ReadAll(res.Body)
		assert.NoError(t, err)

		result := &message.Result{}
		err = json.Unmarshal(data, result)
		assert.NoError(t, err)

		assert.Equal(t, int(errors.UnrecognizedError), result.Code)
		assert.Equal(t, "something wrong", result.Message)
	})
	t.Run("no panic", func(t *testing.T) {
		w := httptest.NewRecorder()

		req, _ := http.NewRequest("GET", "/recover/ok/", nil)
		testEngine.ServeHTTP(w, req)
		assert.Equal(t, http.StatusOK, w.Code)

		res := w.Result()
		defer res.Body.Close()

		data, err := io.ReadAll(res.Body)
		assert.NoError(t, err)

		result := &message.Result{
			Data: &message.GetServiceInfoResp{},
		}
		err = json.Unmarshal(data, result)
		assert.NoError(t, err)

		assert.Equal(t, errors.SUCCESS, result.Code)
		assert.Equal(t, constants.ObservabilityRegionalServer, result.Data.(*message.GetServiceInfoResp).ServiceName)
	})
}
