package httputil

import (
	"context"
	"errors"
	"net/http"
	"testing"

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/require"
)

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

	router := gin.New()
	router.POST("/echo", func(ctx *gin.Context) {
		require.Equal(t, "Bearer token", ctx.GetHeader("Authorization"))
		require.Equal(t, "wsp_1", ctx.GetHeader("X-Workspace-Id"))
		require.Contains(t, ctx.GetHeader("Content-Type"), "application/json")
		var body map[string]string
		require.NoError(t, ctx.ShouldBindJSON(&body))
		ctx.JSON(http.StatusCreated, body)
	})

	response := DoJSON(t, router, http.MethodPost, "/echo", map[string]string{"hello": "world"})
	require.Equal(t, http.StatusCreated, response.Code)
	require.JSONEq(t, `{"hello":"world"}`, response.Body.String())
}

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

	router := gin.New()
	router.POST("/raw", func(ctx *gin.Context) {
		require.Empty(t, ctx.GetHeader("Authorization"))
		require.Equal(t, "custom", ctx.GetHeader("X-Custom"))
		body, err := ctx.GetRawData()
		require.NoError(t, err)
		ctx.String(http.StatusAccepted, string(body))
	})

	headers := http.Header{"X-Custom": []string{"custom"}}
	response := DoRaw(t, router, http.MethodPost, "/raw", headers, []byte("payload"))
	require.Equal(t, http.StatusAccepted, response.Code)
	require.Equal(t, "payload", response.Body.String())
}

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

	require.Empty(t, RouteCounts(nil))
	router := gin.New()
	router.GET("/healthz", func(*gin.Context) {})
	router.POST("/healthz", func(*gin.Context) {})
	require.Equal(t, map[string]int{"GET /healthz": 1, "POST /healthz": 1}, RouteCounts(router))

	blocker := &FakeBlocker{}
	count, err := blocker.BlockServiceEventSubscriptions(context.Background(), "wsp_1", "github", "conn_1")
	require.NoError(t, err)
	require.Equal(t, 1, count)
	require.Equal(t, []BlockCall{{WorkspaceID: "wsp_1", Provider: "github", ConnectionRef: "conn_1"}}, blocker.BlockCalls)

	blocker.UnblockErr = ErrSentinel
	_, err = blocker.UnblockServiceEventSubscriptions(context.Background(), "wsp_1", "github", "conn_1")
	require.True(t, errors.Is(err, ErrSentinel))
	require.Len(t, blocker.UnblockCalls, 1)
}
